Update to v084r08 release.

byuu says:

Okay, everything can now load XML again, including board layouts for all
three systems. New is the ability to load external Game Boy layouts (not
really that useful, but it's there.)
I'd like to aim for a v085 release soon. I've included a binary, so I'd
appreciate testing. I had to redo all of the XML mappings for every
system (I like consistency), so basically the following things need to
be tested:
* load one of every type of game for every system (every NES board type,
* every Game Boy MBC type, every SNES chip and layout type.)
* test cheat codes and the cheat database
* test pixel shaders for OpenGL and Direct3D (sepia for the win)
* test anything else for v085 release
This commit is contained in:
Tim Allen 2011-12-31 20:24:58 +11:00
parent f947d84309
commit 1bf9265b7c
34 changed files with 603 additions and 476 deletions

View File

@ -30,9 +30,9 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
info.romsize = 0;
info.ramsize = 0;
BML::Document document(markup);
XML::Document document(markup);
auto &mapperid = document["cartridge"]["mapper"].value;
auto &mapperid = document["cartridge"]["mapper"].data;
if(mapperid == "none" ) info.mapper = Mapper::MBC0;
if(mapperid == "MBC1" ) info.mapper = Mapper::MBC1;
if(mapperid == "MBC2" ) info.mapper = Mapper::MBC2;
@ -42,12 +42,12 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
if(mapperid == "HuC1" ) info.mapper = Mapper::HuC1;
if(mapperid == "HuC3" ) info.mapper = Mapper::HuC3;
info.rtc = document["cartridge"]["rtc"].exists();
info.rumble = document["cartridge"]["rumble"].exists();
info.rtc = document["cartridge"]["rtc"].data == "true";
info.rumble = document["cartridge"]["rumble"].data == "true";
info.romsize = hex(document["cartridge"]["rom"]["size"].value);
info.ramsize = hex(document["cartridge"]["ram"]["size"].value);
info.battery = document["cartridge"]["ram"]["non-volatile"].exists();
info.romsize = hex(document["cartridge"]["rom"]["size"].data);
info.ramsize = hex(document["cartridge"]["ram"]["size"].data);
info.battery = document["cartridge"]["ram"]["battery"].data == "true";
switch(info.mapper) { default:
case Mapper::MBC0: mapper = &mbc0; break;

View File

@ -100,6 +100,16 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
markup.append(
"<?xml version='1.0' encoding='UTF-8'?>\n",
"<cartridge mapper='", info.mapper, "' rtc='", info.rtc, "' rumble='", info.rumble, "'>\n",
" <rom size='0x", hex(romsize), "'/>\n");
if(info.ramsize > 0) markup.append(
" <ram size='0x", hex(info.ramsize), "' battery='", info.battery, "'/>\n");
markup.append(
"</cartridge>\n");
/*
markup.append("cartridge mapper=", info.mapper);
if(info.rtc) markup.append(" rtc");
if(info.rumble) markup.append(" rumble");
@ -109,6 +119,7 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
if(info.ramsize > 0)
markup.append("\t" "ram size=", hex(info.ramsize), info.battery ? " non-volatile\n" : "\n");
*/
}
}

View File

