Update to v089r17 release.

byuu says:

This implements the spec from the XML part 3 thread:

    http://board.byuu.org/viewtopic.php?f=16&t=2998

It's also propagated the changes to nall and purify, so you can test
this one.

This is basically it, after years of effort I feel I finally have
a fully consistent and logical XML board format.
The only things left to change will be: modifications if emulation turns
out to be incorrect (eg we missed some MMIO mirrors, or mirrored too
much), and new additions.

And of course, I'm giving it a bit of time for good arguments against
the format.

Other than that, this release removes linear_vector and pointer_vector,
as vector is better than linear_vector and I've never used
pointer_vector.
vector also gets move(), which is a way to use move-semantics across
types. It lets you steal the underlying memory pool, effectively
destroying the vector without a copy.
This works really nicely with the move for read() functions to return
vector<uint8> instead of taking (uint8_t*&, unsigned&) parameters.
This commit is contained in:
Tim Allen 2012-07-15 23:02:27 +10:00
parent c1318961d8
commit 87cb164f7c
27 changed files with 1009 additions and 1501 deletions

View File

@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "bsnes";
static const char Version[] = "089.16";
static const char Version[] = "089.17";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}

View File

@ -4,7 +4,7 @@ struct CheatCode {
unsigned comp;
};
struct Cheat : public linear_vector<CheatCode> {
struct Cheat : public vector<CheatCode> {
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
void synchronize();

View File

@ -4,7 +4,7 @@ struct CheatCode {
unsigned comp;
};
struct Cheat : public linear_vector<CheatCode> {
struct Cheat : public vector<CheatCode> {
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
void synchronize();

View File

@ -1,6 +1,8 @@
#ifndef NALL_ATOI_HPP
#define NALL_ATOI_HPP
#include <nall/stdint.hpp>
namespace nall {
//note: this header is intended to form the base for user-defined literals;

View File

@ -122,419 +122,348 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
" <icd2 revision='1'>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" <firmware name='boot.rom' size='256' sha256='0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" </icd2>\n"
);
else if(has_cx4) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.rom' 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 model='HG51B169' frequency='20000000'>\n"
" <firmware name='cx4.rom' size='3072' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'/>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
" </hitachidsp>\n"
);
else if(has_spc7110) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.ram' size='", hex(ram_size), "'/>\n"
" <spc7110>\n"
" <mmio>\n"
" <map address='00-3f:4800-483f'/>\n"
" <map address='80-bf:4800-483f'/>\n"
" </mmio>\n"
" <dcu>\n"
" <map address='50:0000-ffff'/>\n"
" </dcu>\n"
" <mcu>\n"
" <rom>\n"
" <program offset='0x000000' size='0x100000'/>\n"
" <data offset='0x100000' size='", hex(rom_size - 0x100000), "'/>\n"
" <map address='00-0f:8000-ffff'/>\n"
" <map address='80-bf:8000-ffff'/>\n"
" <map address='c0-cf:0000-ffff'/>\n"
" </rom>\n"
" <ram>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" </ram>\n"
" </mcu>\n"
" </spc7110>\n"
);
if(has_spc7110rtc) markup.append(
" <epsonrtc name='rtc.ram' size='0x10'>\n"
" <map address='00-3f:4840-4842'/>\n"
" <map address='80-bf:4840-4842'/>\n"
" </epsonrtc>\n"
);
}
else if(has_spc7110) markup.append(
" <spc7110>\n"
" <prom name='program.rom' size='0x100000'/>\n"
" <drom name='data.rom' size='0x", hex(rom_size - 0x100000), "'/>\n"
" <ram name='save.rwm' size='0x2000'/>\n"
" <map address='00-3f:4800-483f' id='io'/>\n"
" <map address='80-bf:4800-483f' id='io'/>\n"
" <map address='50:0000-ffff' id='io'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <map address='00-3f:6000-7fff' id='ram'/>\n"
" <map address='80-bf:6000-7fff' id='ram'/>\n"
" </spc7110>\n"
);
else if(has_sdd1) markup.append(
" <sdd1>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-3f:4800-4807' id='io'/>\n"
" <map address='80-bf:4800-4807' id='io'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='40-7f:0000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <map address='20-3f:6000-7fff' id='ram'/>\n"
" <map address='a0-bf:6000-7fff' id='ram'/>\n"
" <map address='70-7f:0000-7fff' id='ram'/>\n"
" </sdd1>\n"
);
else if(mapper == LoROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
" <map address='f0-ff:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == HiROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-ff:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == ExLoROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:0000-7fff' id='ram' mode='linear'/>\n"
);
}
else if(mapper == ExHiROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='shadow' offset='0x400000'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='shadow' offset='0x000000'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear' offset='0x400000'/>\n"
" <map address='c0-ff:0000-ffff' id='rom' mode='linear' offset='0x000000'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == SuperFXROM) {
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
if(ram_size > 0)
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
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>\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"
" <map address='00-3f:3000-32ff' id='io'/>\n"
" <map address='80-bf:3000-32ff' id='io'/>\n"
" <rom name='program.rom' size='", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='40-5f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.rwm' size='", hex(ram_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='ram' mode='linear' size='0x2000'/>\n"
" <map address='80-bf:6000-7fff' id='ram' mode='linear' size='0x2000'/>\n"
" <map address='60-7f:0000-ffff' id='ram' mode='linear'/>\n"
" <map address='e0-ff:0000-ffff' id='ram' mode='linear'/>\n"
);
markup.append(
" </superfx>\n"
);
}
else if(mapper == SA1ROM) {
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
if(ram_size > 0)
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
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>\n"
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
" </iram>\n"
" <bwram>\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"
" <map address='00-3f:2200-23ff' id='io'/>\n"
" <map address='80-bf:2200-23ff' id='io'/>\n"
" <rom name='program.rom' size='", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <iram size='0x800'/>\n"
" <map address='00-3f:3000-37ff' id='iram'/>\n"
" <map address='80-bf:3000-37ff' id='iram'/>\n"
);
if(ram_size > 0) markup.append(
" <bwram name='save.rwm' size='", hex(ram_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='bwram'/>\n"
" <map address='80-bf:6000-7fff' id='bwram'/>\n"
" <map address='40-4f:0000-ffff' id='bwram'/>\n"
);
markup.append(
" </sa1>\n"
);
}
else if(mapper == BSCLoROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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 name='save.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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='linear' offset='0x000000'/>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='linear' offset='0x100000'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='linear' offset='0x200000'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='linear' offset='0x100000'/>\n"
" <map address='70-7f:0000-7fff' id='ram' mode='linear'/>\n"
" <map address='f0-ff:0000-7fff' id='ram' mode='linear'/>\n"
" <bsxslot>\n"
" <map address='c0-ef:0000-ffff' id='rom' mode='linear'/>\n"
" </bsxslot>\n"
);
else if(mapper == BSCHiROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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 name='save.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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='40-5f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <bsxslot>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='60-7f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='e0-ff:0000-ffff' id='rom' mode='linear'/>\n"
" </bsxslot>\n"
);
else if(mapper == BSXROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n"
" <psram name='bsx.ram' size='0x40000'/>\n"
" <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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <psram name='bsx.rwm' size='0x40000'/>\n"
" <map address='00-3f:5000-5fff' id='io'/>\n"
" <map address='80-bf:5000-5fff' id='io'/>\n"
" <map address='20-3f:6000-7fff' id='ram'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='40-7f:0000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" </bsx>\n"
);
else if(mapper == STROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='linear'/>\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>\n"
" <map mode='linear' address='60-63:8000-ffff'/>\n"
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
" </ram>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='60-63:8000-ffff' id='ram' mode='linear'/>\n"
" <map address='e0-e3:8000-ffff' id='ram' mode='linear'/>\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>\n"
" <map mode='linear' address='70-73:8000-ffff'/>\n"
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
" </ram>\n"
" <map address='40-5f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='70-73:8000-ffff' id='ram' mode='linear'/>\n"
" <map address='f0-f3:8000-ffff' id='ram' mode='linear'/>\n"
" </slot>\n"
" </sufamiturbo>\n"
);
if(has_srtc) markup.append(
" <sharprtc name='rtc.ram' size='0x10'>\n"
" <map address='00-3f:2800-2801'/>\n"
" <map address='80-bf:2800-2801'/>\n"
" </sharprtc>\n"
if(has_spc7110rtc) markup.append(
" <epsonrtc>\n"
" <ram name='rtc.rwm' size='0x10'/>\n"
" <map address='00-3f:4840-4842' id='io'/>\n"
" <map address='80-bf:4840-4842' id='io'/>\n"
" </epsonrtc>\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_srtc) markup.append(
" <sharprtc>\n"
" <ram name='rtc.rwm' size='0x10'/>\n"
" <map address='00-3f:2800-2801' id='io'/>\n"
" <map address='80-bf:2800-2801' id='io'/>\n"
" </sharprtc>\n"
);
if(has_obc1) markup.append(
" <obc1>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" <ram name='save.rwm' size='0x2000'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" </obc1>\n"
);
if(has_dsp1) {
//91e87d11e1c30d172556bed2211cce2efa94ba595f58c5d264809ef4d363a97b dsp1.rom
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.rom' sha256='d789cb3c36b05c0b23b6c6f23be7aa37c6e78b6ee9ceac8d2d2aa9d8c4d35fa9'>\n");
markup.append(
" <necdsp model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp1b.rom' size='8192' sha256='d789cb3c36b05c0b23b6c6f23be7aa37c6e78b6ee9ceac8d2d2aa9d8c4d35fa9'/>\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"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='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"
" <map address='60-6f:0000-3fff' id='dr'/>\n"
" <map address='e0-ef:0000-3fff' id='dr'/>\n"
" <map address='60-6f:4000-7fff' id='sr'/>\n"
" <map address='e0-ef:4000-7fff' id='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"
" <map address='00-1f:6000-6fff' id='dr'/>\n"
" <map address='80-9f:6000-6fff' id='dr'/>\n"
" <map address='00-1f:7000-7fff' id='sr'/>\n"
" <map address='80-9f:7000-7fff' id='sr'/>\n"
);
markup.append(
" </necdsp>\n"
);
markup.append(" </necdsp>\n");
}
if(has_dsp2) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.rom' sha256='03ef4ef26c9f701346708cb5d07847b5203cf1b0818bf2930acd34510ffdd717'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp2.rom' size='8192' sha256='03ef4ef26c9f701346708cb5d07847b5203cf1b0818bf2930acd34510ffdd717'/>\n"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_dsp3) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.rom' sha256='0971b08f396c32e61989d1067dddf8e4b14649d548b2188f7c541b03d7c69e4e'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp3.rom' size='8192' sha256='0971b08f396c32e61989d1067dddf8e4b14649d548b2188f7c541b03d7c69e4e'/>\n"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_dsp4) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.rom' sha256='752d03b2d74441e430b7f713001fa241f8bbcfc1a0d890ed4143f174dbe031da'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp4.rom' size='8192' sha256='752d03b2d74441e430b7f713001fa241f8bbcfc1a0d890ed4143f174dbe031da'/>\n"
" <map address='30-3f:8000-bfff' id='dr'/>\n"
" <map address='b0-bf:8000-bfff' id='dr'/>\n"
" <map address='30-3f:c000-ffff' id='sr'/>\n"
" <map address='b0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_st010) markup.append(
" <necdsp model='uPD96050' frequency='10000000' firmware='st010.rom' sha256='fa9bced838fedea11c6f6ace33d1878024bdd0d02cc9485899d0bdd4015ec24c'>\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 model='uPD96050' frequency='10000000'>\n"
" <firmware name='st010.rom' size='53248' sha256='fa9bced838fedea11c6f6ace33d1878024bdd0d02cc9485899d0bdd4015ec24c'/>\n"
" <ram name='save.rwm' size='0x1000'/>\n"
" <map address='60:0000' id='dr'/>\n"
" <map address='e0:0000' id='dr'/>\n"
" <map address='60:0001' id='sr'/>\n"
" <map address='e0:0001' id='sr'/>\n"
" <map address='68-6f:0000-0fff' id='ram'/>\n"
" <map address='e8-ef:0000-0fff' id='ram'/>\n"
" </necdsp>\n"
);
if(has_st011) markup.append(
" <necdsp model='uPD96050' frequency='15000000' firmware='st011.rom' sha256='8b2b3f3f3e6e29f4d21d8bc736b400bc988b7d2214ebee15643f01c1fee2f364'>\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 model='uPD96050' frequency='15000000'>\n"
" <firmware name='st011.rom' size='53248' sha256='8b2b3f3f3e6e29f4d21d8bc736b400bc988b7d2214ebee15643f01c1fee2f364'/>\n"
" <ram name='save.rwm' size='0x1000'/>\n"
" <map address='60:0000' id='dr'/>\n"
" <map address='e0:0000' id='dr'/>\n"
" <map address='60:0001' id='sr'/>\n"
" <map address='e0:0001' id='sr'/>\n"
" <map address='68-6f:0000-0fff' id='ram'/>\n"
" <map address='e8-ef:0000-0fff' id='ram'/>\n"
" </necdsp>\n"
);
if(has_st018) markup.append(
" <armdsp firmware='st018.rom' frequency='21477272' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'>\n"
" <map address='00-3f:3800-38ff'/>\n"
" <map address='80-bf:3800-38ff'/>\n"
" <armdsp frequency='21477272'>\n"
" <firmware name='st018.rom' size='163840' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'/>\n"
" <map address='00-3f:3800-38ff' id='io'/>\n"
" <map address='80-bf:3800-38ff' id='io'/>\n"
" </armdsp>\n"
);

