neogeo: support for .neo format.

This commit is contained in:
sorgelig
2019-09-09 08:11:10 +08:00
parent a42d9745c8
commit 28d82d1c32
2 changed files with 164 additions and 20 deletions

View File

@@ -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;

View File

@@ -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