@ -105,345 +105,438 @@ public:
bool has_st018;
};
#define T "\t"
SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
read_header(data, size);
string xml;
markup = "";
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
if(type == TypeBsx) {
markup.append("cartridge");
markup.append("<cartridge/>\n");
return;
}
if(type == TypeSufamiTurbo) {
markup.append("cartridge");
markup.append("<cartridge/>\n");
return;
}
if(type == TypeGameBoy) {
markup.append("cartridge rtc=", gameboy_has_rtc(data, size), "\n");
markup.append("<cartridge rtc='", gameboy_has_rtc(data, size), "'\n");
if(gameboy_ram_size(data, size) > 0) {
markup.append(T "ram size=0x", hex(gameboy_ram_size(data, size)), "\n");
markup.append(" <ram size='0x", hex(gameboy_ram_size(data, size)), "'>\n");
}
markup.append("</cartridge>\n");
return;
}
markup.append("cartridge region=", region == NTSC ? "NTSC\n" : "PAL\n");
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
if(type == TypeSuperGameBoy1Bios) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
markup.append(T "icd2 revision=1\n");
markup.append(T T "map address=00-3f:6000-7fff\n");
markup.append(T T "map address=80-bf:6000-7fff\n");
} else if(type == TypeSuperGameBoy2Bios) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
markup.append(T "icd2 revision=1\n");
markup.append(T T "map address=00-3f:6000-7fff\n");
markup.append(T T "map address=80-bf:6000-7fff\n");
} else if(has_cx4) {
markup.append(T "hitachidsp model=HG51B169 frequency=20000000 firmware=cx4.bin sha256=ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18\n");
markup.append(T T "rom\n");
markup.append(T T T "map mode=linear address=00-7f:8000-ffff\n");
markup.append(T T T "map mode=linear address=80-ff:8000-ffff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:6000-7fff\n");
markup.append(T T T "map address=80-bf:6000-7fff\n");
} else if(has_spc7110) {
markup.append(T "rom\n");
markup.append(T T "map mode=shadow address=00-0f:8000-ffff\n");
markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n");
markup.append(T T "map mode=linear address=c0-cf:0000-ffff\n");
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
" <rom>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <icd2 revision='1'>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" </icd2>\n"
);
markup.append(T "spc7110\n");
markup.append(T T "mcu\n");
markup.append(T T T "map address=d0-ff:0000-ffff offset=0x100000 size=0x", hex(size - 0x100000), "\n");
markup.append(T T "ram size=0x", hex(ram_size), "\n");
markup.append(T T T "map mode=linear address=00:6000-7fff\n");
markup.append(T T T "map mode=linear address=30:6000-7fff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:4800-483f\n");
markup.append(T T T "map address=80-bf:4800-483f\n");
if(has_spc7110rtc) {
markup.append(T T "rtc\n");
markup.append(T T T "map address=00-3f:4840-4842\n");
markup.append(T T T "map address=80-bf:4840-4842\n");
}
markup.append(T T "dcu\n");
markup.append(T T T "map address=50:0000-ffff\n");
} else if(mapper == LoROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
else if(has_cx4) markup.append(
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.bin' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n"
" <rom>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <mmio>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" </mmio>\n"
" </hitachidsp>\n"
);
if(ram_size > 0) {
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n");
} else {
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
markup.append(T T "map mode=linear address=f0-ff:0000-ffff\n");
}
}
} else if(mapper == HiROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=shadow address=00-3f:8000-ffff\n");
markup.append(T T "map mode=linear address=40-7f:0000-ffff\n");
markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n");
markup.append(T T "map mode=linear address=c0-ff:0000-ffff\n");
if(ram_size > 0) {
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
} else {
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
}
}
} else if(mapper == ExLoROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-3f:8000-ffff\n");
markup.append(T T "map mode=linear address=40-7f:0000-ffff\n");
markup.append(T T "map mode=linear address=80-bf:8000-ffff\n");
if(ram_size > 0) {
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
}
} else if(mapper == ExHiROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=shadow address=00-3f:8000-ffff offset=0x400000\n");
markup.append(T T "map mode=linear address=40-7f:0000-ffff offset=0x400000\n");
markup.append(T T "map mode=shadow address=80-bf:8000-ffff offset=0x000000\n");
markup.append(T T "map mode=linear address=c0-ff:0000-ffff offset=0x000000\n");
if(ram_size > 0) {
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
} else {
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
}
}
} else if(mapper == SuperFXROM) {
markup.append(T "superfx revision=2\n");
markup.append(T T "rom\n");
markup.append(T T T "map mode=linear address=00-3f:8000-ffff\n");
markup.append(T T T "map mode=linear address=40-5f:0000-ffff\n");
markup.append(T T T "map mode=linear address=80-bf:8000-ffff\n");
markup.append(T T T "map mode=linear address=c0-df:0000-ffff\n");
markup.append(T T "ram size=0x", hex(ram_size), "\n");
markup.append(T T T "map mode=linear address=00-3f:6000-7fff size=0x2000\n");
markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n");
markup.append(T T T "map mode=linear address=80-bf:6000-7fff size=0x2000\n");
markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:3000-32ff\n");
markup.append(T T T "map address=80-bf:3000-32ff\n");
} else if(mapper == SA1ROM) {
markup.append(T "sa1\n");
markup.append(T T "mcu\n");
markup.append(T T T "rom\n");
markup.append(T T T T "map mode=direct address=00-3f:8000-ffff\n");
markup.append(T T T T "map mode=direct address=80-bf:8000-ffff\n");
markup.append(T T T T "map mode=direct address=c0-ff:0000-ffff\n");
markup.append(T T T "ram\n");
markup.append(T T T T "map mode=direct address=00-3f:6000-7fff\n");
markup.append(T T T T "map mode=direct address=80-bf:6000-7fff\n");
markup.append(T T "iram size=0x800\n");
markup.append(T T T "map mode=linear address=00-3f:3000-37ff\n");
markup.append(T T T "map mode=linear address=80-bf:3000-37ff\n");
markup.append(T T "bwram size=0x", hex(ram_size), "\n");
markup.append(T T T "map mode=linear address=40-4f:0000-ffff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:2200-23ff\n");
markup.append(T T T "map address=80-bf:2200-23ff\n");
} else if(mapper == BSCLoROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-1f:8000-ffff offset=0x000000\n");
markup.append(T T "map mode=linear address=20-3f:8000-ffff offset=0x100000\n");
markup.append(T T "map mode=linear address=80-9f:8000-ffff offset=0x200000\n");
markup.append(T T "map mode=linear address=a0-bf:8000-ffff offset=0x100000\n");
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n");
markup.append(T "bsx\n");
markup.append(T T "slot\n");
markup.append(T T T "map mode=linear address=c0-ef:0000-ffff\n");
} else if(mapper == BSCHiROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=shadow address=00-1f:8000-ffff\n");
markup.append(T T "map mode=linear address=40-5f:0000-ffff\n");
markup.append(T T "map mode=shadow address=80-9f:8000-ffff\n");
markup.append(T T "map mode=linear address=c0-df:0000-ffff\n");
markup.append(T "ram size=0x", hex(ram_size), "\n");
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
markup.append(T "bsx\n");
markup.append(T T "slot\n");
markup.append(T T T "map mode=shadow address=20-3f:8000-ffff\n");
markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n");
markup.append(T T T "map mode=shadow address=a0-bf:8000-ffff\n");
markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n");
} else if(mapper == BSXROM) {
markup.append(T "bsx\n");
markup.append(T T "mcu\n");
markup.append(T T T "map address=00-3f:8000-ffff\n");
markup.append(T T T "map address=80-bf:8000-ffff\n");
markup.append(T T T "map address=40-7f:0000-ffff\n");
markup.append(T T T "map address=c0-ff:0000-ffff\n");
markup.append(T T T "map address=20-3f:6000-7fff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:5000-5fff\n");
markup.append(T T T "map address=80-bf:5000-5fff\n");
} else if(mapper == STROM) {
markup.append(T "rom\n");
markup.append(T T "map mode=linear address=00-1f:8000-ffff\n");
markup.append(T T "map mode=linear address=80-9f:8000-ffff\n");
markup.append(T "sufamiturbo\n");
markup.append(T T "slot id=A\n");
markup.append(T T T "rom\n");
markup.append(T T T T "map mode=linear address=20-3f:8000-ffff\n");
markup.append(T T T T "map mode=linear address=a0-bf:8000-ffff\n");
markup.append(T T T "ram size=0x20000\n");
markup.append(T T T T "map mode=linear address=60-63:8000-ffff\n");
markup.append(T T T T "map mode=linear address=e0-e3:8000-ffff\n");
markup.append(T T "slot id=B\n");
markup.append(T T T "rom\n");
markup.append(T T T T "map mode=linear address=40-5f:8000-ffff\n");
markup.append(T T T T "map mode=linear address=c0-df:8000-ffff\n");
markup.append(T T T "ram size=0x20000\n");
markup.append(T T T T "map mode=linear address=70-73:8000-ffff\n");
markup.append(T T T T "map mode=linear address=f0-f3:8000-ffff\n");
else if(has_spc7110) {
markup.append(
" <rom>\n"
" <map mode='shadow' address='00-0f:8000-ffff'/>\n"
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
" <map mode='linear' address='c0-cf:0000-ffff'/>\n"
" </rom>\n"
" <spc7110>\n"
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='00:6000-7fff'/>\n"
" <map mode='linear' address='30:6000-7fff'/>\n"
" </ram>\n"
" <mmio>\n"
" <map address='00-3f:4800-483f'/>\n"
" <map address='80-bf:4800-483f'/>\n"
" </mmio>\n"
" <mcu>\n"
" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n"
" </mcu>\n"
" <dcu>\n"
" <map address='50:0000-ffff'/>\n"
" </dcu>\n"
);
if(has_spc7110rtc) markup.append(
" <rtc>\n"
" <map address='00-3f:4840-4842'/>\n"
" <map address='80-bf:4840-4842'/>\n"
" </rtc>\n"
);
markup.append(
" </spc7110>\n"
);
}
if(has_srtc) {
markup.append(T "srtc\n");
markup.append(T T "map address=00-3f:2800-2801\n");
markup.append(T T "map address=80-bf:2800-2801\n");
else if(mapper == LoROM) {
markup.append(
" <rom>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
);
if(ram_size > 0) markup.append(
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
" <map mode='linear' address='70-7f:", range, "'/>\n"
" <map mode='linear' address='f0-ff:", range, "'/>\n"
" </ram>\n"
);
}
if(has_sdd1) {
markup.append(T "sdd1\n");
markup.append(T T "mcu\n");
markup.append(T T T "map address=c0-ff:0000-ffff\n");
markup.append(T T "mmio\n");
markup.append(T T T "map address=00-3f:4800-4807\n");
markup.append(T T T "map address=80-bf:4800-4807\n");
else if(mapper == HiROM) {
markup.append(
" <rom>\n"
" <map mode='shadow' address='00-3f:8000-ffff'/>\n"
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
" <map mode='linear' address='c0-ff:0000-ffff'/>\n"
" </rom>\n"
);
if(ram_size > 0) markup.append(
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
" <map mode='linear' address='70-7f:", range, "'/>\n"
" </ram>\n"
);
}
else if(mapper == ExLoROM) {
markup.append(
" <rom>\n"
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
" </rom>\n"
);
if(ram_size > 0) markup.append(
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
" </ram>\n"
);
}
else if(mapper == ExHiROM) {
markup.append(
" <rom>\n"
" <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n"
" <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n"
" <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n"
" <map mode='linear' address='c0-ff:0000-ffff' offset='0x000000'/>\n"
" </rom>\n"
);
if(ram_size > 0) markup.append(
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
" <map mode='linear' address='70-7f:", range, "'/>\n"
" </ram>\n"
);
}
else if(mapper == SuperFXROM) markup.append(
" <superfx revision='2'>\n"
" <rom>\n"
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
" </rom>\n"
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n"
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
" <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n"
" <map mode='linear' address='e0-ff:0000-ffff'/>\n"
" </ram>\n"
" <mmio>\n"
" <map address='00-3f:3000-32ff'/>\n"
" <map address='80-bf:3000-32ff'/>\n"
" </mmio>\n"
" </superfx>\n"
);
else if(mapper == SA1ROM) markup.append(
" <sa1>\n"
" <mcu>\n"
" <rom>\n"
" <map mode='direct' address='00-3f:8000-ffff'/>\n"
" <map mode='direct' address='80-bf:8000-ffff'/>\n"
" <map mode='direct' address='c0-ff:0000-ffff'/>\n"
" </rom>\n"
" <ram>\n"
" <map mode='direct' address='00-3f:6000-7fff'/>\n"
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
" </ram>\n"
" </mcu>\n"
" <iram size='0x800'>\n"
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
" </iram>\n"
" <bwram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='40-4f:0000-ffff'/>\n"
" </bwram>\n"
" <mmio>\n"
" <map address='00-3f:2200-23ff'/>\n"
" <map address='80-bf:2200-23ff'/>\n"
" </mmio>\n"
" </sa1>\n"
);
else if(mapper == BSCLoROM) markup.append(
" <rom>\n"
" <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n"
" <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n"
" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n"
" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n"
" </rom>\n"
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
" <map mode='linear' address='f0-ff:0000-7fff'/>\n"
" </ram>\n"
" <bsx>\n"
" <slot>\n"
" <map mode='linear' address='c0-ef:0000-ffff'/>\n"
" </slot>\n"
" </bsx>\n"
);
else if(mapper == BSCHiROM) markup.append(
" <rom>\n"
" <map mode='shadow' address='00-1f:8000-ffff'/>\n"
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
" <map mode='shadow' address='80-9f:8000-ffff'/>\n"
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
" </rom>\n"
" <ram size='0x", hex(ram_size), "'>\n"
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
" </ram>\n"
" <bsx>\n"
" <slot>\n"
" <map mode='shadow' address='20-3f:8000-ffff'/>\n"
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
" <map mode='shadow' address='a0-bf:8000-ffff'/>\n"
" <map mode='linear' address='e0-ff:0000-ffff'/>\n"
" </slot>\n"
" </bsx>\n"
);
else if(mapper == BSXROM) markup.append(
" <bsx>\n"
" <mcu>\n"
" <map address='00-3f:8000-ffff'/>\n"
" <map address='80-bf:8000-ffff'/>\n"
" <map address='40-7f:0000-ffff'/>\n"
" <map address='c0-ff:0000-ffff'/>\n"
" <map address='20-3f:6000-7fff'/>\n"
" </mcu>\n"
" <mmio>\n"
" <map address='00-3f:5000-5fff'/>\n"
" <map address='80-bf:5000-5fff'/>\n"
" </mmio>\n"
" </bsx>\n"
);
else if(mapper == STROM) markup.append(
" <rom>\n"
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
" </rom>\n"
" <sufamiturbo>\n"
" <slot id='A'>\n"
" <rom>\n"
" <map mode='linear' address='20-3f:8000-ffff'/>\n"
" <map mode='linear' address='a0-bf:8000-ffff'/>\n"
" </rom>\n"
" <ram size='0x20000'>\n"
" <map mode='linear' address='60-63:8000-ffff'/>\n"
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
" </ram>\n"
" </slot>\n"
" <slot id='B'>\n"
" <rom>\n"
" <map mode='linear' address='40-5f:8000-ffff'/>\n"
" <map mode='linear' address='c0-df:8000-ffff'/>\n"
" </rom>\n"
" <ram size='0x20000'>\n"
" <map mode='linear' address='70-73:8000-ffff'/>\n"
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
" </ram>\n"
" </slot>\n"
" </sufamiturbo>\n"
);
if(has_srtc) markup.append(
" <srtc>\n"
" <map address='00-3f:2800-2801'/>\n"
" <map address='80-bf:2800-2801'/>\n"
" </srtc>\n"
);
if(has_sdd1) markup.append(
" <sdd1>\n"
" <mcu>\n"
" <map address='c0-ff:0000-ffff'/>\n"
" </mcu>\n"
" <mmio>\n"
" <map address='00-3f:4800-4807'/>\n"
" <map address='80-bf:4800-4807'/>\n"
" </mmio>\n"
" </sdd1>\n"
);
if(has_obc1) markup.append(
" <obc1>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" </obc1>\n"
);
if(has_dsp1) {
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp1b.bin sha256=4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c\n");
if(dsp1_mapper == DSP1LoROM1MB) {
markup.append(T T "dr\n");
markup.append(T T T "map address=20-3f:8000-bfff\n");
markup.append(T T T "map address=a0-bf:8000-bfff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=20-3f:c000-ffff\n");
markup.append(T T T "map address=a0-bf:c000-ffff\n");
} else if(dsp1_mapper == DSP1LoROM2MB) {
markup.append(T T "dr\n");
markup.append(T T T "map address=60-6f:0000-3fff\n");
markup.append(T T T "map address=e0-ef:0000-3fff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=60-6f:4000-7fff\n");
markup.append(T T T "map address=e0-ef:4000-7fff\n");
} else if(dsp1_mapper == DSP1HiROM) {
markup.append(T T "dr\n");
markup.append(T T T "map address=00-1f:6000-6fff\n");
markup.append(T T T "map address=80-9f:6000-6fff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=00-1f:7000-7fff\n");
markup.append(T T T "map address=80-9f:7000-7fff\n");
}
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n");
if(dsp1_mapper == DSP1LoROM1MB) markup.append(
" <dr>\n"
" <map address='20-3f:8000-bfff'/>\n"
" <map address='a0-bf:8000-bfff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='20-3f:c000-ffff'/>\n"
" <map address='a0-bf:c000-ffff'/>\n"
" </sr>\n"
);
if(dsp1_mapper == DSP1LoROM2MB) markup.append(
" <dr>\n"
" <map address='60-6f:0000-3fff'/>\n"
" <map address='e0-ef:0000-3fff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='60-6f:4000-7fff'/>\n"
" <map address='e0-ef:4000-7fff'/>\n"
" </sr>\n"
);
if(dsp1_mapper == DSP1HiROM) markup.append(
" <dr>\n"
" <map address='00-1f:6000-6fff'/>\n"
" <map address='80-9f:6000-6fff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='00-1f:7000-7fff'/>\n"
" <map address='80-9f:7000-7fff'/>\n"
" </sr>\n"
);
markup.append(" </necdsp>\n");
}
if(has_dsp2) {
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp2.bin sha256=5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1\n");
markup.append(T T "dr\n");
markup.append(T T T "map address=20-3f:8000-bfff\n");
markup.append(T T T "map address=a0-bf:8000-bfff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=20-3f:c000-ffff\n");
markup.append(T T T "map address=a0-bf:c000-ffff\n");
}
if(has_dsp2) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n"
" <dr>\n"
" <map address='20-3f:8000-bfff'/>\n"
" <map address='a0-bf:8000-bfff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='20-3f:c000-ffff'/>\n"
" <map address='a0-bf:c000-ffff'/>\n"
" </sr>\n"
" </necdsp>\n"
);
if(has_dsp3) {
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp3.bin sha256=2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90\n");
markup.append(T T "dr\n");
markup.append(T T T "map address=20-3f:8000-bfff\n");
markup.append(T T T "map address=a0-bf:8000-bfff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=20-3f:c000-ffff\n");
markup.append(T T T "map address=a0-bf:c000-ffff\n");
}
if(has_dsp3) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n"
" <dr>\n"
" <map address='20-3f:8000-bfff'/>\n"
" <map address='a0-bf:8000-bfff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='20-3f:c000-ffff'/>\n"
" <map address='a0-bf:c000-ffff'/>\n"
" </sr>\n"
" </necdsp>\n"
);
if(has_dsp4) {
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp4.bin sha256=63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a\n");
markup.append(T T "dr\n");
markup.append(T T T "map address=30-3f:8000-bfff\n");
markup.append(T T T "map address=b0-bf:8000-bfff\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=30-3f:c000-ffff\n");
markup.append(T T T "map address=b0-bf:c000-ffff\n");
}
if(has_dsp4) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n"
" <dr>\n"
" <map address='30-3f:8000-bfff'/>\n"
" <map address='b0-bf:8000-bfff'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='30-3f:c000-ffff'/>\n"
" <map address='b0-bf:c000-ffff'/>\n"
" </sr>\n"
" </necdsp>\n"
);
if(has_obc1) {
markup.append(T "obc1\n");
markup.append(T T "map address=00-3f:6000-7fff\n");
markup.append(T T "map address=80-bf:6000-7fff\n");
}
if(has_st010) markup.append(
" <necdsp model='uPD96050' frequency='10000000' firmware='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n"
" <dr>\n"
" <map address='60:0000'/>\n"
" <map address='e0:0000'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='60:0001'/>\n"
" <map address='e0:0001'/>\n"
" </sr>\n"
" <dp>\n"
" <map address='68-6f:0000-0fff'/>\n"
" <map address='e8-ef:0000-0fff'/>\n"
" </dp>\n"
" </necdsp>\n"
);
if(has_st010) {
markup.append(T "necdsp model=uPD96050 frequency=10000000 firmware=st0010.bin sha256=55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e\n");
markup.append(T T "dr\n");
markup.append(T T T "map address=60:0000\n");
markup.append(T T T "map address=e0:0000\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=60:0001\n");
markup.append(T T T "map address=e0:0001\n");
markup.append(T T "dp\n");
markup.append(T T T "map address=68-6f:0000-0fff\n");
markup.append(T T T "map address=e8-ef:0000-0fff\n");
}
if(has_st011) markup.append(
" <necdsp model='uPD96050' frequency='15000000' firmware='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n"
" <dr>\n"
" <map address='60:0000'/>\n"
" <map address='e0:0000'/>\n"
" </dr>\n"
" <sr>\n"
" <map address='60:0001'/>\n"
" <map address='e0:0001'/>\n"
" </sr>\n"
" <dp>\n"
" <map address='68-6f:0000-0fff'/>\n"
" <map address='e8-ef:0000-0fff'/>\n"
" </dp>\n"
" </necdsp>\n"
);
if(has_st011) {
markup.append(T "necdsp model=uPD96050 frequency=15000000 firmware=st0011.bin sha256=651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e\n");
markup.append(T T "dr\n");
markup.append(T T T "map address=60:0000\n");
markup.append(T T T "map address=e0:0000\n");
markup.append(T T "sr\n");
markup.append(T T T "map address=60:0001\n");
markup.append(T T T "map address=e0:0001\n");
markup.append(T T "dp\n");
markup.append(T T T "map address=68-6f:0000-0fff\n");
markup.append(T T T "map address=e8-ef:0000-0fff\n");
}
if(has_st018) markup.append(
" <setarisc firmware='ST-0018'>\n"
" <map address='00-3f:3800-38ff'/>\n"
" <map address='80-bf:3800-38ff'/>\n"
" </setarisc>\n"
);
if(has_st018) {
markup.append(T "setarisc firmware=ST-0018\n");
markup.append(T T "map address=00-3f:3800-38ff\n");
markup.append(T T "map address=80-bf:3800-38ff\n");
}
markup.append("</cartridge>\n");
}
#undef T
void SnesCartridge::read_header(const uint8_t *data, unsigned size) {
type = TypeUnknown;
mapper = LoROM;

View File

@ -12,6 +12,10 @@ struct Node {
bool attribute;
array<Node*> children;
inline bool exists() const {
return !name.empty();
}
inline bool isName(char c) const {
if(c >= 'A' && c <= 'Z') return true;
if(c >= 'a' && c <= 'z') return true;

View File

@ -111,7 +111,7 @@ void serialize(serializer &s) {
s.integer(irq_latch);
}
BandaiFCG(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
BandaiFCG(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
}
};

View File

@ -86,14 +86,14 @@ void Board::serialize(serializer &s) {
if(chrram.size) s.array(chrram.data, chrram.size);
}
Board::Board(BML::Node &board, const uint8_t *data, unsigned size) {
information.type = board["type"].value;
information.battery = board["prg"]["battery"].value;
Board::Board(XML::Node &board, const uint8_t *data, unsigned size) {
information.type = board["type"].data;
information.battery = board["prg"]["battery"].data == "true";
prgrom.size = decimal(board["prg"]["rom"].value);
prgram.size = decimal(board["prg"]["ram"].value);
chrrom.size = decimal(board["chr"]["rom"].value);
chrram.size = decimal(board["chr"]["ram"].value);
prgrom.size = hex(board["prg"]["rom"].data);
prgram.size = hex(board["prg"]["ram"].data);
chrrom.size = hex(board["chr"]["rom"].data);
chrram.size = hex(board["chr"]["ram"].data);
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
if(prgram.size) prgram.data = new uint8[prgram.size]();
@ -111,9 +111,9 @@ Board::~Board() {
}
Board* Board::load(const string &markup, const uint8_t *data, unsigned size) {
BML::Document document(markup);
XML::Document document(markup);
auto &board = document["cartridge"]["board"];
string type = board["type"].value;
string type = board["type"].data;
if(type == "BANDAI-FCG") return new BandaiFCG(board, data, size);

View File

@ -31,7 +31,7 @@ struct Board {
virtual void reset();
virtual void serialize(serializer&);
Board(BML::Node &board, const uint8_t *data, unsigned size);
Board(XML::Node &board, const uint8_t *data, unsigned size);
virtual ~Board();
static Board* load(const string &markup, const uint8_t *data, unsigned size);

View File

@ -34,7 +34,7 @@ void serialize(serializer &s) {
vrc1.serialize(s);
}
KonamiVRC1(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) {
KonamiVRC1(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) {
}
};

View File

@ -49,9 +49,9 @@ void serialize(serializer &s) {
vrc2.serialize(s);
}
KonamiVRC2(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].value);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].value);
KonamiVRC2(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
}
};

View File

@ -50,8 +50,8 @@ void serialize(serializer &s) {
vrc3.serialize(s);
}
KonamiVRC3(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc3(*this) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
KonamiVRC3(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc3(*this) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -53,9 +53,9 @@ void serialize(serializer &s) {
vrc4.serialize(s);
}
KonamiVRC4(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc4(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].value);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].value);
KonamiVRC4(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc4(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
}
};

View File

@ -36,7 +36,7 @@ void main() { vrc6.main(); }
void power() { vrc6.power(); }
void reset() { vrc6.reset(); }
KonamiVRC6(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc6(*this) {
KonamiVRC6(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc6(*this) {
}
};

View File

@ -41,7 +41,7 @@ void serialize(serializer &s) {
vrc7.serialize(s);
}
KonamiVRC7(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc7(*this) {
KonamiVRC7(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc7(*this) {
}
};

View File

@ -45,7 +45,7 @@ void serialize(serializer &s) {
s.integer(mirror_select);
}
NES_AxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_AxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
}
};

View File

@ -45,8 +45,8 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_BNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
NES_BNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -47,8 +47,8 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_CNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
NES_CNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -46,7 +46,7 @@ void serialize(serializer &s) {
mmc5.serialize(s);
}
NES_ExROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc5(*this) {
NES_ExROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc5(*this) {
revision = Revision::ELROM;
}

View File

@ -84,7 +84,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_FxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_FxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
revision = Revision::FKROM;
}

View File

@ -54,8 +54,8 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_GxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
NES_GxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -42,7 +42,7 @@ void serialize(serializer &s) {
mmc6.serialize(s);
}
NES_HKROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) {
NES_HKROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) {
}
};

View File

@ -36,8 +36,8 @@ void serialize(serializer &s) {
Board::serialize(s);
}
NES_NROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
NES_NROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -90,7 +90,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_PxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_PxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
revision = Revision::PNROM;
}

View File

@ -94,7 +94,7 @@ void serialize(serializer &s) {
mmc1.serialize(s);
}
NES_SxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
NES_SxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
revision = Revision::SXROM;
}

View File

@ -60,7 +60,7 @@ void serialize(serializer &s) {
mmc3.serialize(s);
}
NES_TxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
NES_TxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
revision = Revision::TLROM;
}