56
bsnes/nall/nall.hpp Executable file
View File

@ -0,0 +1,56 @@
#ifndef NALL_HPP
#define NALL_HPP
//include the most common nall headers with one statement
//does not include the most obscure components with high cost and low usage
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/any.hpp>
#include <nall/atoi.hpp>
#include <nall/base64.hpp>
#include <nall/bit.hpp>
#include <nall/bmp.hpp>
#include <nall/config.hpp>
#include <nall/crc32.hpp>
#include <nall/directory.hpp>
#include <nall/dl.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/filemap.hpp>
#include <nall/function.hpp>
#include <nall/gzip.hpp>
#include <nall/http.hpp>
#include <nall/image.hpp>
#include <nall/inflate.hpp>
#include <nall/interpolation.hpp>
#include <nall/intrinsics.hpp>
#include <nall/invoke.hpp>
#include <nall/map.hpp>
#include <nall/png.hpp>
#include <nall/property.hpp>
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/set.hpp>
#include <nall/sha256.hpp>
#include <nall/sort.hpp>
#include <nall/stdint.hpp>
#include <nall/stream.hpp>
#include <nall/string.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/zip.hpp>
#if defined(PLATFORM_WINDOWS)
#include <nall/windows/registry.hpp>
#include <nall/windows/utf8.hpp>
#endif
#if defined(PLATFORM_X)
#include <nall/serial.hpp>
#endif
#endif

View File

