diff --git a/file_io.cpp b/file_io.cpp index 133aec4..baaafae 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -1062,7 +1062,11 @@ int ScanDirectory(char* path, int mode, const char *extension, int options, cons de->d_type = DT_DIR; } - if (de->d_type != DT_DIR) continue; + if (strcasecmp(de->d_name + strlen(de->d_name) - 4, ".neo")) + { + if (de->d_type != DT_DIR) continue; + } + if (!strcmp(de->d_name, "..")) { if (!strlen(path)) continue; diff --git a/support/neogeo/loader.cpp b/support/neogeo/loader.cpp index fb4cad8..6bea624 100644 --- a/support/neogeo/loader.cpp +++ b/support/neogeo/loader.cpp @@ -13,6 +13,20 @@ #include "../../osd.h" #include "../../menu.h" +struct NeoFile +{ + uint8_t header1, header2, header3, version; + uint32_t PSize, SSize, MSize, V1Size, V2Size, CSize; + uint32_t Year; + uint32_t Genre; + uint32_t Screenshot; + uint32_t NGH; + uint8_t Name[33]; + uint8_t Manu[17]; + uint8_t Filler[128 + 290]; //fill to 512 + uint8_t Filler2[4096 - 512]; //fill to 4096 +}; + static inline void spr_convert(uint16_t* buf_in, uint16_t* buf_out, uint32_t size) { /* @@ -111,6 +125,7 @@ static void neogeo_osd_progress(const char* name, unsigned int progress) const char* p = strrchr(name, '/'); if (p) p++; else p = name; + if (strlen(p) > 16) p = p + strlen(p) - 16; strcpy(progress_buf, p); char *buf = progress_buf + strlen(progress_buf); @@ -285,7 +300,12 @@ static uint32_t load_crom_to_mem(const char* path, const char* name, uint8_t ind return map_addr - 0x38000000; } -static uint32_t load_rom_to_mem(const char* path, const char* name, uint8_t neo_file_type, uint8_t index, uint32_t offset, uint32_t size, uint32_t expand) +static inline void spr_bswap(uint32_t* buf, uint32_t size) +{ + for (uint32_t i = 0; i < size; i++) buf[i] = (buf[i] & 0xFF0000FF) | ((buf[i] & 0xFF00) << 8) | ((buf[i] & 0xFF0000) >> 8); +} + +static uint32_t load_rom_to_mem(const char* path, const char* name, uint8_t neo_file_type, uint8_t index, uint32_t offset, uint32_t size, uint32_t expand, int swap) { fileTYPE f = {}; static char name_buf[1024]; @@ -347,6 +367,7 @@ static uint32_t load_rom_to_mem(const char* path, const char* name, uint8_t neo_ { memset(loadbuf, 0, partsz); if (partszf) FileReadAdv(&f, loadbuf, partszf); + if (swap) spr_bswap((uint32_t*)loadbuf, partsz / 4); spr_convert_dbl((uint16_t*)loadbuf, (uint16_t*)base, partsz / 2); } else @@ -410,7 +431,7 @@ static void notify_core(uint8_t index, uint32_t size) } static uint32_t crom_sz = 0; -static uint32_t neogeo_tx(const char* path, const char* name, uint8_t neo_file_type, int16_t index, uint32_t offset, uint32_t size, uint32_t expand = 0) +static uint32_t neogeo_tx(const char* path, const char* name, uint8_t neo_file_type, int16_t index, uint32_t offset, uint32_t size, uint32_t expand = 0, int swap = 0) { /* if (index >= 0) neogeo_file_tx(path, name, neo_file_type, index, offset, size); @@ -435,7 +456,7 @@ static uint32_t neogeo_tx(const char* path, const char* name, uint8_t neo_file_t if (index >= 0) { - sz = load_rom_to_mem(path, name, neo_file_type, index, offset, size, expand); + sz = load_rom_to_mem(path, name, neo_file_type, index, offset, size, expand, swap); if (sz) notify_core(index, sz); } @@ -574,6 +595,22 @@ char *neogeo_get_altname(char *path, direntext_t *de) strcpy(full_path, path); strcat(full_path, "/"); strcat(full_path, de->de.d_name); + + char *p = strrchr(de->de.d_name, '.'); + if (p && !strcasecmp(p, ".neo")) + { + static NeoFile hdr; + + fileTYPE f = {}; + if (FileOpen(&f, full_path)) + { + int res = FileReadAdv(&f, &hdr, sizeof(hdr)); + FileClose(&f); + if(res) return (char*)hdr.Name; + } + return NULL; + } + strcat(full_path, "/romset.xml"); if (FileExists(full_path)) @@ -963,6 +1000,99 @@ static int xml_load_files(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, co return true; } +struct NeoQuirk +{ + uint16_t id; + uint8_t hw; + uint8_t cmc; + uint8_t pvc; + uint8_t sma; + uint8_t mir; +}; + +static NeoQuirk neo_quirks[] = { + {0x022, 0, 0, 0, 0, 1 }, // Blue's Journey + {0x052, 1, 0, 0, 0, 0 }, // Super Sidekicks + {0x047, 1, 0, 0, 0, 0 }, // Fatal Fury 2 + {0x006, 2, 0, 0, 0, 0 }, // Riding Hero + {0x263, 0, 1, 0, 0, 0 }, // Metal Slug 4 + {0x253, 0, 1, 0, 2, 0 }, // Garou - Mark of the Wolves + {0x251, 0, 0, 0, 1, 0 }, // King of Fighters 99 + {0x257, 0, 2, 0, 5, 0 }, // King of Fighters 2000 + {0x271, 0, 2, 1, 0, 0 }, // King of Fighters 2003 + {0x266, 0, 2, 0, 0, 0 }, // Matrimelee + {0x256, 0, 1, 0, 4, 0 }, // Metal Slug 3 + {0x268, 0, 0, 1, 0, 0 }, // Metal Slug 5 + {0x269, 0, 2, 1, 0, 0 }, // SNK vs Capcom +}; + +void load_neo(char *path) +{ + static NeoFile hdr; + + fileTYPE f = {}; + if (FileOpen(&f, path)) + { + int res = FileReadAdv(&f, &hdr, sizeof(hdr)); + FileClose(&f); + if(res) + { + static uint32_t hw_type = 0, use_pcm = 0, pvc = 0, sma = 0, cmc = 0, mir = 1; + for (uint32_t i = 0; i < sizeof(neo_quirks) / sizeof(neo_quirks[0]); i++) + { + if (neo_quirks[i].id == hdr.NGH) + { + hw_type = neo_quirks[i].hw; + cmc = neo_quirks[i].cmc; + sma = neo_quirks[i].sma; + pvc = neo_quirks[i].pvc; + mir = !neo_quirks[i].mir; + break; + } + } + + printf("PSize=%d, SSize=%d, MSize=%d, V1Size=%d, V2Size=%d, CSize=%d, Name=%s\n", hdr.PSize, hdr.SSize, hdr.MSize, hdr.V1Size, hdr.V2Size, hdr.CSize, hdr.Name); + char *p = strrchr(path, '/'); + *p++ = 0; + uint32_t off = 4096; + neogeo_tx(path, p, NEO_FILE_RAW, 4, off, hdr.PSize); + off += hdr.PSize; + + neogeo_tx(path, p, NEO_FILE_FIX, 8, off, hdr.SSize); + off += hdr.SSize; + + neogeo_tx(path, p, NEO_FILE_RAW, 9, off, hdr.MSize); + off += hdr.MSize; + + neogeo_tx(path, p, NEO_FILE_RAW, 16, off, hdr.V1Size, mir ? 0 : VROM_SIZE); + off += hdr.V1Size; + + use_pcm = 1; + if (hdr.V2Size) + { + use_pcm = 0; + neogeo_tx(path, p, NEO_FILE_RAW, 48, off, hdr.V2Size, mir ? 0 : VROM_SIZE); + off += hdr.V2Size; + } + + neogeo_tx(path, p, NEO_FILE_SPR, 15, off, hdr.CSize, 0, 1); + + printf("Setting cart special chip (legacy) to %u\n", hw_type); + set_config((hw_type & 3) << 24, 3 << 24); + + printf("Setting CMC chip to %u\n", cmc); + set_config((cmc & 3) << 26, 3 << 26); + + if (pvc) set_config(2 << 20, 0x7 << 20); + else if (sma) set_config(((2 + sma) & 0x7) << 20, 0x7 << 20); + printf("Setting cart prom special chip to %u\n", (set_config(0, 0) >> 20) & 0x7); + + printf("Setting cart to%s use the PCM chip\n", use_pcm ? "" : " not"); + set_config((use_pcm & 1) << 23, 1 << 23); + } + } +} + int neogeo_romset_tx(char* name) { char *romset = strrchr(name, '/'); @@ -985,28 +1115,38 @@ int neogeo_romset_tx(char* name) // Look for the romset's file list in romsets.xml if (!(system_type & 2)) { - sprintf(full_path, "%s/%s/romset.xml", getRootDir(), name); - if (!FileExists(full_path)) + char *p = strrchr(name, '.'); + if (p && !strcasecmp(p, ".neo")) { + printf("Loading neo file.\n"); strcpy(full_path, name); - char *p = strrchr(full_path, '/'); - if (p) *p = 0; - strcat(full_path, "/romsets.xml"); - if (!FileExists(full_path)) sprintf(full_path, "%s/%s/romsets.xml", getRootDir(), HomeDir); + load_neo(full_path); } - printf("xml for %s: %s\n", name, full_path); + else + { + sprintf(full_path, "%s/%s/romset.xml", getRootDir(), name); + if (!FileExists(full_path)) + { + strcpy(full_path, name); + char *p = strrchr(full_path, '/'); + if (p) *p = 0; + strcat(full_path, "/romsets.xml"); + if (!FileExists(full_path)) sprintf(full_path, "%s/%s/romsets.xml", getRootDir(), HomeDir); + } + printf("xml for %s: %s\n", name, full_path); - SAX_Callbacks sax; - SAX_Callbacks_init(&sax); + SAX_Callbacks sax; + SAX_Callbacks_init(&sax); - checked_ok = false; - romsets = 0; - sax.all_event = xml_check_files; - parse_xml(full_path, &sax, name); - if (!checked_ok) return 0; + checked_ok = false; + romsets = 0; + sax.all_event = xml_check_files; + parse_xml(full_path, &sax, name); + if (!checked_ok) return 0; - sax.all_event = xml_load_files; - parse_xml(full_path, &sax, name); + sax.all_event = xml_load_files; + parse_xml(full_path, &sax, name); + } } // Load system ROMs