View File

@ -48,8 +48,8 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_UxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
NES_UxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@ -220,7 +220,7 @@ void serialize(serializer &s) {
pulse[2].serialize(s);
}
Sunsoft5B(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
Sunsoft5B(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
}
};

View File

@ -16,135 +16,142 @@ static string iNES(const uint8_t *data, unsigned size) {
//print("iNES mapper: ", mapper, "\n");
output.append("cartridge\n");
output.append("<?xml version='1.0' encoding='UTF-8'?>\n");
output.append("<cartridge>\n");
switch(mapper) {
default:
output.append("\tboard type:NES-NROM-256\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='NES-NROM-256'>\n");
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
break;
case 1:
output.append("\tboard type:NES-SXROM\n");
output.append("\t\tchip type:MMC1B2\n");
output.append(" <board type='NES-SXROM'>\n");
output.append(" <chip type='MMC1B2'/>\n");
prgram = 8192;
break;
case 2:
output.append("\tboard type:NES-UOROM\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='NES-UOROM'>\n");
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
break;
case 3:
output.append("\tboard type:NES-CNROM\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='NES-CNROM'>\n");
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
break;
case 4:
//MMC3
output.append("\tboard type:NES-TLROM\n");
output.append("\t\tchip type:MMC3B\n");
output.append(" <board type='NES-TLROM'>\n");
output.append(" <chip type='MMC3B'/>\n");
prgram = 8192;
//MMC6
//output.append("\tboard type:NES-HKROM\n");
//output.append("\t\tchip type:MMC6\n");
//output.append(" <board type='NES-HKROM'>\n");
//output.append(" <chip type='MMC6'/>\n");
//prgram = 1024;
break;
case 5:
output.append("\tboard type:NES-ELROM\n");
output.append("\t\tchip type:MMC5\n");
output.append(" <board type='NES-ELROM'>\n");
output.append(" <chip type='MMC5'/>\n");
prgram = 65536;
break;
case 7:
output.append("\tboard type:NES-AOROM\n");
output.append(" <board type='NES-AOROM'>\n");
break;
case 9:
output.append("\tboard type:NES-PNROM\n");
output.append("\t\tchip type:MMC2\n");
output.append(" <board type='NES-PNROM'>\n");
output.append(" <chip type='MMC2'/>\n");
prgram = 8192;
break;
case 10:
output.append("\tboard type:NES-FKROM\n");
output.append("\t\tchip type:MMC4\n");
output.append(" <board type='NES-FKROM'>\n");
output.append(" <chip type='MMC4'/>\n");
prgram = 8192;
break;
case 16:
output.append("\tboard type:BANDAI-FCG\n");
output.append("\t\tchip type:LZ93D50\n");
output.append(" <board type='BANDAI-FCG'>\n");
output.append(" <chip type='LZ93D50'/>\n");
break;
case 21:
case 23:
case 25:
//VRC4
output.append("\tboard type:KONAMI-VRC-4\n");
output.append("\t\tchip type:VRC4\n");
output.append("\t\t\tpinout a0=1 a1=0\n");
output.append(" <board type='KONAMI-VRC-4'>\n");
output.append(" <chip type='VRC4'>\n");
output.append(" <pinout a0='1' a1='0'/>\n");
output.append(" </chip>\n");
prgram = 8192;
break;
case 22:
//VRC2
output.append("\tboard type:KONAMI-VRC-2\n");
output.append("\t\tchip type:VRC2\n");
output.append("\t\t\tpinout a0=0 a1=1\n");
output.append(" <board type='KONAMI-VRC-2'>\n");
output.append(" <chip type='VRC2'>\n");
output.append(" <pinout a0='0' a1='1'/>\n");
output.append(" </chip>\n");
break;
case 24:
output.append("\tboard type:KONAMI-VRC-6\n");
output.append("\t\tchip type:VRC6\n");
output.append(" <board type='KONAMI-VRC-6'>\n");
output.append(" <chip type='VRC6'/>\n");
break;
case 26:
output.append("\tboard type:KONAMI-VRC-6\n");
output.append("\t\tchip type:VRC6\n");
output.append(" <board type='KONAMI-VRC-6'>\n");
output.append(" <chip type='VRC6'/>\n");
prgram = 8192;
break;
case 34:
output.append("\tboard type:NES-BNROM\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='NES-BNROM'>\n");
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
break;
case 66:
output.append("\tboard type:NES-GNROM\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='NES-GNROM'>\n");
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
break;
case 69:
output.append("\tboard type:SUNSOFT-5B\n");
output.append("\t\tchip type:5B\n");
output.append(" <board type='SUNSOFT-5B'>\n");
output.append(" <chip type='5B'/>\n");
prgram = 8192;
break;
case 73:
output.append("\tboard type:KONAMI-VRC-3\n");
output.append("\t\tchip type:VRC3\n");
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
output.append(" <board type='KONAMI-VRC-3'>\n");
output.append(" <chip type='VRC3'/>\n");
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
prgram = 8192;
break;
case 75:
output.append("\tboard type:KONAMI-VRC-1\n");
output.append("\t\tchip type:VRC1\n");
output.append(" <board type='KONAMI-VRC-1'>\n");
output.append(" <chip type='VRC1'/>\n");
break;
case 85:
output.append("\tboard type:KONAMI-VRC-7\n");
output.append("\t\tchip type:VRC7\n");
output.append(" <board type='KONAMI-VRC-7'>\n");
output.append(" <chip type='VRC7'/>\n");
prgram = 8192;
break;
}
output.append("\t\tprg rom=", prgrom, " ram=", prgram, "\n");
output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n");
output.append(
" <prg rom='0x", hex(prgrom), "' ram='0x", hex(prgram), "'/>\n"
" <chr rom='0x", hex(chrrom), "' ram='0x", hex(chrram), "'/>\n"
" </board>\n"
"</cartridge>\n"
);
//print(output, "\n");
print(output, "\n");
return output;
}