@ -20,7 +20,9 @@ struct zipstream : memorystream {
for(auto &file : archive.file) {
if(file.name.wildcard(filter)) {
archive.extract(file, pdata, psize);
auto buffer = archive.extract(file);
psize = buffer.size();
pdata = buffer.move();
return;
}
}

View File

@ -24,10 +24,18 @@ namespace nall {
operator bool() const { return pool; }
T* data() { return pool; }
bool empty() const { return pool == nullptr; }
bool empty() const { return objectsize == 0; }
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
T* move() {
T *result = data;
pool = nullptr;
poolsize = 0;
objectsize = 0;
return result;
}
void reset() {
if(pool) {
for(unsigned n = 0; n < objectsize; n++) pool[n].~T();
@ -191,293 +199,6 @@ namespace nall {
reset();
}
};
//linear_vector
//memory: O(capacity * 2)
//
//linear_vector uses placement new + manual destructor calls to create a
//contiguous block of memory for all objects. accessing individual elements
//is fast, though resizing the array incurs significant overhead.
//reserve() overhead is reduced from quadratic time to amortized constant time
//by resizing twice as much as requested.
//
//if objects hold memory address references to themselves (introspection), a
//valid copy constructor will be needed to keep pointers valid.
#define NALL_DEPRECATED
#if defined(NALL_DEPRECATED)
template<typename T> struct linear_vector {
protected:
T *pool;
unsigned poolsize, objectsize;
public:
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
void reset() {
if(pool) {
for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
free(pool);
}
pool = nullptr;
poolsize = 0;
objectsize = 0;
}
void reserve(unsigned newsize) {
newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
T *poolcopy = (T*)calloc(newsize, sizeof(T));
for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]);
for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
free(pool);
pool = poolcopy;
poolsize = newsize;
objectsize = min(objectsize, newsize);
}
void resize(unsigned newsize) {
if(newsize > poolsize) reserve(newsize);
if(newsize < objectsize) {
//vector is shrinking; destroy excess objects
for(unsigned i = newsize; i < objectsize; i++) pool[i].~T();
} else if(newsize > objectsize) {
//vector is expanding; allocate new objects
for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T;
}
objectsize = newsize;
}
void append(const T data) {
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
new(pool + objectsize++) T(data);
}
template<typename U> void insert(unsigned index, const U list) {
linear_vector<T> merged;
for(unsigned i = 0; i < index; i++) merged.append(pool[i]);
for(auto &item : list) merged.append(item);
for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]);
operator=(merged);
}
void insert(unsigned index, const T item) {
insert(index, linear_vector<T>{ item });
}
void remove(unsigned index, unsigned count = 1) {
for(unsigned i = index; count + i < objectsize; i++) {
pool[i] = pool[count + i];
}
if(count + index >= objectsize) resize(index); //every element >= index was removed
else resize(objectsize - count);
}
linear_vector() : pool(nullptr), poolsize(0), objectsize(0) {
}
linear_vector(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
}
~linear_vector() {
reset();
}
//copy
inline linear_vector<T>& operator=(const linear_vector<T> &source) {
reset();
reserve(source.capacity());
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
linear_vector(const linear_vector<T> &source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(source);
}
//move
inline linear_vector<T>& operator=(linear_vector<T> &&source) {
reset();
pool = source.pool;
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = nullptr;
source.reset();
return *this;
}
linear_vector(linear_vector<T> &&source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//index
inline T& operator[](unsigned index) {
if(index >= objectsize) resize(index + 1);
return pool[index];
}
inline const T& operator[](unsigned index) const {
if(index >= objectsize) throw "vector[] out of bounds";
return pool[index];
}
//iteration
T* begin() { return &pool[0]; }
T* end() { return &pool[objectsize]; }
const T* begin() const { return &pool[0]; }
const T* end() const { return &pool[objectsize]; }
};
//pointer_vector
//memory: O(1)
//
//pointer_vector keeps an array of pointers to each vector object. this adds
//significant overhead to individual accesses, but allows for optimal memory
//utilization.
//
//by guaranteeing that the base memory address of each objects never changes,
//this avoids the need for an object to have a valid copy constructor.
template<typename T> struct pointer_vector {
protected:
T **pool;
unsigned poolsize, objectsize;
public:
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
void reset() {
if(pool) {
for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; }
free(pool);
}
pool = nullptr;
poolsize = 0;
objectsize = 0;
}
void reserve(unsigned newsize) {
newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
for(unsigned i = newsize; i < objectsize; i++) {
if(pool[i]) { delete pool[i]; pool[i] = 0; }
}
pool = (T**)realloc(pool, newsize * sizeof(T*));
for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0;
poolsize = newsize;
objectsize = min(objectsize, newsize);
}
void resize(unsigned newsize) {
if(newsize > poolsize) reserve(newsize);
for(unsigned i = newsize; i < objectsize; i++) {
if(pool[i]) { delete pool[i]; pool[i] = 0; }
}
objectsize = newsize;
}
void append(const T data) {
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
pool[objectsize++] = new T(data);
}
template<typename U> void insert(unsigned index, const U list) {
pointer_vector<T> merged;
for(unsigned i = 0; i < index; i++) merged.append(*pool[i]);
for(auto &item : list) merged.append(item);
for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]);
operator=(merged);
}
void insert(unsigned index, const T item) {
insert(index, pointer_vector<T>{ item });
}
void remove(unsigned index, unsigned count = 1) {
for(unsigned i = index; count + i < objectsize; i++) {
*pool[i] = *pool[count + i];
}
if(count + index >= objectsize) resize(index); //every element >= index was removed
else resize(objectsize - count);
}
pointer_vector() : pool(nullptr), poolsize(0), objectsize(0) {
}
pointer_vector(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
}
~pointer_vector() {
reset();
}
//copy
inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
reset();
reserve(source.capacity());
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
pointer_vector(const pointer_vector<T> &source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(source);
}
//move
inline pointer_vector<T>& operator=(pointer_vector<T> &&source) {
reset();
pool = source.pool;
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = nullptr;
source.reset();
return *this;
}
pointer_vector(pointer_vector<T> &&source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//index
inline T& operator[](unsigned index) {
if(index >= objectsize) resize(index + 1);
if(!pool[index]) pool[index] = new T;
return *pool[index];
}
inline const T& operator[](unsigned index) const {
if(index >= objectsize || !pool[index]) throw "vector[] out of bounds";
return *pool[index];
}
//iteration
struct iterator {
bool operator!=(const iterator &source) const { return index != source.index; }
T& operator*() { return vector.operator[](index); }
iterator& operator++() { index++; return *this; }
iterator(const pointer_vector &vector, unsigned index) : vector(vector), index(index) {}
private:
const pointer_vector &vector;
unsigned index;
};
iterator begin() { return iterator(*this, 0); }
iterator end() { return iterator(*this, objectsize); }
const iterator begin() const { return iterator(*this, 0); }
const iterator end() const { return iterator(*this, objectsize); }
};
#endif
}
#endif

View File

@ -3,13 +3,13 @@
<bsx>
<rom name="program.rom" size="0x100000"/>
<ram name="save.rwm" size="0x8000"/>
<psram name="flash.rwm" size="0x40000"/>
<map address="00-3f:8000-ffff"/>
<map address="80-bf:8000-ffff"/>
<map address="40-7f:0000-ffff"/>
<map address="c0-ff:0000-ffff"/>
<map address="20-3f:6000-7fff"/>
<map address="00-3f:5000-5fff"/>
<map address="80-bf:5000-5fff"/>
<psram name="bsx.rwm" size="0x40000"/>
<map address="00-3f:8000-ffff" id="rom"/>
<map address="80-bf:8000-ffff" id="rom"/>
<map address="40-7f:0000-ffff" id="rom"/>
<map address="c0-ff:0000-ffff" id="rom"/>
<map address="20-3f:6000-7fff" id="ram"/>
<map address="00-3f:5000-5fff" id="io"/>
<map address="80-bf:5000-5fff" id="io"/>
</bsx>
</cartridge>

View File

@ -1,29 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<rom name="program.rom" size="0x40000">
<map mode="linear" address="00-1f:8000-ffff"/>
<map mode="linear" address="80-9f:8000-ffff"/>
</rom>
<rom name="program.rom" size="0x40000"/>
<map address="00-1f:8000-ffff" id="rom" mode="linear"/>
<map address="80-9f:8000-ffff" id="rom" mode="linear"/>
<sufamiturbo>
<slot id="A">
<rom>
<map mode="linear" address="20-3f:8000-ffff"/>
<map mode="linear" address="a0-bf:8000-ffff"/>
</rom>
<ram>
<map mode="linear" address="60-63:8000-ffff"/>
<map mode="linear" address="e0-e3:8000-ffff"/>
</ram>
<map address="20-3f:8000-ffff" id="rom" mode="linear"/>
<map address="a0-bf:8000-ffff" id="rom" mode="linear"/>
<map address="60-63:8000-ffff" id="ram" mode="linear"/>
<map address="e0-e3:8000-ffff" id="ram" mode="linear"/>
</slot>
<slot id="B">
<rom>
<map mode="linear" address="40-5f:8000-ffff"/>
<map mode="linear" address="c0-df:8000-ffff"/>
</rom>
<ram>
<map mode="linear" address="70-73:8000-ffff"/>
<map mode="linear" address="f0-f3:8000-ffff"/>
</ram>
<map address="40-5f:8000-ffff" id="rom" mode="linear"/>
<map address="c0-df:8000-ffff" id="rom" mode="linear"/>
<map address="70-73:8000-ffff" id="ram" mode="linear"/>
<map address="f0-f3:8000-ffff" id="ram" mode="linear"/>
</slot>
</sufamiturbo>
</cartridge>

View File

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<rom name="program.rom" size="0x80000">
<map mode="linear" address="00-7f:8000-ffff"/>
<map mode="linear" address="80-ff:8000-ffff"/>
</rom>
<rom name="program.rom" size="0x80000"/>
<map address="00-7f:8000-ffff" id="rom" mode="linear"/>
<map address="80-ff:8000-ffff" id="rom" mode="linear"/>
<icd2 revision="1">
<firmware name="boot.rom" size="256" sha256="0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360"/>
<map address="00-3f:6000-7fff"/>
<map address="80-bf:6000-7fff"/>
<map address="00-3f:6000-7fff" id="io"/>
<map address="80-bf:6000-7fff" id="io"/>
</icd2>
</cartridge>

File diff suppressed because one or more lines are too long

View File

@ -78,11 +78,10 @@ private:
void parse_markup_map(Mapping&, XML::Node&);
void parse_markup_memory(MappedRAM&, XML::Node&, unsigned id, bool writable);
void parse_markup_rom(XML::Node&);
void parse_markup_ram(XML::Node&);
void parse_markup_psram(XML::Node&);
void parse_markup_cartridge(XML::Node&);
void parse_markup_icd2(XML::Node&);
void parse_markup_bsx(XML::Node&);
void parse_markup_bsxslot(XML::Node&);
void parse_markup_sufamiturbo(XML::Node&);
void parse_markup_nss(XML::Node&);
void parse_markup_sa1(XML::Node&);

View File

@ -7,11 +7,10 @@ void Cartridge::parse_markup(const char *markup) {
auto &cartridge = document["cartridge"];
region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL;
parse_markup_rom(cartridge["rom"]);
parse_markup_ram(cartridge["ram"]);
parse_markup_psram(cartridge["psram"]);
parse_markup_cartridge(cartridge);
parse_markup_icd2(cartridge["icd2"]);
parse_markup_bsx(cartridge["bsx"]);
parse_markup_bsxslot(cartridge["bsxslot"]);
parse_markup_sufamiturbo(cartridge["sufamiturbo"]);
parse_markup_nss(cartridge["nss"]);
parse_markup_sa1(cartridge["sa1"]);
@ -74,39 +73,35 @@ void Cartridge::parse_markup_memory(MappedRAM &ram, XML::Node &node, unsigned id
//
void Cartridge::parse_markup_rom(XML::Node &root) {
void Cartridge::parse_markup_cartridge(XML::Node &root) {
if(root.exists() == false) return;
parse_markup_memory(rom, root, ID::ROM, false);
parse_markup_memory(rom, root["rom"], ID::ROM, false);
parse_markup_memory(ram, root["ram"], ID::RAM, true);
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m(rom);
parse_markup_map(m, node);
if(m.size == 0) m.size = rom.size();
mapping.append(m);
if(node["id"].data == "rom") {
Mapping m(rom);
parse_markup_map(m, node);
if(m.size == 0) m.size = rom.size();
mapping.append(m);
}
if(node["id"].data == "ram") {
Mapping m(ram);
parse_markup_map(m, node);
if(m.size == 0) m.size = ram.size();
mapping.append(m);
}
}
}
void Cartridge::parse_markup_ram(XML::Node &root) {
if(root.exists() == false) return;
parse_markup_memory(ram, root, ID::RAM, true);
for(auto &node : root) {
Mapping m(ram);
parse_markup_map(m, node);
if(m.size == 0) m.size = ram.size();
mapping.append(m);
}
}
void Cartridge::parse_markup_psram(XML::Node &root) {
if(root.exists() == false) return;
parse_markup_memory(bsxcartridge.psram, root, ID::BsxPSRAM, true);
}
void Cartridge::parse_markup_icd2(XML::Node &root) {
if(root.exists() == false) return;
has_gb_slot = true;
icd2.revision = max(1, numeral(root["revision"].data));
interface->loadRequest(ID::SuperGameBoy, "Game Boy", "gb");
@ -116,43 +111,61 @@ void Cartridge::parse_markup_icd2(XML::Node &root) {
interface->notify("Error: required firmware ", firmware, " not found.\n");
}
icd2.revision = max(1, numeral(root["revision"].data));
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&ICD2::read, &icd2}, {&ICD2::write, &icd2});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&ICD2::read, &icd2}, {&ICD2::write, &icd2});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
void Cartridge::parse_markup_bsx(XML::Node &root) {
if(root.exists() == false) return;
has_bs_cart = root["map"].exists();
has_bs_cart = true;
has_bs_slot = true;
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs");
if(has_bs_cart) {
parse_markup_memory(bsxcartridge.rom, root["rom"], ID::BsxROM, false);
parse_markup_memory(bsxcartridge.ram, root["ram"], ID::BsxRAM, true);
parse_markup_memory(bsxcartridge.psram, root["psram"], ID::BsxPSRAM, true);
}
for(auto &node : root["slot"]) {
if(node.name != "map") continue;
if(bsxflash.memory.size() == 0) continue;
Mapping m(bsxflash.memory);
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(bsxcartridge.rom, root["rom"], ID::BsxROM, false);
parse_markup_memory(bsxcartridge.ram, root["ram"], ID::BsxRAM, true);
parse_markup_memory(bsxcartridge.psram, root["psram"], ID::BsxPSRAM, true);
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&BSXCartridge::mcu_read, &bsxcartridge}, {&BSXCartridge::mcu_write, &bsxcartridge});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "rom" || node["id"].data == "ram") {
Mapping m({&BSXCartridge::mcu_read, &bsxcartridge}, {&BSXCartridge::mcu_write, &bsxcartridge});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "io") {
Mapping m({&BSXCartridge::mmio_read, &bsxcartridge}, {&BSXCartridge::mmio_write, &bsxcartridge});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
void Cartridge::parse_markup_bsxslot(XML::Node &root) {
if(root.exists() == false) return;
has_bs_slot = true;
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs");
for(auto &node : root) {
if(node.name != "map") continue;
if(node["id"].data == "rom") {
if(bsxflash.memory.size() == 0) continue;
Mapping m(bsxflash.memory);
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -166,31 +179,28 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
for(auto &slot : root) {
if(slot.name != "slot") continue;
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) {
if(leaf.name != "map") continue;
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom;
if(memory.size() == 0) continue;
if(node.name != "map") continue;
Mapping m(memory);
parse_markup_map(m, leaf);
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
}
if(node["id"].data == "rom") {
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom;
if(memory.size() == 0) continue;
Mapping m(memory);
parse_markup_map(m, node);
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
}
if(node.name == "ram") {
unsigned ram_size = numeral(node["size"].data);
for(auto &leaf : node) {
if(leaf.name != "map") continue;
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
if(memory.size() == 0) continue;
Mapping m(memory);
parse_markup_map(m, leaf);
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
}
if(node["id"].data == "ram") {
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
if(memory.size() == 0) continue;
Mapping m(memory);
parse_markup_map(m, node);
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
}
}
}
@ -203,9 +213,12 @@ void Cartridge::parse_markup_nss(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&NSS::read, &nss}, {&NSS::write, &nss});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&NSS::read, &nss}, {&NSS::write, &nss});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -214,34 +227,36 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
has_sa1 = true;
parse_markup_memory(sa1.rom, root["rom"], ID::SA1ROM, false);
for(auto &node : root["rom"]) {
if(node.name != "map") continue;
Mapping m({&SA1::mmc_read, &sa1}, {&SA1::mmc_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(sa1.iram, root["iram"], ID::SA1IRAM, true);
for(auto &node : root["iram"]) {
if(node.name != "map") continue;
Mapping m({&SA1::mmc_read, &sa1}, {&SA1::mmc_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(sa1.bwram, root["bwram"], ID::SA1BWRAM, true);
for(auto &node : root["bwram"]) {
if(node.name != "map") continue;
Mapping m({&SA1::mmc_read, &sa1}, {&SA1::mmc_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "rom") {
Mapping m({&SA1::mmcrom_read, &sa1}, {&SA1::mmcrom_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "iram") {
Mapping m(sa1.cpuiram);
parse_markup_map(m, node);
if(m.size == 0) m.size = sa1.cpuiram.size();
mapping.append(m);
}
if(node["id"].data == "bwram") {
Mapping m({&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -250,27 +265,29 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
has_superfx = true;
parse_markup_memory(superfx.rom, root["rom"], ID::SuperFXROM, false);
for(auto &node : root["rom"]) {
if(node.name != "map") continue;
Mapping m(superfx.cpurom);
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(superfx.ram, root["ram"], ID::SuperFXRAM, true);
for(auto &node : root["ram"]) {
if(node.name != "map") continue;
Mapping m(superfx.cpuram);
parse_markup_map(m, node);
if(m.size == 0) m.size = superfx.ram.size();
mapping.append(m);
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "rom") {
Mapping m(superfx.cpurom);
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "ram") {
Mapping m(superfx.cpuram);
parse_markup_map(m, node);
if(m.size == 0) m.size = superfx.ram.size();
mapping.append(m);
}
}
}
@ -285,9 +302,12 @@ void Cartridge::parse_markup_armdsp(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&ArmDSP::mmio_read, &armdsp}, {&ArmDSP::mmio_write, &armdsp});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&ArmDSP::mmio_read, &armdsp}, {&ArmDSP::mmio_write, &armdsp});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -305,18 +325,21 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
interface->loadRequest(ID::HitachiDSP, firmware);
parse_markup_memory(hitachidsp.rom, root["rom"], ID::HitachiDSPROM, false);
for(auto &node : root["rom"]) {
if(node.name != "map") continue;
Mapping m({&HitachiDSP::rom_read, &hitachidsp}, {&HitachiDSP::rom_write, &hitachidsp});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&HitachiDSP::dsp_read, &hitachidsp}, {&HitachiDSP::dsp_write, &hitachidsp});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&HitachiDSP::dsp_read, &hitachidsp}, {&HitachiDSP::dsp_write, &hitachidsp});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "rom") {
Mapping m({&HitachiDSP::rom_read, &hitachidsp}, {&HitachiDSP::rom_write, &hitachidsp});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -347,25 +370,26 @@ void Cartridge::parse_markup_necdsp(XML::Node &root) {
memory.append({ID::NecDSPRAM, name});
}
for(auto &node : root["ram"]) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&NECDSP::dp_read, &necdsp}, {&NECDSP::dp_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root["dr"]) {
if(node.name != "map") continue;
Mapping m({&NECDSP::dr_read, &necdsp}, {&NECDSP::dr_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "dr") {
Mapping m({&NECDSP::dr_read, &necdsp}, {&NECDSP::dr_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root["sr"]) {
if(node.name != "map") continue;
Mapping m({&NECDSP::sr_read, &necdsp}, {&NECDSP::sr_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "sr") {
Mapping m({&NECDSP::sr_read, &necdsp}, {&NECDSP::sr_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "ram") {
Mapping m({&NECDSP::dp_read, &necdsp}, {&NECDSP::dp_write, &necdsp});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -379,9 +403,12 @@ void Cartridge::parse_markup_epsonrtc(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -395,9 +422,12 @@ void Cartridge::parse_markup_sharprtc(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -405,28 +435,30 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
if(root.exists() == false) return;
has_spc7110 = true;
parse_markup_memory(spc7110.prom, root["rom"]["program"], ID::SPC7110PROM, false);
parse_markup_memory(spc7110.drom, root["rom"]["data"], ID::SPC7110DROM, false);
for(auto &node : root["rom"]) {
if(node.name != "map") continue;
Mapping m({&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(spc7110.prom, root["prom"], ID::SPC7110PROM, false);
parse_markup_memory(spc7110.drom, root["drom"], ID::SPC7110DROM, false);
parse_markup_memory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
for(auto &node : root["ram"]) {
if(node.name != "map") continue;
Mapping m({&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "rom") {
Mapping m({&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "ram") {
Mapping m({&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -435,26 +467,28 @@ void Cartridge::parse_markup_sdd1(XML::Node &root) {
has_sdd1 = true;
parse_markup_memory(sdd1.rom, root["rom"], ID::SDD1ROM, false);
for(auto &node : root["rom"]) {
if(node.name != "map") continue;
Mapping m({&SDD1::mcu_read, &sdd1}, {&SDD1::mcu_write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
}
parse_markup_memory(sdd1.ram, root["ram"], ID::SDD1RAM, true);
for(auto &node : root["ram"]) {
if(node.name != "map") continue;
Mapping m({&SDD1::mcu_read, &sdd1}, {&SDD1::mcu_write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "rom") {
Mapping m({&SDD1::mcurom_read, &sdd1}, {&SDD1::mcurom_write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "ram") {
Mapping m({&SDD1::mcuram_read, &sdd1}, {&SDD1::mcuram_write, &sdd1});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -463,11 +497,15 @@ void Cartridge::parse_markup_obc1(XML::Node &root) {
has_obc1 = true;
parse_markup_memory(obc1.ram, root["ram"], ID::OBC1RAM, true);
for(auto &node : root["ram"]) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&OBC1::read, &obc1}, {&OBC1::write, &obc1});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&OBC1::read, &obc1}, {&OBC1::write, &obc1});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
@ -477,9 +515,12 @@ void Cartridge::parse_markup_msu1(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&MSU1::mmio_read, &msu1}, {&MSU1::mmio_write, &msu1});
parse_markup_map(m, node);
mapping.append(m);
if(node["id"].data == "io") {
Mapping m({&MSU1::mmio_read, &msu1}, {&MSU1::mmio_write, &msu1});
parse_markup_map(m, node);
mapping.append(m);
}
}
}

View File

@ -42,11 +42,6 @@ void BSXCartridge::memory_write(Memory &memory, unsigned addr, uint8 data) {
//mcu_access() allows mcu_read() and mcu_write() to share decoding logic
uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) {
if((addr & 0x40f000) == 0x005000) { //$00-3f|80-bf:5000-5fff
if(write == 0) return mmio_read(addr);
if(write == 1) return mmio_write(addr, data), 0;
}
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
if(r07 == 1) {
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff);

View File

@ -6,11 +6,11 @@ uint8 SA1::bus_read(unsigned addr) {
}
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmc_read(addr);
return mmcrom_read(addr);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmc_read(addr);
return mmcrom_read(addr);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
@ -74,11 +74,11 @@ void SA1::bus_write(unsigned addr, uint8 data) {
//these ports.
uint8 SA1::vbr_read(unsigned addr) {
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmc_read(addr);
return mmcrom_read(addr);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmc_read(addr);
return mmcrom_read(addr);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
@ -119,21 +119,7 @@ void SA1::op_write(unsigned addr, uint8 data) {
bus_write(addr, data);
}
uint8 SA1::mmc_read(unsigned addr) {
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
return cpuiram.read(addr & 0x07ff);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronize_coprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
return cpubwram.read(addr);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return cpubwram.read(addr & 0x0fffff);
}
uint8 SA1::mmcrom_read(unsigned addr) {
if((addr & 0xffffe0) == 0x00ffe0) {
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
@ -188,11 +174,24 @@ uint8 SA1::mmc_read(unsigned addr) {
return 0x00;
}
void SA1::mmc_write(unsigned addr, uint8 data) {
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
return cpuiram.write(addr & 0x07ff, data);
void SA1::mmcrom_write(unsigned addr, uint8 data) {
}
uint8 SA1::mmcbwram_read(unsigned addr) {
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronize_coprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
return cpubwram.read(addr);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return cpubwram.read(addr & 0x0fffff);
}
return cpu.regs.mdr;
}
void SA1::mmcbwram_write(unsigned addr, uint8 data) {
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronize_coprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());

View File

@ -6,8 +6,11 @@ alwaysinline void op_io();
alwaysinline uint8 op_read(unsigned addr);
alwaysinline void op_write(unsigned addr, uint8 data);
uint8 mmc_read(unsigned addr);
void mmc_write(unsigned addr, uint8 data);
uint8 mmcrom_read(unsigned addr);
void mmcrom_write(unsigned addr, uint8 data);
uint8 mmcbwram_read(unsigned addr);
void mmcbwram_write(unsigned addr, uint8 data);
uint8 mmc_sa1_read(unsigned addr);
void mmc_sa1_write(unsigned addr, uint8 data);

View File

@ -108,15 +108,7 @@ uint8 SDD1::mmc_read(unsigned addr) {
//
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
uint8 SDD1::mcu_read(unsigned addr) {
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return ram.read(addr & 0x1fff);
}
if((addr & 0xf08000) == 0x700000) { //$70-7f:0000-7fff
return ram.read(addr & 0x1fff);
}
uint8 SDD1::mcurom_read(unsigned addr) {
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
return rom.read(addr);
@ -152,7 +144,22 @@ uint8 SDD1::mcu_read(unsigned addr) {
return mmc_read(addr);
}
void SDD1::mcu_write(unsigned addr, uint8 data) {
void SDD1::mcurom_write(unsigned addr, uint8 data) {
}
uint8 SDD1::mcuram_read(unsigned addr) {
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return ram.read(addr & 0x1fff);
}
if((addr & 0xf08000) == 0x700000) { //$70-7f:0000-7fff
return ram.read(addr & 0x1fff);
}
return cpu.regs.mdr;
}
void SDD1::mcuram_write(unsigned addr, uint8 data) {
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return ram.write(addr & 0x1fff, data);
}

View File

@ -12,8 +12,12 @@ struct SDD1 {
void write(unsigned addr, uint8 data);
uint8 mmc_read(unsigned addr);
uint8 mcu_read(unsigned addr);
void mcu_write(unsigned addr, uint8 data);
uint8 mcurom_read(unsigned addr);
void mcurom_write(unsigned addr, uint8 data);
uint8 mcuram_read(unsigned addr);
void mcuram_write(unsigned addr, uint8 data);
void serialize(serializer&);

View File

@ -1,6 +1,8 @@
#ifndef NALL_ATOI_HPP
#define NALL_ATOI_HPP
#include <nall/stdint.hpp>
namespace nall {
//note: this header is intended to form the base for user-defined literals;

View File

@ -122,419 +122,348 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
" <icd2 revision='1'>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" <firmware name='boot.rom' size='256' sha256='0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" </icd2>\n"
);
else if(has_cx4) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.rom' 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 model='HG51B169' frequency='20000000'>\n"
" <firmware name='cx4.rom' size='3072' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'/>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
" </hitachidsp>\n"
);
else if(has_spc7110) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.ram' size='", hex(ram_size), "'/>\n"
" <spc7110>\n"
" <mmio>\n"
" <map address='00-3f:4800-483f'/>\n"
" <map address='80-bf:4800-483f'/>\n"
" </mmio>\n"
" <dcu>\n"
" <map address='50:0000-ffff'/>\n"
" </dcu>\n"
" <mcu>\n"
" <rom>\n"
" <program offset='0x000000' size='0x100000'/>\n"
" <data offset='0x100000' size='", hex(rom_size - 0x100000), "'/>\n"
" <map address='00-0f:8000-ffff'/>\n"
" <map address='80-bf:8000-ffff'/>\n"
" <map address='c0-cf:0000-ffff'/>\n"
" </rom>\n"
" <ram>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" </ram>\n"
" </mcu>\n"
" </spc7110>\n"
);
if(has_spc7110rtc) markup.append(
" <epsonrtc name='rtc.ram' size='0x10'>\n"
" <map address='00-3f:4840-4842'/>\n"
" <map address='80-bf:4840-4842'/>\n"
" </epsonrtc>\n"
);
}
else if(has_spc7110) markup.append(
" <spc7110>\n"
" <prom name='program.rom' size='0x100000'/>\n"
" <drom name='data.rom' size='0x", hex(rom_size - 0x100000), "'/>\n"
" <ram name='save.rwm' size='0x2000'/>\n"
" <map address='00-3f:4800-483f' id='io'/>\n"
" <map address='80-bf:4800-483f' id='io'/>\n"
" <map address='50:0000-ffff' id='io'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <map address='00-3f:6000-7fff' id='ram'/>\n"
" <map address='80-bf:6000-7fff' id='ram'/>\n"
" </spc7110>\n"
);
else if(has_sdd1) markup.append(
" <sdd1>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-3f:4800-4807' id='io'/>\n"
" <map address='80-bf:4800-4807' id='io'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='40-7f:0000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <map address='20-3f:6000-7fff' id='ram'/>\n"
" <map address='a0-bf:6000-7fff' id='ram'/>\n"
" <map address='70-7f:0000-7fff' id='ram'/>\n"
" </sdd1>\n"
);
else if(mapper == LoROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-7f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-ff:8000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
" <map address='f0-ff:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == HiROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-ff:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == ExLoROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:0000-7fff' id='ram' mode='linear'/>\n"
);
}
else if(mapper == ExHiROM) {
markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='shadow' offset='0x400000'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='shadow' offset='0x000000'/>\n"
" <map address='40-7f:0000-ffff' id='rom' mode='linear' offset='0x400000'/>\n"
" <map address='c0-ff:0000-ffff' id='rom' mode='linear' offset='0x000000'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.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"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='70-7f:", range, "' id='ram' mode='linear'/>\n"
);
}
else if(mapper == SuperFXROM) {
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
if(ram_size > 0)
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
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>\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"
" <map address='00-3f:3000-32ff' id='io'/>\n"
" <map address='80-bf:3000-32ff' id='io'/>\n"
" <rom name='program.rom' size='", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='40-5f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:0000-ffff' id='rom' mode='linear'/>\n"
);
if(ram_size > 0) markup.append(
" <ram name='save.rwm' size='", hex(ram_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='ram' mode='linear' size='0x2000'/>\n"
" <map address='80-bf:6000-7fff' id='ram' mode='linear' size='0x2000'/>\n"
" <map address='60-7f:0000-ffff' id='ram' mode='linear'/>\n"
" <map address='e0-ff:0000-ffff' id='ram' mode='linear'/>\n"
);
markup.append(
" </superfx>\n"
);
}
else if(mapper == SA1ROM) {
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
if(ram_size > 0)
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
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 >\n"
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
" </iram>\n"
" <bwram>\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"
" <map address='00-3f:2200-23ff' id='io'/>\n"
" <map address='80-bf:2200-23ff' id='io'/>\n"
" <rom name='program.rom' size='", hex(rom_size), "'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" <iram size='0x800'/>\n"
" <map address='00-3f:3000-37ff' id='iram'/>\n"
" <map address='80-bf:3000-37ff' id='iram'/>\n"
);
if(ram_size > 0) markup.append(
" <bwram name='save.rwm' size='", hex(ram_size), "'/>\n"
" <map address='00-3f:6000-7fff' id='bwram'/>\n"
" <map address='80-bf:6000-7fff' id='bwram'/>\n"
" <map address='40-4f:0000-ffff' id='bwram'/>\n"
);
markup.append(
" </sa1>\n"
);
}
else if(mapper == BSCLoROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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 name='save.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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='linear' offset='0x000000'/>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='linear' offset='0x100000'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='linear' offset='0x200000'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='linear' offset='0x100000'/>\n"
" <map address='70-7f:0000-7fff' id='ram' mode='linear'/>\n"
" <map address='f0-ff:0000-7fff' id='ram' mode='linear'/>\n"
" <bsxslot>\n"
" <map address='c0-ef:0000-ffff' id='rom' mode='linear'/>\n"
" </bsxslot>\n"
);
else if(mapper == BSCHiROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\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 name='save.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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='40-5f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='20-3f:6000-7fff' id='ram' mode='linear'/>\n"
" <map address='a0-bf:6000-7fff' id='ram' mode='linear'/>\n"
" <bsxslot>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='shadow'/>\n"
" <map address='60-7f:0000-ffff' id='rom' mode='linear'/>\n"
" <map address='e0-ff:0000-ffff' id='rom' mode='linear'/>\n"
" </bsxslot>\n"
);
else if(mapper == BSXROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n"
" <psram name='bsx.ram' size='0x40000'/>\n"
" <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"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <ram name='save.rwm' size='0x", hex(ram_size), "'/>\n"
" <psram name='bsx.rwm' size='0x40000'/>\n"
" <map address='00-3f:5000-5fff' id='io'/>\n"
" <map address='80-bf:5000-5fff' id='io'/>\n"
" <map address='20-3f:6000-7fff' id='ram'/>\n"
" <map address='00-3f:8000-ffff' id='rom'/>\n"
" <map address='80-bf:8000-ffff' id='rom'/>\n"
" <map address='40-7f:0000-ffff' id='rom'/>\n"
" <map address='c0-ff:0000-ffff' id='rom'/>\n"
" </bsx>\n"
);
else if(mapper == STROM) markup.append(
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
" </rom>\n"
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
" <map address='00-1f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='80-9f:8000-ffff' id='rom' mode='linear'/>\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>\n"
" <map mode='linear' address='60-63:8000-ffff'/>\n"
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
" </ram>\n"
" <map address='20-3f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='a0-bf:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='60-63:8000-ffff' id='ram' mode='linear'/>\n"
" <map address='e0-e3:8000-ffff' id='ram' mode='linear'/>\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>\n"
" <map mode='linear' address='70-73:8000-ffff'/>\n"
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
" </ram>\n"
" <map address='40-5f:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='c0-df:8000-ffff' id='rom' mode='linear'/>\n"
" <map address='70-73:8000-ffff' id='ram' mode='linear'/>\n"
" <map address='f0-f3:8000-ffff' id='ram' mode='linear'/>\n"
" </slot>\n"
" </sufamiturbo>\n"
);
if(has_srtc) markup.append(
" <sharprtc name='rtc.ram' size='0x10'>\n"
" <map address='00-3f:2800-2801'/>\n"
" <map address='80-bf:2800-2801'/>\n"
" </sharprtc>\n"
if(has_spc7110rtc) markup.append(
" <epsonrtc>\n"
" <ram name='rtc.rwm' size='0x10'/>\n"
" <map address='00-3f:4840-4842' id='io'/>\n"
" <map address='80-bf:4840-4842' id='io'/>\n"
" </epsonrtc>\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_srtc) markup.append(
" <sharprtc>\n"
" <ram name='rtc.rwm' size='0x10'/>\n"
" <map address='00-3f:2800-2801' id='io'/>\n"
" <map address='80-bf:2800-2801' id='io'/>\n"
" </sharprtc>\n"
);
if(has_obc1) markup.append(
" <obc1>\n"
" <map address='00-3f:6000-7fff'/>\n"
" <map address='80-bf:6000-7fff'/>\n"
" <ram name='save.rwm' size='0x2000'/>\n"
" <map address='00-3f:6000-7fff' id='io'/>\n"
" <map address='80-bf:6000-7fff' id='io'/>\n"
" </obc1>\n"
);
if(has_dsp1) {
//91e87d11e1c30d172556bed2211cce2efa94ba595f58c5d264809ef4d363a97b dsp1.rom
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.rom' sha256='d789cb3c36b05c0b23b6c6f23be7aa37c6e78b6ee9ceac8d2d2aa9d8c4d35fa9'>\n");
markup.append(
" <necdsp model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp1b.rom' size='8192' sha256='d789cb3c36b05c0b23b6c6f23be7aa37c6e78b6ee9ceac8d2d2aa9d8c4d35fa9'/>\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"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='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"
" <map address='60-6f:0000-3fff' id='dr'/>\n"
" <map address='e0-ef:0000-3fff' id='dr'/>\n"
" <map address='60-6f:4000-7fff' id='sr'/>\n"
" <map address='e0-ef:4000-7fff' id='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"
" <map address='00-1f:6000-6fff' id='dr'/>\n"
" <map address='80-9f:6000-6fff' id='dr'/>\n"
" <map address='00-1f:7000-7fff' id='sr'/>\n"
" <map address='80-9f:7000-7fff' id='sr'/>\n"
);
markup.append(
" </necdsp>\n"
);
markup.append(" </necdsp>\n");
}
if(has_dsp2) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.rom' sha256='03ef4ef26c9f701346708cb5d07847b5203cf1b0818bf2930acd34510ffdd717'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp2.rom' size='8192' sha256='03ef4ef26c9f701346708cb5d07847b5203cf1b0818bf2930acd34510ffdd717'/>\n"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_dsp3) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.rom' sha256='0971b08f396c32e61989d1067dddf8e4b14649d548b2188f7c541b03d7c69e4e'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp3.rom' size='8192' sha256='0971b08f396c32e61989d1067dddf8e4b14649d548b2188f7c541b03d7c69e4e'/>\n"
" <map address='20-3f:8000-bfff' id='dr'/>\n"
" <map address='a0-bf:8000-bfff' id='dr'/>\n"
" <map address='20-3f:c000-ffff' id='sr'/>\n"
" <map address='a0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_dsp4) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.rom' sha256='752d03b2d74441e430b7f713001fa241f8bbcfc1a0d890ed4143f174dbe031da'>\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 model='uPD7725' frequency='8000000'>\n"
" <firmware name='dsp4.rom' size='8192' sha256='752d03b2d74441e430b7f713001fa241f8bbcfc1a0d890ed4143f174dbe031da'/>\n"
" <map address='30-3f:8000-bfff' id='dr'/>\n"
" <map address='b0-bf:8000-bfff' id='dr'/>\n"
" <map address='30-3f:c000-ffff' id='sr'/>\n"
" <map address='b0-bf:c000-ffff' id='sr'/>\n"
" </necdsp>\n"
);
if(has_st010) markup.append(
" <necdsp model='uPD96050' frequency='10000000' firmware='st010.rom' sha256='fa9bced838fedea11c6f6ace33d1878024bdd0d02cc9485899d0bdd4015ec24c'>\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 model='uPD96050' frequency='10000000'>\n"
" <firmware name='st010.rom' size='53248' sha256='fa9bced838fedea11c6f6ace33d1878024bdd0d02cc9485899d0bdd4015ec24c'/>\n"
" <ram name='save.rwm' size='0x1000'/>\n"
" <map address='60:0000' id='dr'/>\n"
" <map address='e0:0000' id='dr'/>\n"
" <map address='60:0001' id='sr'/>\n"
" <map address='e0:0001' id='sr'/>\n"
" <map address='68-6f:0000-0fff' id='ram'/>\n"
" <map address='e8-ef:0000-0fff' id='ram'/>\n"
" </necdsp>\n"
);
if(has_st011) markup.append(
" <necdsp model='uPD96050' frequency='15000000' firmware='st011.rom' sha256='8b2b3f3f3e6e29f4d21d8bc736b400bc988b7d2214ebee15643f01c1fee2f364'>\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 model='uPD96050' frequency='15000000'>\n"
" <firmware name='st011.rom' size='53248' sha256='8b2b3f3f3e6e29f4d21d8bc736b400bc988b7d2214ebee15643f01c1fee2f364'/>\n"
" <ram name='save.rwm' size='0x1000'/>\n"
" <map address='60:0000' id='dr'/>\n"
" <map address='e0:0000' id='dr'/>\n"
" <map address='60:0001' id='sr'/>\n"
" <map address='e0:0001' id='sr'/>\n"
" <map address='68-6f:0000-0fff' id='ram'/>\n"
" <map address='e8-ef:0000-0fff' id='ram'/>\n"
" </necdsp>\n"
);
if(has_st018) markup.append(
" <armdsp firmware='st018.rom' frequency='21477272' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'>\n"
" <map address='00-3f:3800-38ff'/>\n"
" <map address='80-bf:3800-38ff'/>\n"
" <armdsp frequency='21477272'>\n"
" <firmware name='st018.rom' size='163840' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'/>\n"
" <map address='00-3f:3800-38ff' id='io'/>\n"
" <map address='80-bf:3800-38ff' id='io'/>\n"
" </armdsp>\n"
);

View File

@ -66,6 +66,14 @@ namespace nall {
return memory;
}
static bool read(const string &filename, uint8_t *data, unsigned size) {
file fp;
if(fp.open(filename, mode::read) == false) return false;
fp.read(data, size);
fp.close();
return true;
}
static bool write(const string &filename, const uint8_t *data, unsigned size) {
file fp;
if(fp.open(filename, mode::write) == false) return false;

56
purify/nall/nall.hpp Executable file
View File

@ -0,0 +1,56 @@
#ifndef NALL_HPP
#define NALL_HPP
//include the most common nall headers with one statement
//does not include the most obscure components with high cost and low usage
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/any.hpp>
#include <nall/atoi.hpp>
#include <nall/base64.hpp>
#include <nall/bit.hpp>
#include <nall/bmp.hpp>
#include <nall/config.hpp>
#include <nall/crc32.hpp>
#include <nall/directory.hpp>
#include <nall/dl.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/filemap.hpp>
#include <nall/function.hpp>
#include <nall/gzip.hpp>
#include <nall/http.hpp>
#include <nall/image.hpp>
#include <nall/inflate.hpp>
#include <nall/interpolation.hpp>
#include <nall/intrinsics.hpp>
#include <nall/invoke.hpp>
#include <nall/map.hpp>
#include <nall/png.hpp>
#include <nall/property.hpp>
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/set.hpp>
#include <nall/sha256.hpp>
#include <nall/sort.hpp>
#include <nall/stdint.hpp>
#include <nall/stream.hpp>
#include <nall/string.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/zip.hpp>
#if defined(PLATFORM_WINDOWS)
#include <nall/windows/registry.hpp>
#include <nall/windows/utf8.hpp>
#endif
#if defined(PLATFORM_X)
#include <nall/serial.hpp>
#endif
#endif

View File

@ -20,7 +20,9 @@ struct zipstream : memorystream {
for(auto &file : archive.file) {
if(file.name.wildcard(filter)) {
archive.extract(file, pdata, psize);
auto buffer = archive.extract(file);
psize = buffer.size();
pdata = buffer.move();
return;
}
}

View File

@ -2,59 +2,71 @@
namespace nall {
// "foo/bar.c" -> "foo/"
// "foo/" -> "foo/"
// "/foo/bar.c" -> "/foo/"
// "/foo/" -> "/foo/"
// "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
inline string dir(string name) {
for(signed i = name.length(); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
name[i + 1] = 0;
break;
}
if(i == 0) name = "./";
}
string result = name;
return result;
return name;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
// "/foo/bar.c" -> "bar.c"
// "/foo/" -> ""
// "bar.c" -> "bar.c"
inline string notdir(string name) {
for(signed i = name.length(); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
return (const char*)name + i + 1;
}
}
return result;
return name;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
// "/foo/bar/baz" -> "/foo/bar/"
// "/foo/bar/" -> "/foo/"
// "/foo/bar" -> "/foo/"
inline string parentdir(string name) {
unsigned length = name.length(), paths = 0, prev, last;
for(unsigned i = 0; i < length; i++) {
if(name[i] == '/' || name[i] == '\\') {
paths++;
prev = last;
last = i;
}
}
if(last + 1 == length) last = prev; //if name ends in slash; use previous slash
if(paths > 1) name[last + 1] = 0;
return name;
}
// "/foo/bar.c" -> "/foo/bar"
inline string basename(string name) {
for(signed i = name.length(); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') break; //file has no extension
if(name[i] == '.') {
name += i + 1;
name[i] = 0;
break;
}
}
string result = name;
return result;
return name;
}
// "/foo/bar.c" -> "c"
// "/foo/bar" -> ""
inline string extension(string name) {
for(signed i = name.length(); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') return ""; //file has no extension
if(name[i] == '.') {
return (const char*)name + i + 1;
}
}
return name;
}
}

View File

@ -24,10 +24,18 @@ namespace nall {
operator bool() const { return pool; }
T* data() { return pool; }
bool empty() const { return pool == nullptr; }
bool empty() const { return objectsize == 0; }
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
T* move() {
T *result = data;
pool = nullptr;
poolsize = 0;
objectsize = 0;
return result;
}
void reset() {
if(pool) {
for(unsigned n = 0; n < objectsize; n++) pool[n].~T();
@ -97,6 +105,13 @@ namespace nall {
return item;
}
void reverse() {
unsigned pivot = size() / 2;
for(unsigned l = 0, r = size() - 1; l < pivot; l++, r--) {
std::swap(pool[l], pool[r]);
}
}
void sort() {
nall::sort(pool, objectsize);
}
@ -184,293 +199,6 @@ namespace nall {
reset();
}
};
//linear_vector
//memory: O(capacity * 2)
//
//linear_vector uses placement new + manual destructor calls to create a
//contiguous block of memory for all objects. accessing individual elements
//is fast, though resizing the array incurs significant overhead.
//reserve() overhead is reduced from quadratic time to amortized constant time
//by resizing twice as much as requested.
//
//if objects hold memory address references to themselves (introspection), a
//valid copy constructor will be needed to keep pointers valid.
#define NALL_DEPRECATED
#if defined(NALL_DEPRECATED)
template<typename T> struct linear_vector {
protected:
T *pool;
unsigned poolsize, objectsize;
public:
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
void reset() {
if(pool) {
for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
free(pool);
}
pool = nullptr;
poolsize = 0;
objectsize = 0;
}
void reserve(unsigned newsize) {
newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
T *poolcopy = (T*)calloc(newsize, sizeof(T));
for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]);
for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
free(pool);
pool = poolcopy;
poolsize = newsize;
objectsize = min(objectsize, newsize);
}
void resize(unsigned newsize) {
if(newsize > poolsize) reserve(newsize);
if(newsize < objectsize) {
//vector is shrinking; destroy excess objects
for(unsigned i = newsize; i < objectsize; i++) pool[i].~T();
} else if(newsize > objectsize) {
//vector is expanding; allocate new objects
for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T;
}
objectsize = newsize;
}
void append(const T data) {
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
new(pool + objectsize++) T(data);
}
template<typename U> void insert(unsigned index, const U list) {
linear_vector<T> merged;
for(unsigned i = 0; i < index; i++) merged.append(pool[i]);
for(auto &item : list) merged.append(item);
for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]);
operator=(merged);
}
void insert(unsigned index, const T item) {
insert(index, linear_vector<T>{ item });
}
void remove(unsigned index, unsigned count = 1) {
for(unsigned i = index; count + i < objectsize; i++) {
pool[i] = pool[count + i];
}
if(count + index >= objectsize) resize(index); //every element >= index was removed
else resize(objectsize - count);
}
linear_vector() : pool(nullptr), poolsize(0), objectsize(0) {
}
linear_vector(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
}
~linear_vector() {
reset();
}
//copy
inline linear_vector<T>& operator=(const linear_vector<T> &source) {
reset();
reserve(source.capacity());
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
linear_vector(const linear_vector<T> &source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(source);
}
//move
inline linear_vector<T>& operator=(linear_vector<T> &&source) {
reset();
pool = source.pool;
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = nullptr;
source.reset();
return *this;
}
linear_vector(linear_vector<T> &&source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//index
inline T& operator[](unsigned index) {
if(index >= objectsize) resize(index + 1);
return pool[index];
}
inline const T& operator[](unsigned index) const {
if(index >= objectsize) throw "vector[] out of bounds";
return pool[index];
}
//iteration
T* begin() { return &pool[0]; }
T* end() { return &pool[objectsize]; }
const T* begin() const { return &pool[0]; }
const T* end() const { return &pool[objectsize]; }
};
//pointer_vector
//memory: O(1)
//
//pointer_vector keeps an array of pointers to each vector object. this adds
//significant overhead to individual accesses, but allows for optimal memory
//utilization.
//
//by guaranteeing that the base memory address of each objects never changes,
//this avoids the need for an object to have a valid copy constructor.
template<typename T> struct pointer_vector {
protected:
T **pool;
unsigned poolsize, objectsize;
public:
unsigned size() const { return objectsize; }
unsigned capacity() const { return poolsize; }
void reset() {
if(pool) {
for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; }
free(pool);
}
pool = nullptr;
poolsize = 0;
objectsize = 0;
}
void reserve(unsigned newsize) {
newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
for(unsigned i = newsize; i < objectsize; i++) {
if(pool[i]) { delete pool[i]; pool[i] = 0; }
}
pool = (T**)realloc(pool, newsize * sizeof(T*));
for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0;
poolsize = newsize;
objectsize = min(objectsize, newsize);
}
void resize(unsigned newsize) {
if(newsize > poolsize) reserve(newsize);
for(unsigned i = newsize; i < objectsize; i++) {
if(pool[i]) { delete pool[i]; pool[i] = 0; }
}
objectsize = newsize;
}
void append(const T data) {
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
pool[objectsize++] = new T(data);
}
template<typename U> void insert(unsigned index, const U list) {
pointer_vector<T> merged;
for(unsigned i = 0; i < index; i++) merged.append(*pool[i]);
for(auto &item : list) merged.append(item);
for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]);
operator=(merged);
}
void insert(unsigned index, const T item) {
insert(index, pointer_vector<T>{ item });
}
void remove(unsigned index, unsigned count = 1) {
for(unsigned i = index; count + i < objectsize; i++) {
*pool[i] = *pool[count + i];
}
if(count + index >= objectsize) resize(index); //every element >= index was removed
else resize(objectsize - count);
}
pointer_vector() : pool(nullptr), poolsize(0), objectsize(0) {
}
pointer_vector(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
}
~pointer_vector() {
reset();
}
//copy
inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
reset();
reserve(source.capacity());
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
pointer_vector(const pointer_vector<T> &source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(source);
}
//move
inline pointer_vector<T>& operator=(pointer_vector<T> &&source) {
reset();
pool = source.pool;
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = nullptr;
source.reset();
return *this;
}
pointer_vector(pointer_vector<T> &&source) : pool(nullptr), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//index
inline T& operator[](unsigned index) {
if(index >= objectsize) resize(index + 1);
if(!pool[index]) pool[index] = new T;
return *pool[index];
}
inline const T& operator[](unsigned index) const {
if(index >= objectsize || !pool[index]) throw "vector[] out of bounds";
return *pool[index];
}
//iteration
struct iterator {
bool operator!=(const iterator &source) const { return index != source.index; }
T& operator*() { return vector.operator[](index); }
iterator& operator++() { index++; return *this; }
iterator(const pointer_vector &vector, unsigned index) : vector(vector), index(index) {}
private:
const pointer_vector &vector;
unsigned index;
};
iterator begin() { return iterator(*this, 0); }
iterator end() { return iterator(*this, objectsize); }
const iterator begin() const { return iterator(*this, 0); }
const iterator end() const { return iterator(*this, objectsize); }
};
#endif
}
#endif

View File

@ -19,7 +19,8 @@ using namespace phoenix;
#include "resource/resource.cpp"
struct Settings : configuration {
bool play;
bool ui; //true if in user-interface mode (windows visible); false if in command-line mode
bool play; //true if emulator should be launched after game conversion
lstring extensions;
string emulator;
@ -27,6 +28,7 @@ struct Settings : configuration {
string recent;
Settings() {
ui = false;
play = false;
extensions = {".fc", ".nes", ".sfc", ".smc", ".swc", ".fig", ".bs", ".st", ".gb", ".gbc", ".sgb", ".gba"};
@ -71,7 +73,7 @@ void create_famicom(const string &filename, uint8_t *data, unsigned size) {
file::write({path, "manifest.xml"}, (const uint8_t*)information.markup(), information.markup.length());
if(information.prgrom > 0) file::write({path, "program.rom"}, data, information.prgrom);
if(information.chrrom > 0) file::write({path, "character.rom"}, data + information.prgrom, information.chrrom);
if(!file::exists({path, "save.ram"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.ram"});
if(!file::exists({path, "save.rwm"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.rwm"});
if(settings.play) play(path);
}
@ -88,8 +90,13 @@ void create_super_famicom(const string &filename, uint8_t *data, unsigned size)
if((size & 0x7fff) == 512) data += 512, size -= 512;
file::write({path, "manifest.xml"}, (const uint8_t*)information.markup(), information.markup.length());
file::write({path, "program.rom"}, data, size);
if(!file::exists({path, "save.ram"})) file::copy({nall::basename(filename), ".srm"}, {path, "save.ram"});
if(information.markup.position("<spc7110>") && size >= 0x100000) {
file::write({path, "program.rom"}, data, 0x100000);
file::write({path, "data.rom"}, data + 0x100000, size - 0x100000);
} else {
file::write({path, "program.rom"}, data, size);
}
if(!file::exists({path, "save.rwm"})) file::copy({nall::basename(filename), ".srm"}, {path, "save.rwm"});
//firmware
if(auto position = information.markup.position("firmware=")) {
@ -130,7 +137,7 @@ void create_sufami_turbo(const string &filename, uint8_t *data, unsigned size) {
file::write({path, "manifest.xml"}, (const uint8_t*)information.markup(), information.markup.length());
file::write({path, "program.rom"}, data, size);
if(!file::exists({path, "save.ram"})) file::copy({nall::basename(filename), ".srm"}, {path, "save.ram"});
if(!file::exists({path, "save.rwm"})) file::copy({nall::basename(filename), ".srm"}, {path, "save.rwm"});
}
void create_game_boy(const string &filename, uint8_t *data, unsigned size) {
@ -146,7 +153,7 @@ void create_game_boy(const string &filename, uint8_t *data, unsigned size) {
file::write({path, "manifest.xml"}, (const uint8_t*)information.markup(), information.markup.length());
file::write({path, "program.rom"}, data, size);
if(!file::exists({path, "save.ram"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.ram"});
if(!file::exists({path, "save.rwm"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.rwm"});
if(settings.play) play(path);
}
@ -161,7 +168,7 @@ void create_game_boy_advance(const string &filename, uint8_t *data, unsigned siz
file::write({path, "manifest.xml"}, (const uint8_t*)information.markup(), information.markup.length());
file::write({path, "program.rom"}, data, size);
if(!file::exists({path, "save.ram"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.ram"});
if(!file::exists({path, "save.rwm"})) file::copy({nall::basename(filename), ".sav"}, {path, "save.rwm"});
if(settings.play) play(path);
}
@ -262,6 +269,14 @@ void create_folder(string pathname) {
pathname.transform("\\", "/");
if(pathname.endswith("/") == false) pathname.append("/");
if(pathname == settings.path) {
print(
"You cannot use the same path for both the source and destination directories.\n"
"Please choose a different output path in settings.cfg.\n"
);
return;
}
lstring files = directory::contents(pathname);
for(auto &name : files) {
if(directory::exists({pathname, name}) && valid_extension(name)) {
@ -368,7 +383,7 @@ struct Application : Window {
Label pathValue;
Application() {
setTitle("purify v00.04");
setTitle("purify v00.06");
setGeometry({128, 128, 440, 180});
layout.setMargin(5);
title.setFont("Sans, 16, Bold");
@ -435,10 +450,18 @@ struct Application : Window {
void convertAction() {
string pathname = DialogWindow::folderSelect(*this, settings.recent);
if(!pathname.empty()) {
settings.recent = pathname;
progress->convert(pathname);
if(pathname.empty()) return;
if(pathname == settings.path) {
MessageWindow::critical(*this,
"You cannot use the same path for both the source and destination directories.\n\n"
"Please choose a different output path."
);
return;
}
settings.recent = pathname;
progress->convert(pathname);
}
void emulatorAction() {
@ -492,6 +515,7 @@ int main(int argc, char **argv) {
return 0;
}
settings.ui = true;
progress = new Progress;
application = new Application;
OS::main();