View File

@ -91,26 +91,26 @@ struct Cartridge : property<Cartridge> {
private:
void parse_markup(const char*);
unsigned parse_markup_integer(cstring&);
void parse_markup_map(Mapping&, BML::Node&);
unsigned parse_markup_integer(string&);
void parse_markup_map(Mapping&, XML::Node&);
void parse_markup_rom(BML::Node&);
void parse_markup_ram(BML::Node&);
void parse_markup_nss(BML::Node&);
void parse_markup_icd2(BML::Node&);
void parse_markup_superfx(BML::Node&);
void parse_markup_sa1(BML::Node&);
void parse_markup_necdsp(BML::Node&);
void parse_markup_hitachidsp(BML::Node&);
void parse_markup_bsx(BML::Node&);
void parse_markup_sufamiturbo(BML::Node&);
void parse_markup_srtc(BML::Node&);
void parse_markup_sdd1(BML::Node&);
void parse_markup_spc7110(BML::Node&);
void parse_markup_obc1(BML::Node&);
void parse_markup_setarisc(BML::Node&);
void parse_markup_msu1(BML::Node&);
void parse_markup_link(BML::Node&);
void parse_markup_rom(XML::Node&);
void parse_markup_ram(XML::Node&);
void parse_markup_nss(XML::Node&);
void parse_markup_icd2(XML::Node&);
void parse_markup_superfx(XML::Node&);
void parse_markup_sa1(XML::Node&);
void parse_markup_necdsp(XML::Node&);
void parse_markup_hitachidsp(XML::Node&);
void parse_markup_bsx(XML::Node&);
void parse_markup_sufamiturbo(XML::Node&);
void parse_markup_srtc(XML::Node&);
void parse_markup_sdd1(XML::Node&);
void parse_markup_spc7110(XML::Node&);
void parse_markup_obc1(XML::Node&);
void parse_markup_setarisc(XML::Node&);
void parse_markup_msu1(XML::Node&);
void parse_markup_link(XML::Node&);
};
extern Cartridge cartridge;

View File

@ -4,9 +4,9 @@ void Cartridge::parse_markup(const char *markup) {
mapping.reset();
information.nss.setting.reset();
BML::Document document(markup);
XML::Document document(markup);
auto &cartridge = document["cartridge"];
region = cartridge["region"].value != "PAL" ? Region::NTSC : Region::PAL;
region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL;
parse_markup_rom(cartridge["rom"]);
parse_markup_ram(cartridge["ram"]);
@ -29,22 +29,22 @@ void Cartridge::parse_markup(const char *markup) {
//
unsigned Cartridge::parse_markup_integer(cstring &data) {
unsigned Cartridge::parse_markup_integer(string &data) {
if(strbegin(data, "0x")) return hex(data);
return decimal(data);
}
void Cartridge::parse_markup_map(Mapping &m, BML::Node &map) {
m.offset = parse_markup_integer(map["offset"].value);
m.size = parse_markup_integer(map["size"].value);
void Cartridge::parse_markup_map(Mapping &m, XML::Node &map) {
m.offset = parse_markup_integer(map["offset"].data);
m.size = parse_markup_integer(map["size"].data);
string data = map["mode"].value;
string data = map["mode"].data;
if(data == "direct") m.mode = Bus::MapMode::Direct;
if(data == "linear") m.mode = Bus::MapMode::Linear;
if(data == "shadow") m.mode = Bus::MapMode::Shadow;
lstring part;
part.split(":", map["address"].value);
part.split(":", map["address"].data);
if(part.size() != 2) return;
lstring subpart;
@ -69,7 +69,7 @@ void Cartridge::parse_markup_map(Mapping &m, BML::Node &map) {
//
void Cartridge::parse_markup_rom(BML::Node &root) {
void Cartridge::parse_markup_rom(XML::Node &root) {
if(root.exists() == false) return;
for(auto &node : root) {
if(node.name != "map") continue;
@ -80,9 +80,9 @@ void Cartridge::parse_markup_rom(BML::Node &root) {
}
}
void Cartridge::parse_markup_ram(BML::Node &root) {
void Cartridge::parse_markup_ram(XML::Node &root) {
if(root.exists() == false) return;
ram_size = parse_markup_integer(root["size"].value);
ram_size = parse_markup_integer(root["size"].data);
for(auto &node : root) {
Mapping m(ram);
parse_markup_map(m, node);
@ -91,7 +91,7 @@ void Cartridge::parse_markup_ram(BML::Node &root) {
}
}
void Cartridge::parse_markup_nss(BML::Node &root) {
void Cartridge::parse_markup_nss(XML::Node &root) {
if(root.exists() == false) return;
has_nss_dip = true;
for(auto &node : root) {
@ -100,21 +100,21 @@ void Cartridge::parse_markup_nss(BML::Node &root) {
if(number >= 16) break; //more than 16 DIP switches is not physically possible
information.nss.option[number].reset();
information.nss.setting[number] = node["name"].value;
information.nss.setting[number] = node["name"].data;
for(auto &leaf : node) {
if(leaf.name != "option") continue;
string name = leaf["name"].value;
unsigned value = parse_markup_integer(leaf["value"].value);
string name = leaf["name"].data;
unsigned value = parse_markup_integer(leaf["value"].data);
information.nss.option[number].append({ hex<4>(value), ":", name });
}
}
}
void Cartridge::parse_markup_icd2(BML::Node &root) {
void Cartridge::parse_markup_icd2(XML::Node &root) {
if(root.exists() == false) return;
if(mode != Mode::SuperGameBoy) return;
icd2.revision = max(1, parse_markup_integer(root["revision"].value));
icd2.revision = max(1, parse_markup_integer(root["revision"].data));
for(auto &node : root) {
if(node.name != "map") continue;
@ -124,7 +124,7 @@ void Cartridge::parse_markup_icd2(BML::Node &root) {
}
}
void Cartridge::parse_markup_superfx(BML::Node &root) {
void Cartridge::parse_markup_superfx(XML::Node &root) {
if(root.exists() == false) return;
has_superfx = true;
@ -140,7 +140,7 @@ void Cartridge::parse_markup_superfx(BML::Node &root) {
if(node.name == "ram") {
for(auto &leaf : node) {
if(leaf.name == "size") {
ram_size = parse_markup_integer(leaf.value);
ram_size = parse_markup_integer(leaf.data);
continue;
}
if(leaf.name != "map") continue;
@ -161,7 +161,7 @@ void Cartridge::parse_markup_superfx(BML::Node &root) {
}
}
void Cartridge::parse_markup_sa1(BML::Node &root) {
void Cartridge::parse_markup_sa1(XML::Node &root) {
if(root.exists() == false) return;
has_sa1 = true;
@ -193,7 +193,7 @@ void Cartridge::parse_markup_sa1(BML::Node &root) {
mapping.append(m);
}
ram_size = parse_markup_integer(bwram["size"].value);
ram_size = parse_markup_integer(bwram["size"].data);
for(auto &node : bwram) {
if(node.name != "map") continue;
Mapping m(sa1.cpubwram);
@ -210,21 +210,21 @@ void Cartridge::parse_markup_sa1(BML::Node &root) {
}
}
void Cartridge::parse_markup_necdsp(BML::Node &root) {
void Cartridge::parse_markup_necdsp(XML::Node &root) {
if(root.exists() == false) return;
has_necdsp = true;
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
necdsp.frequency = parse_markup_integer(root["frequency"].value);
necdsp.frequency = parse_markup_integer(root["frequency"].data);
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
necdsp.revision
= root["model"].value == "uPD7725" ? NECDSP::Revision::uPD7725
: root["model"].value == "uPD96050" ? NECDSP::Revision::uPD96050
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
: NECDSP::Revision::uPD7725;
string firmware = root["firmware"].value;
string sha256 = root["sha256"].value;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
string path = { dir(interface->path(Slot::Base, ".dsp")), firmware };
unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384);
@ -280,16 +280,16 @@ void Cartridge::parse_markup_necdsp(BML::Node &root) {
}
}
void Cartridge::parse_markup_hitachidsp(BML::Node &root) {
void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
if(root.exists() == false) return;
has_hitachidsp = true;
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
hitachidsp.frequency = parse_markup_integer(root["frequency"].value);
hitachidsp.frequency = parse_markup_integer(root["frequency"].data);
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
string firmware = root["firmware"].value;
string sha256 = root["sha256"].value;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
string path = { dir(interface->path(Slot::Base, ".dsp")), firmware };
file fp;
@ -334,7 +334,7 @@ void Cartridge::parse_markup_hitachidsp(BML::Node &root) {
}
}
void Cartridge::parse_markup_bsx(BML::Node &root) {
void Cartridge::parse_markup_bsx(XML::Node &root) {
if(root.exists() == false) return;
if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return;
@ -360,13 +360,13 @@ void Cartridge::parse_markup_bsx(BML::Node &root) {
}
}
void Cartridge::parse_markup_sufamiturbo(BML::Node &root) {
void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
if(root.exists() == false) return;
if(mode != Mode::SufamiTurbo) return;
for(auto &slot : root) {
if(slot.name != "slot") continue;
bool slotid = slot["id"].value == "A" ? 0 : slot["id"].value == "B" ? 1 : 0;
bool slotid = slot["id"].data == "A" ? 0 : slot["id"].data == "B" ? 1 : 0;
for(auto &node : slot) {
if(node.name == "rom") {
for(auto &leaf : node) {
@ -379,7 +379,7 @@ void Cartridge::parse_markup_sufamiturbo(BML::Node &root) {
}
}
if(node.name == "ram") {
unsigned ram_size = parse_markup_integer(node["size"].value);
unsigned ram_size = parse_markup_integer(node["size"].data);
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
@ -393,7 +393,7 @@ void Cartridge::parse_markup_sufamiturbo(BML::Node &root) {
}
}
void Cartridge::parse_markup_srtc(BML::Node &root) {
void Cartridge::parse_markup_srtc(XML::Node &root) {
if(root.exists() == false) return;
has_srtc = true;
@ -405,7 +405,7 @@ void Cartridge::parse_markup_srtc(BML::Node &root) {
}
}
void Cartridge::parse_markup_sdd1(BML::Node &root) {
void Cartridge::parse_markup_sdd1(XML::Node &root) {
if(root.exists() == false) return;
has_sdd1 = true;
@ -424,7 +424,7 @@ void Cartridge::parse_markup_sdd1(BML::Node &root) {
}
}
void Cartridge::parse_markup_spc7110(BML::Node &root) {
void Cartridge::parse_markup_spc7110(XML::Node &root) {
if(root.exists() == false) return;
has_spc7110 = true;
@ -434,7 +434,7 @@ void Cartridge::parse_markup_spc7110(BML::Node &root) {
auto &dcu = root["dcu"];
auto &rtc = root["rtc"];
ram_size = parse_markup_integer(ram["size"].value);
ram_size = parse_markup_integer(ram["size"].data);
for(auto &node : ram) {
if(node.name != "map") continue;
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
@ -449,7 +449,7 @@ void Cartridge::parse_markup_spc7110(BML::Node &root) {
mapping.append(m);
}
spc7110.data_rom_offset = parse_markup_integer(mcu["offset"].value);
spc7110.data_rom_offset = parse_markup_integer(mcu["offset"].data);
if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000;
for(auto &node : mcu) {
if(node.name != "map") continue;
@ -473,7 +473,7 @@ void Cartridge::parse_markup_spc7110(BML::Node &root) {
}
}
void Cartridge::parse_markup_obc1(BML::Node &root) {
void Cartridge::parse_markup_obc1(XML::Node &root) {
if(root.exists() == false) return;
has_obc1 = true;
@ -485,7 +485,7 @@ void Cartridge::parse_markup_obc1(BML::Node &root) {
}
}
void Cartridge::parse_markup_setarisc(BML::Node &root) {
void Cartridge::parse_markup_setarisc(XML::Node &root) {
if(root.exists() == false) return;
has_st0018 = true;
@ -497,7 +497,7 @@ void Cartridge::parse_markup_setarisc(BML::Node &root) {
}
}
void Cartridge::parse_markup_msu1(BML::Node &root) {
void Cartridge::parse_markup_msu1(XML::Node &root) {
if(root.exists() == false) {
has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, ".msu"));
if(has_msu1) {
@ -520,12 +520,12 @@ void Cartridge::parse_markup_msu1(BML::Node &root) {
}
}
void Cartridge::parse_markup_link(BML::Node &root) {
void Cartridge::parse_markup_link(XML::Node &root) {
if(root.exists() == false) return;
has_link = true;
link.frequency = max(1, parse_markup_integer(root["frequency"].value));
link.program = root["program"].value;
link.frequency = max(1, parse_markup_integer(root["frequency"].data));
link.program = root["program"].data;
for(auto &node : root) {
if(node.name != "map") continue;

View File

@ -15,8 +15,13 @@ bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const s
interface->unloadCartridge();
interface->baseName = nall::basename(filename);
string markup;
markup.readfile({ interface->baseName, ".xml" });
GameBoyCartridge info(data, size);
GameBoy::cartridge.load(revision, info.markup, data, size);
if(markup.empty()) markup = info.markup;
GameBoy::cartridge.load(revision, markup, data, size);
GameBoy::system.power();
delete[] data;

View File

@ -31,7 +31,7 @@ bool InterfaceNES::loadCartridge(const string &filename) {
interface->baseName = nall::basename(filename);
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
NES::cartridge.load(markup, data, size);
NES::system.power();

View File

@ -40,7 +40,7 @@ bool InterfaceSNES::loadCartridge(const string &basename) {
interface->slotName = { nall::basename(basename) };
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
if(markup == "") markup = SnesCartridge(data, size).markup;
SNES::cartridge.rom.copy(data, size);
@ -67,7 +67,7 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, cons
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
if(markup == "") markup = SnesCartridge(data[0], size[0]).markup;
SNES::cartridge.rom.copy(data[0], size[0]);
@ -96,7 +96,7 @@ bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const strin
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
if(markup == "") markup = SnesCartridge(data[0], size[0]).markup;
SNES::cartridge.rom.copy(data[0], size[0]);
@ -128,7 +128,7 @@ bool InterfaceSNES::loadSufamiTurboCartridge(const string &basename, const strin
interface->slotName = { nall::basename(basename), nall::basename(slotAname), nall::basename(slotBname) };
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
if(markup == "") markup = SnesCartridge(data[0], size[0]).markup;
SNES::cartridge.rom.copy(data[0], size[0]);
@ -159,11 +159,11 @@ bool InterfaceSNES::loadSuperGameBoyCartridge(const string &basename, const stri
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
string markup;
markup.readfile({ interface->baseName, ".bml" });
markup.readfile({ interface->baseName, ".xml" });
if(markup == "") markup = SnesCartridge(data[0], size[0]).markup;
string gbMarkup;
gbMarkup.readfile({ nall::basename(slotname), ".bml" });
gbMarkup.readfile({ nall::basename(slotname), ".xml" });
if(gbMarkup == "") gbMarkup = GameBoyCartridge(data[1], size[1]).markup;
SNES::cartridge.rom.copy(data[0], size[0]);

View File

@ -27,7 +27,7 @@ void Application::run() {
}
Application::Application(int argc, char **argv) {
title = "bsnes v084.07";
title = "bsnes v084.08";
application = this;
quit = false;

View File

@ -36,16 +36,23 @@ void CheatDatabase::findCodes() {
string data;
data.readfile(application->path("cheats.xml"));
XML::Document document(data);
for(auto &root : document["database"]) {
if(root.name != "cartridge") continue;
if(root["sha256"].data != interface->sha256()) continue;
for(auto &node : document["database"]) {
if(node.name != "cartridge") continue;
if(node["sha256"].data != interface->sha256()) continue;
setTitle(root["title"].data);
for(auto &cheat : root) {
setTitle(node["title"].data);
for(auto &cheat : node) {
if(cheat.name != "cheat") continue;
if(cheat["description"].name.empty() || cheat["code"].name.empty()) continue;
cheatList.append(cheat["description"].data);
cheatCode.append({ cheat["code"].data, "\t", cheat["description"].data });
string codeList;
for(auto &code : cheat) {
if(code.name != "code") continue;
codeList.append(code.data, "+");
}
codeList.rtrim<1>("+");
cheatCode.append({ codeList, "\t", cheat["description"].data });
}
setVisible();