mirror of https://github.com/bsnes-emu/bsnes.git
Update to v074r03 release.
byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
This commit is contained in:
parent
5810e69be3
commit
2d73086569
|
@ -22,7 +22,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
|
GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
|
||||||
xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
if(romsize < 0x4000) return;
|
if(romsize < 0x4000) return;
|
||||||
|
|
||||||
info.mapper = "unknown";
|
info.mapper = "unknown";
|
||||||
|
@ -97,6 +97,7 @@ GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
|
||||||
xml << " <ram size='" << hex(info.ramsize) << "' battery='" << info.battery << "'/>\n";
|
xml << " <ram size='" << hex(info.ramsize) << "' battery='" << info.battery << "'/>\n";
|
||||||
|
|
||||||
xml << "</cartridge>\n";
|
xml << "</cartridge>\n";
|
||||||
|
xml.transform("'", "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,13 +112,13 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
|
||||||
if(type == TypeBsx) {
|
if(type == TypeBsx) {
|
||||||
xml << "<cartridge/>";
|
xml << "<cartridge/>";
|
||||||
xmlMemoryMap = xml;
|
xmlMemoryMap = xml.transform("'", "\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == TypeSufamiTurbo) {
|
if(type == TypeSufamiTurbo) {
|
||||||
xml << "<cartridge/>";
|
xml << "<cartridge/>";
|
||||||
xmlMemoryMap = xml;
|
xmlMemoryMap = xml.transform("'", "\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
xml << " <ram size='" << hex(gameboy_ram_size(data, size)) << "'/>\n";
|
xml << " <ram size='" << hex(gameboy_ram_size(data, size)) << "'/>\n";
|
||||||
}
|
}
|
||||||
xml << "</cartridge>\n";
|
xml << "</cartridge>\n";
|
||||||
xmlMemoryMap = xml;
|
xmlMemoryMap = xml.transform("'", "\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,19 +279,23 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
xml << " </superfx>\n";
|
xml << " </superfx>\n";
|
||||||
} else if(mapper == SA1ROM) {
|
} else if(mapper == SA1ROM) {
|
||||||
xml << " <sa1>\n";
|
xml << " <sa1>\n";
|
||||||
xml << " <rom>\n";
|
xml << " <mcu>\n";
|
||||||
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
|
xml << " <rom>\n";
|
||||||
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
|
xml << " <map mode='direct' address='00-3f:8000-ffff'/>\n";
|
||||||
xml << " <map mode='linear' address='c0-ff:0000-ffff'/>\n";
|
xml << " <map mode='direct' address='80-bf:8000-ffff'/>\n";
|
||||||
xml << " </rom>\n";
|
xml << " <map mode='direct' address='c0-ff:0000-ffff'/>\n";
|
||||||
|
xml << " </rom>\n";
|
||||||
|
xml << " <ram>\n";
|
||||||
|
xml << " <map mode='direct' address='00-3f:6000-7fff'/>\n";
|
||||||
|
xml << " <map mode='direct' address='80-bf:6000-7fff'/>\n";
|
||||||
|
xml << " </ram>\n";
|
||||||
|
xml << " </mcu>\n";
|
||||||
xml << " <iram size='800'>\n";
|
xml << " <iram size='800'>\n";
|
||||||
xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
|
xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
|
||||||
xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
|
xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
|
||||||
xml << " </iram>\n";
|
xml << " </iram>\n";
|
||||||
xml << " <bwram size='" << hex(ram_size) << "'>\n";
|
xml << " <bwram size='" << hex(ram_size) << "'>\n";
|
||||||
xml << " <map mode='linear' address='00-3f:6000-7fff'/>\n";
|
|
||||||
xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
|
xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
|
||||||
xml << " <map mode='linear' address='80-bf:6000-7fff'/>\n";
|
|
||||||
xml << " </bwram>\n";
|
xml << " </bwram>\n";
|
||||||
xml << " <mmio>\n";
|
xml << " <mmio>\n";
|
||||||
xml << " <map address='00-3f:2200-23ff'/>\n";
|
xml << " <map address='00-3f:2200-23ff'/>\n";
|
||||||
|
@ -402,48 +406,72 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
if(has_dsp1) {
|
if(has_dsp1) {
|
||||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
||||||
if(dsp1_mapper == DSP1LoROM1MB) {
|
if(dsp1_mapper == DSP1LoROM1MB) {
|
||||||
xml << " <dr mask='004000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='004000' test='004000'/>\n";
|
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||||
|
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
} else if(dsp1_mapper == DSP1LoROM2MB) {
|
} else if(dsp1_mapper == DSP1LoROM2MB) {
|
||||||
xml << " <dr mask='004000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='004000' test='004000'/>\n";
|
xml << " <map address='60-6f:0000-3fff'/>\n";
|
||||||
xml << " <map address='60-6f:0000-7fff'/>\n";
|
xml << " <map address='e0-ef:0000-3fff'/>\n";
|
||||||
xml << " <map address='e0-ef:0000-7fff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='60-6f:4000-7fff'/>\n";
|
||||||
|
xml << " <map address='e0-ef:4000-7fff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
} else if(dsp1_mapper == DSP1HiROM) {
|
} else if(dsp1_mapper == DSP1HiROM) {
|
||||||
xml << " <dr mask='001000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='001000' test='001000'/>\n";
|
xml << " <map address='00-1f:6000-6fff'/>\n";
|
||||||
xml << " <map address='00-1f:6000-7fff'/>\n";
|
xml << " <map address='80-9f:6000-6fff'/>\n";
|
||||||
xml << " <map address='80-9f:6000-7fff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='00-1f:7000-7fff'/>\n";
|
||||||
|
xml << " <map address='80-9f:7000-7fff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
}
|
}
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(has_dsp2) {
|
if(has_dsp2) {
|
||||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
||||||
xml << " <dr mask='004000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='004000' test='004000'/>\n";
|
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||||
|
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(has_dsp3) {
|
if(has_dsp3) {
|
||||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
||||||
xml << " <dr mask='004000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='004000' test='004000'/>\n";
|
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||||
|
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(has_dsp4) {
|
if(has_dsp4) {
|
||||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
||||||
xml << " <dr mask='004000' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='004000' test='004000'/>\n";
|
xml << " <map address='30-3f:8000-bfff'/>\n";
|
||||||
xml << " <map address='30-3f:8000-ffff'/>\n";
|
xml << " <map address='b0-bf:8000-bfff'/>\n";
|
||||||
xml << " <map address='b0-bf:8000-ffff'/>\n";
|
xml << " </dr>\n";
|
||||||
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='30-3f:c000-ffff'/>\n";
|
||||||
|
xml << " <map address='b0-bf:c000-ffff'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,21 +484,35 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
|
||||||
if(has_st010) {
|
if(has_st010) {
|
||||||
xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
||||||
xml << " <dr mask='080001' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='080001' test='000001'/>\n";
|
xml << " <map address='60:0000'/>\n";
|
||||||
xml << " <dp mask='080000' test='080000'/>\n";
|
xml << " <map address='e0:0000'/>\n";
|
||||||
xml << " <map address='60-6f:0000-0fff'/>\n";
|
xml << " </dr>\n";
|
||||||
xml << " <map address='e0-ef:0000-0fff'/>\n";
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='60:0001'/>\n";
|
||||||
|
xml << " <map address='e0:0001'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
|
xml << " <dp>\n";
|
||||||
|
xml << " <map address='68-6f:0000-0fff'/>\n";
|
||||||
|
xml << " <map address='e8-ef:0000-0fff'/>\n";
|
||||||
|
xml << " </dp>\n";
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(has_st011) {
|
if(has_st011) {
|
||||||
xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
|
xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
|
||||||
xml << " <dr mask='080001' test='000000'/>\n";
|
xml << " <dr>\n";
|
||||||
xml << " <sr mask='080001' test='000001'/>\n";
|
xml << " <map address='60:0000'/>\n";
|
||||||
xml << " <dp mask='080000' test='080000'/>\n";
|
xml << " <map address='e0:0000'/>\n";
|
||||||
xml << " <map address='60-6f:0000-0fff'/>\n";
|
xml << " </dr>\n";
|
||||||
xml << " <map address='e0-ef:0000-0fff'/>\n";
|
xml << " <sr>\n";
|
||||||
|
xml << " <map address='60:0001'/>\n";
|
||||||
|
xml << " <map address='e0:0001'/>\n";
|
||||||
|
xml << " </sr>\n";
|
||||||
|
xml << " <dp>\n";
|
||||||
|
xml << " <map address='68-6f:0000-0fff'/>\n";
|
||||||
|
xml << " <map address='e8-ef:0000-0fff'/>\n";
|
||||||
|
xml << " </dp>\n";
|
||||||
xml << " </necdsp>\n";
|
xml << " </necdsp>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +524,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
xml << "</cartridge>\n";
|
xml << "</cartridge>\n";
|
||||||
xmlMemoryMap = xml;
|
xmlMemoryMap = xml.transform("'", "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SNESCartridge::read_header(const uint8_t *data, unsigned size) {
|
void SNESCartridge::read_header(const uint8_t *data, unsigned size) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
|
class CPU : public Processor, public CPUcore, public PPUcounter {
|
||||||
public:
|
public:
|
||||||
enum : bool { Threaded = true };
|
enum : bool { Threaded = true };
|
||||||
array<Processor*> coprocessors;
|
array<Processor*> coprocessors;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class PPU : public Processor, public PPUcounter, public MMIO {
|
class PPU : public Processor, public PPUcounter {
|
||||||
public:
|
public:
|
||||||
enum : bool { Threaded = true };
|
enum : bool { Threaded = true };
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class PPU : public Processor, public PPUcounter, public MMIO {
|
class PPU : public Processor, public PPUcounter {
|
||||||
public:
|
public:
|
||||||
enum : bool { Threaded = true };
|
enum : bool { Threaded = true };
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
|
|
|
@ -38,7 +38,7 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
|
||||||
has_serial = false;
|
has_serial = false;
|
||||||
|
|
||||||
parse_xml(xml_list);
|
parse_xml(xml_list);
|
||||||
//print(xml_list[0], "\n\n");
|
print(xml_list[0], "\n\n");
|
||||||
|
|
||||||
if(ram_size > 0) {
|
if(ram_size > 0) {
|
||||||
memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
|
memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
|
||||||
|
|
|
@ -40,8 +40,8 @@ public:
|
||||||
readonly<bool> has_serial;
|
readonly<bool> has_serial;
|
||||||
|
|
||||||
struct Mapping {
|
struct Mapping {
|
||||||
Memory *memory;
|
function<uint8 (unsigned)> read;
|
||||||
MMIO *mmio;
|
function<void (unsigned, uint8)> write;
|
||||||
Bus::MapMode mode;
|
Bus::MapMode mode;
|
||||||
unsigned banklo;
|
unsigned banklo;
|
||||||
unsigned bankhi;
|
unsigned bankhi;
|
||||||
|
@ -51,10 +51,10 @@ public:
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
|
||||||
Mapping();
|
Mapping();
|
||||||
|
Mapping(const function<uint8 (unsigned)>&, const function<void (unsigned, uint8)>&);
|
||||||
Mapping(Memory&);
|
Mapping(Memory&);
|
||||||
Mapping(MMIO&);
|
|
||||||
};
|
};
|
||||||
array<Mapping> mapping;
|
linear_vector<Mapping> mapping;
|
||||||
|
|
||||||
void load(Mode, const lstring&);
|
void load(Mode, const lstring&);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
|
@ -70,6 +70,7 @@ void Cartridge::xml_parse_rom(xml_element &root) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
|
if(m.size == 0) m.size = memory::cartrom.size() - m.offset;
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +90,7 @@ void Cartridge::xml_parse_ram(xml_element &root) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
|
if(m.size == 0) m.size = ram_size - m.offset;
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +109,7 @@ void Cartridge::xml_parse_icd2(xml_element &root) {
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "map") {
|
if(node.name == "map") {
|
||||||
Mapping m((Memory&)icd2);
|
Mapping m({ &ICD2::read, &icd2 }, { &ICD2::write, &icd2 });
|
||||||
foreach(attr, node.attribute) {
|
foreach(attr, node.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -147,13 +149,14 @@ void Cartridge::xml_parse_superfx(xml_element &root) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
|
if(m.size == 0) m.size = ram_size;
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(node.name == "mmio") {
|
} else if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(superfx);
|
Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -168,17 +171,31 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||||
has_sa1 = true;
|
has_sa1 = true;
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "rom") {
|
if(node.name == "mcu") {
|
||||||
foreach(leaf, node.element) {
|
foreach(subnode, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(subnode.name == "rom") {
|
||||||
Mapping m(memory::vsprom);
|
foreach(leaf, subnode.element) {
|
||||||
foreach(attr, leaf.attribute) {
|
if(leaf.name == "map") {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||||
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
|
}
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(subnode.name == "ram") {
|
||||||
|
foreach(leaf, subnode.element) {
|
||||||
|
if(leaf.name == "map") {
|
||||||
|
Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 });
|
||||||
|
foreach(attr, leaf.attribute) {
|
||||||
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
|
}
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mapping.append(m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(node.name == "iram") {
|
} else if(node.name == "iram") {
|
||||||
|
@ -191,6 +208,7 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
|
if(m.size == 0) m.size = 2048;
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,13 +226,14 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
|
if(m.size == 0) m.size = ram_size;
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(node.name == "mmio") {
|
} else if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(sa1);
|
Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -276,33 +295,36 @@ void Cartridge::xml_parse_necdsp(xml_element &root) {
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "dr") {
|
if(node.name == "dr") {
|
||||||
foreach(attr, node.attribute) {
|
foreach(leaf, node.element) {
|
||||||
if(attr.name == "mask") necdsp.drmask = hex(attr.content);
|
if(leaf.name == "map") {
|
||||||
if(attr.name == "test") necdsp.drtest = hex(attr.content);
|
Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp });
|
||||||
|
foreach(attr, leaf.attribute) {
|
||||||
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
|
}
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if(node.name == "sr") {
|
||||||
|
foreach(leaf, node.element) {
|
||||||
if(node.name == "sr") {
|
if(leaf.name == "map") {
|
||||||
foreach(attr, node.attribute) {
|
Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp });
|
||||||
if(attr.name == "mask") necdsp.srmask = hex(attr.content);
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "test") necdsp.srtest = hex(attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
|
}
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if(node.name == "dp") {
|
||||||
|
foreach(leaf, node.element) {
|
||||||
if(node.name == "dp") {
|
if(leaf.name == "map") {
|
||||||
foreach(attr, node.attribute) {
|
Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp });
|
||||||
if(attr.name == "mask") necdsp.dpmask = hex(attr.content);
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "test") necdsp.dptest = hex(attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
|
}
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node.name == "map") {
|
|
||||||
Mapping m(necdsp);
|
|
||||||
foreach(attr, node.attribute) {
|
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
|
||||||
}
|
|
||||||
mapping.append(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(program == "") {
|
if(program == "") {
|
||||||
|
@ -336,7 +358,7 @@ void Cartridge::xml_parse_bsx(xml_element &root) {
|
||||||
} else if(node.name == "mmio") {
|
} else if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(bsxcart);
|
Mapping m({ &BSXCart::mmio_read, &bsxcart }, { &BSXCart::mmio_write, &bsxcart });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -364,27 +386,29 @@ void Cartridge::xml_parse_sufamiturbo(xml_element &root) {
|
||||||
if(slot.name == "rom") {
|
if(slot.name == "rom") {
|
||||||
foreach(leaf, slot.element) {
|
foreach(leaf, slot.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(slotid == 0 ? memory::stArom : memory::stBrom);
|
Memory &memory = slotid == 0 ? memory::stArom : memory::stBrom;
|
||||||
|
Mapping m(memory);
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
if(m.memory->size() > 0) mapping.append(m);
|
if(memory.size() > 0) mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(slot.name == "ram") {
|
} else if(slot.name == "ram") {
|
||||||
foreach(leaf, slot.element) {
|
foreach(leaf, slot.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(slotid == 0 ? memory::stAram : memory::stBram);
|
Memory &memory = slotid == 0 ? memory::stAram : memory::stBram;
|
||||||
|
Mapping m(memory);
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||||
if(attr.name == "size") m.size = hex(attr.content);
|
if(attr.name == "size") m.size = hex(attr.content);
|
||||||
}
|
}
|
||||||
if(m.memory->size() > 0) mapping.append(m);
|
if(memory.size() > 0) mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,7 +422,7 @@ void Cartridge::xml_parse_srtc(xml_element &root) {
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "map") {
|
if(node.name == "map") {
|
||||||
Mapping m(srtc);
|
Mapping m({ &SRTC::read, &srtc }, { &SRTC::write, &srtc });
|
||||||
foreach(attr, node.attribute) {
|
foreach(attr, node.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -414,7 +438,7 @@ void Cartridge::xml_parse_sdd1(xml_element &root) {
|
||||||
if(node.name == "mcu") {
|
if(node.name == "mcu") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m((Memory&)sdd1);
|
Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -424,7 +448,7 @@ void Cartridge::xml_parse_sdd1(xml_element &root) {
|
||||||
} else if(node.name == "mmio") {
|
} else if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m((MMIO&)sdd1);
|
Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -443,7 +467,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||||
if(node.name == "dcu") {
|
if(node.name == "dcu") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(spc7110dcu);
|
Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -453,7 +477,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||||
} else if(node.name == "mcu") {
|
} else if(node.name == "mcu") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(spc7110mcu);
|
Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
if(attr.name == "offset") spc7110.data_rom_offset = hex(attr.content);
|
if(attr.name == "offset") spc7110.data_rom_offset = hex(attr.content);
|
||||||
|
@ -464,7 +488,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||||
} else if(node.name == "mmio") {
|
} else if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(spc7110);
|
Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -478,7 +502,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||||
|
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(spc7110ram);
|
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||||
|
@ -493,7 +517,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||||
|
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(spc7110);
|
Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -509,7 +533,7 @@ void Cartridge::xml_parse_cx4(xml_element &root) {
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "map") {
|
if(node.name == "map") {
|
||||||
Mapping m(cx4);
|
Mapping m({ &Cx4::read, &cx4 }, { &Cx4::write, &cx4 });
|
||||||
foreach(attr, node.attribute) {
|
foreach(attr, node.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -523,7 +547,7 @@ void Cartridge::xml_parse_obc1(xml_element &root) {
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "map") {
|
if(node.name == "map") {
|
||||||
Mapping m(obc1);
|
Mapping m({ &OBC1::read, &obc1 }, { &OBC1::write, &obc1 });
|
||||||
foreach(attr, node.attribute) {
|
foreach(attr, node.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -533,22 +557,11 @@ void Cartridge::xml_parse_obc1(xml_element &root) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::xml_parse_setarisc(xml_element &root) {
|
void Cartridge::xml_parse_setarisc(xml_element &root) {
|
||||||
unsigned program = 0;
|
has_st0018 = true;
|
||||||
|
|
||||||
foreach(attr, root.attribute) {
|
|
||||||
if(attr.name == "program") {
|
|
||||||
if(attr.content == "ST-0018") {
|
|
||||||
program = 1;
|
|
||||||
has_st0018 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MMIO *map[2] = { 0, &st0018 };
|
|
||||||
|
|
||||||
foreach(node, root.element) {
|
foreach(node, root.element) {
|
||||||
if(node.name == "map" && map[program]) {
|
if(node.name == "map") {
|
||||||
Mapping m(*map[program]);
|
Mapping m({ &ST0018::mmio_read, &st0018 }, { &ST0018::mmio_write, &st0018 });
|
||||||
foreach(attr, node.attribute) {
|
foreach(attr, node.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -564,7 +577,7 @@ void Cartridge::xml_parse_msu1(xml_element &root) {
|
||||||
if(node.name == "mmio") {
|
if(node.name == "mmio") {
|
||||||
foreach(leaf, node.element) {
|
foreach(leaf, node.element) {
|
||||||
if(leaf.name == "map") {
|
if(leaf.name == "map") {
|
||||||
Mapping m(msu1);
|
Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 });
|
||||||
foreach(attr, leaf.attribute) {
|
foreach(attr, leaf.attribute) {
|
||||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||||
}
|
}
|
||||||
|
@ -611,22 +624,20 @@ void Cartridge::xml_parse_mode(Mapping &m, const string& data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cartridge::Mapping::Mapping() {
|
Cartridge::Mapping::Mapping() {
|
||||||
memory = 0;
|
|
||||||
mmio = 0;
|
|
||||||
mode = Bus::MapMode::Direct;
|
mode = Bus::MapMode::Direct;
|
||||||
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cartridge::Mapping::Mapping(Memory &memory_) {
|
Cartridge::Mapping::Mapping(Memory &memory) {
|
||||||
memory = &memory_;
|
read = { &Memory::read, &memory };
|
||||||
mmio = 0;
|
write = { &Memory::write, &memory };
|
||||||
mode = Bus::MapMode::Direct;
|
mode = Bus::MapMode::Direct;
|
||||||
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cartridge::Mapping::Mapping(MMIO &mmio_) {
|
Cartridge::Mapping::Mapping(const function<uint8 (unsigned)> &read_, const function<void (unsigned, uint8)> &write_) {
|
||||||
memory = 0;
|
read = read_;
|
||||||
mmio = &mmio_;
|
write = write_;
|
||||||
mode = Bus::MapMode::Direct;
|
mode = Bus::MapMode::Direct;
|
||||||
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
banklo = bankhi = addrlo = addrhi = offset = size = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class BSXBase : public MMIO {
|
class BSXBase {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
@ -22,7 +22,7 @@ private:
|
||||||
} regs;
|
} regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BSXCart : public MMIO {
|
class BSXCart {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
@ -43,7 +43,7 @@ private:
|
||||||
void update_memory_map();
|
void update_memory_map();
|
||||||
};
|
};
|
||||||
|
|
||||||
class BSXFlash : public Memory {
|
class BSXFlash {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
|
|
@ -6,7 +6,6 @@ void BSXBase::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSXBase::enable() {
|
void BSXBase::enable() {
|
||||||
for(uint16 i = 0x2188; i <= 0x219f; i++) memory::mmio.map(i, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSXBase::power() {
|
void BSXBase::power() {
|
||||||
|
@ -14,6 +13,9 @@ void BSXBase::power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSXBase::reset() {
|
void BSXBase::reset() {
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, { &BSXBase::mmio_read, &bsxbase }, { &BSXBase::mmio_write, &bsxbase });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, { &BSXBase::mmio_read, &bsxbase }, { &BSXBase::mmio_write, &bsxbase });
|
||||||
|
|
||||||
memset(®s, 0x00, sizeof regs);
|
memset(®s, 0x00, sizeof regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,39 +25,39 @@ void BSXCart::update_memory_map() {
|
||||||
|
|
||||||
if((regs.r[0x02] & 0x80) == 0x00) {
|
if((regs.r[0x02] & 0x80) == 0x00) {
|
||||||
//LoROM mapping
|
//LoROM mapping
|
||||||
bus.map(Bus::MapMode::Linear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Linear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||||
bus.map(Bus::MapMode::Linear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Linear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
||||||
} else {
|
} else {
|
||||||
//HiROM mapping
|
//HiROM mapping
|
||||||
bus.map(Bus::MapMode::Shadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Shadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
||||||
bus.map(Bus::MapMode::Linear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Linear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
||||||
bus.map(Bus::MapMode::Shadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Shadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
||||||
bus.map(Bus::MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, cart);
|
// bus.map(Bus::MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, cart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.r[0x03] & 0x80) {
|
if(regs.r[0x03] & 0x80) {
|
||||||
bus.map(Bus::MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
|
// bus.map(Bus::MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
|
||||||
//bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
//bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((regs.r[0x05] & 0x80) == 0x00) {
|
if((regs.r[0x05] & 0x80) == 0x00) {
|
||||||
bus.map(Bus::MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
|
// bus.map(Bus::MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((regs.r[0x06] & 0x80) == 0x00) {
|
if((regs.r[0x06] & 0x80) == 0x00) {
|
||||||
bus.map(Bus::MapMode::Linear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
|
// bus.map(Bus::MapMode::Linear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.r[0x07] & 0x80) {
|
if(regs.r[0x07] & 0x80) {
|
||||||
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
|
// bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.r[0x08] & 0x80) {
|
if(regs.r[0x08] & 0x80) {
|
||||||
bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
|
// bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Shadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
|
// bus.map(Bus::MapMode::Shadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
|
||||||
bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
// bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 BSXCart::mmio_read(unsigned addr) {
|
uint8 BSXCart::mmio_read(unsigned addr) {
|
||||||
|
@ -93,4 +93,3 @@ BSXCart::~BSXCart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Cx4 : public Memory {
|
class Cx4 {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
|
|
@ -32,12 +32,6 @@ void ICD2::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::enable() {
|
void ICD2::enable() {
|
||||||
mmio[0] = memory::mmio.handle(0x2181);
|
|
||||||
mmio[1] = memory::mmio.handle(0x2182);
|
|
||||||
mmio[2] = memory::mmio.handle(0x420b);
|
|
||||||
memory::mmio.map(0x2181, *this);
|
|
||||||
memory::mmio.map(0x2182, *this);
|
|
||||||
memory::mmio.map(0x420b, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::power() {
|
void ICD2::power() {
|
||||||
|
@ -47,6 +41,11 @@ void ICD2::power() {
|
||||||
void ICD2::reset() {
|
void ICD2::reset() {
|
||||||
create(ICD2::Enter, cpu.frequency / 5);
|
create(ICD2::Enter, cpu.frequency / 5);
|
||||||
|
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||||
|
|
||||||
r2181 = 0x00;
|
r2181 = 0x00;
|
||||||
r2182 = 0x00;
|
r2182 = 0x00;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class ICD2 : public GameBoy::Interface, public Coprocessor, public MMIO, public Memory {
|
class ICD2 : public GameBoy::Interface, public Coprocessor {
|
||||||
public:
|
public:
|
||||||
unsigned revision;
|
unsigned revision;
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ public:
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
uint8 read(unsigned addr);
|
||||||
|
void write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifdef ICD2_CPP
|
#ifdef ICD2_CPP
|
||||||
|
|
||||||
uint8 ICD2::mmio_read(unsigned addr) {
|
uint8 ICD2::mmio_read(unsigned addr) {
|
||||||
if((uint16)addr == 0x2181) return mmio[0]->mmio_read(addr);
|
if((uint16)addr == 0x2181) return cpu.mmio_read(addr);
|
||||||
if((uint16)addr == 0x2182) return mmio[1]->mmio_read(addr);
|
if((uint16)addr == 0x2182) return cpu.mmio_read(addr);
|
||||||
if((uint16)addr == 0x420b) return mmio[2]->mmio_read(addr);
|
if((uint16)addr == 0x420b) return cpu.mmio_read(addr);
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,9 @@ void ICD2::mmio_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((uint16)addr == 0x2181) return mmio[0]->mmio_write(addr, r2181 = data);
|
if((uint16)addr == 0x2181) return cpu.mmio_write(addr, r2181 = data);
|
||||||
if((uint16)addr == 0x2182) return mmio[1]->mmio_write(addr, r2182 = data);
|
if((uint16)addr == 0x2182) return cpu.mmio_write(addr, r2182 = data);
|
||||||
if((uint16)addr == 0x420b) return mmio[2]->mmio_write(addr, data);
|
if((uint16)addr == 0x420b) return cpu.mmio_write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 ICD2::read(unsigned addr) {
|
uint8 ICD2::read(unsigned addr) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
uint8 r2181;
|
uint8 r2181;
|
||||||
uint8 r2182;
|
uint8 r2182;
|
||||||
MMIO *mmio[3];
|
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
@ -13,7 +12,5 @@ uint8 r6007;
|
||||||
uint8 r7000[16];
|
uint8 r7000[16];
|
||||||
unsigned r7800;
|
unsigned r7800;
|
||||||
uint8 mlt_req;
|
uint8 mlt_req;
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 vram[320];
|
uint8 vram[320];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class MSU1 : public Coprocessor, public MMIO {
|
class MSU1 : public Coprocessor {
|
||||||
public:
|
public:
|
||||||
static void Enter();
|
static void Enter();
|
||||||
void enter();
|
void enter();
|
||||||
|
|
|
@ -1,28 +1,16 @@
|
||||||
#ifdef NECDSP_CPP
|
#ifdef NECDSP_CPP
|
||||||
|
|
||||||
uint8 NECDSP::read(unsigned addr) {
|
uint8 NECDSP::sr_read(unsigned) {
|
||||||
cpu.synchronize_coprocessor();
|
cpu.synchronize_coprocessor();
|
||||||
if((addr & srmask) == srtest) return sr_read();
|
|
||||||
if((addr & drmask) == drtest) return dr_read();
|
|
||||||
if((addr & dpmask) == dptest) return dp_read(addr);
|
|
||||||
return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NECDSP::write(unsigned addr, uint8 data) {
|
|
||||||
cpu.synchronize_coprocessor();
|
|
||||||
if((addr & srmask) == srtest) return sr_write(data);
|
|
||||||
if((addr & drmask) == drtest) return dr_write(data);
|
|
||||||
if((addr & dpmask) == dptest) return dp_write(addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 NECDSP::sr_read() {
|
|
||||||
return regs.sr >> 8;
|
return regs.sr >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::sr_write(uint8 data) {
|
void NECDSP::sr_write(unsigned, uint8 data) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::dr_read() {
|
uint8 NECDSP::dr_read(unsigned) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
if(regs.sr.drc == 0) {
|
if(regs.sr.drc == 0) {
|
||||||
//16-bit
|
//16-bit
|
||||||
if(regs.sr.drs == 0) {
|
if(regs.sr.drs == 0) {
|
||||||
|
@ -40,7 +28,8 @@ uint8 NECDSP::dr_read() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::dr_write(uint8 data) {
|
void NECDSP::dr_write(unsigned, uint8 data) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
if(regs.sr.drc == 0) {
|
if(regs.sr.drc == 0) {
|
||||||
//16-bit
|
//16-bit
|
||||||
if(regs.sr.drs == 0) {
|
if(regs.sr.drs == 0) {
|
||||||
|
@ -59,6 +48,7 @@ void NECDSP::dr_write(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::dp_read(unsigned addr) {
|
uint8 NECDSP::dp_read(unsigned addr) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
bool hi = addr & 1;
|
bool hi = addr & 1;
|
||||||
addr = (addr >> 1) & 2047;
|
addr = (addr >> 1) & 2047;
|
||||||
|
|
||||||
|
@ -70,6 +60,7 @@ uint8 NECDSP::dp_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
bool hi = addr & 1;
|
bool hi = addr & 1;
|
||||||
addr = (addr >> 1) & 2047;
|
addr = (addr >> 1) & 2047;
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,6 @@ void NECDSP::power() {
|
||||||
regs.pc.bits(11);
|
regs.pc.bits(11);
|
||||||
regs.rp.bits(10);
|
regs.rp.bits(10);
|
||||||
regs.dp.bits( 8);
|
regs.dp.bits( 8);
|
||||||
dpmask = 0x000000, dptest = 0xffffff; //uPD7725 not mapped to SNES bus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(revision == Revision::uPD96050) {
|
if(revision == Revision::uPD96050) {
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
class NECDSP : public Coprocessor, public Memory {
|
class NECDSP : public Coprocessor {
|
||||||
public:
|
public:
|
||||||
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
|
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
|
||||||
unsigned frequency;
|
unsigned frequency;
|
||||||
unsigned drmask, drtest;
|
|
||||||
unsigned srmask, srtest;
|
|
||||||
unsigned dpmask, dptest;
|
|
||||||
|
|
||||||
#include "registers.hpp"
|
#include "registers.hpp"
|
||||||
|
|
||||||
|
@ -26,14 +23,11 @@ public:
|
||||||
|
|
||||||
string disassemble(uint14 ip);
|
string disassemble(uint14 ip);
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
uint8 sr_read(unsigned);
|
||||||
void write(unsigned addr, uint8 data);
|
void sr_write(unsigned, uint8 data);
|
||||||
|
|
||||||
uint8 sr_read();
|
uint8 dr_read(unsigned);
|
||||||
void sr_write(uint8 data);
|
void dr_write(unsigned, uint8 data);
|
||||||
|
|
||||||
uint8 dr_read();
|
|
||||||
void dr_write(uint8 data);
|
|
||||||
|
|
||||||
uint8 dp_read(unsigned addr);
|
uint8 dp_read(unsigned addr);
|
||||||
void dp_write(unsigned addr, uint8 data);
|
void dp_write(unsigned addr, uint8 data);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class OBC1 : public Memory {
|
class OBC1 {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
|
|
@ -6,7 +6,6 @@ SA1Bus sa1bus;
|
||||||
namespace memory {
|
namespace memory {
|
||||||
StaticRAM iram(2048);
|
StaticRAM iram(2048);
|
||||||
//accessed by:
|
//accessed by:
|
||||||
VSPROM vsprom; //S-CPU + SA-1
|
|
||||||
CPUIRAM cpuiram; //S-CPU
|
CPUIRAM cpuiram; //S-CPU
|
||||||
SA1IRAM sa1iram; //SA-1
|
SA1IRAM sa1iram; //SA-1
|
||||||
SA1BWRAM sa1bwram; //SA-1
|
SA1BWRAM sa1bwram; //SA-1
|
||||||
|
@ -15,73 +14,43 @@ namespace memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
|
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
|
||||||
//this is used both to avoid VBR-reads from accessing MMIO registers, and
|
//this is used both to keep VBR-reads from accessing MMIO registers, and
|
||||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||||
//these ports.
|
//these ports.
|
||||||
//(* eg, memory::cartram is used directly, as memory::sa1bwram syncs to the S-CPU)
|
//(* eg, memory::cartram is used directly, as memory::sa1bwram syncs to the S-CPU)
|
||||||
void VBRBus::init() {
|
void VBRBus::init() {
|
||||||
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
map(MapMode::Direct, 0x00, 0x3f, 0x8000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x8000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
|
map(MapMode::Direct, 0xc0, 0xff, 0x0000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
|
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, { &MappedRAM::read, &memory::cartram }, { &MappedRAM::write, &memory::cartram }, 0, memory::cartram.size());
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, { &MappedRAM::read, &memory::cartram }, { &MappedRAM::write, &memory::cartram }, 0, memory::cartram.size());
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cartram);
|
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, { &MappedRAM::read, &memory::cartram }, { &MappedRAM::write, &memory::cartram }, 0, memory::cartram.size());
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::vsprom);
|
|
||||||
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::cartram);
|
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, { &StaticRAM::read, &memory::iram }, { &StaticRAM::write, &memory::iram }, 0, 2048);
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, { &StaticRAM::read, &memory::iram }, { &StaticRAM::write, &memory::iram }, 0, 2048);
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, { &StaticRAM::read, &memory::iram }, { &StaticRAM::write, &memory::iram }, 0, 2048);
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cartram);
|
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, { &StaticRAM::read, &memory::iram }, { &StaticRAM::write, &memory::iram }, 0, 2048);
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x8000, 0xffff, memory::vsprom);
|
|
||||||
map(MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, memory::vsprom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1Bus::init() {
|
void SA1Bus::init() {
|
||||||
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
map(MapMode::Direct, 0x00, 0x3f, 0x2200, 0x23ff, { &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x2200, 0x23ff, { &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 });
|
||||||
|
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, memory::sa1iram);
|
map(MapMode::Direct, 0x00, 0x3f, 0x8000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
map(MapMode::Direct, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
|
map(MapMode::Direct, 0x80, 0xbf, 0x8000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, memory::sa1iram);
|
map(MapMode::Direct, 0xc0, 0xff, 0x0000, 0xffff, { &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram);
|
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::vsprom);
|
|
||||||
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::sa1bwram);
|
|
||||||
map(MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
|
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, memory::sa1iram);
|
|
||||||
map(MapMode::Direct, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
|
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, memory::sa1iram);
|
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram);
|
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x8000, 0xffff, memory::vsprom);
|
|
||||||
map(MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, memory::vsprom);
|
|
||||||
}
|
|
||||||
|
|
||||||
//======
|
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, { &SA1::mmc_sa1_read, &sa1 }, { &SA1::mmc_sa1_write, &sa1 });
|
||||||
//VSPROM
|
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, { &SA1::mmc_sa1_read, &sa1 }, { &SA1::mmc_sa1_write, &sa1 });
|
||||||
//======
|
|
||||||
|
|
||||||
//this class maps $00:[ff00-ffff] for the purpose of supporting:
|
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, { &SA1IRAM::read, &memory::sa1iram }, { &SA1IRAM::write, &memory::sa1iram }, 0, 2048);
|
||||||
//$2209.d6 IVSW (S-CPU IRQ vector selection) (0 = cart, 1 = SA-1)
|
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, { &SA1IRAM::read, &memory::sa1iram }, { &SA1IRAM::write, &memory::sa1iram }, 0, 2048);
|
||||||
//$2209.d4 NVSW (S-CPU NMI vector selection) (0 = cart, 1 = SA-1)
|
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, { &SA1IRAM::read, &memory::sa1iram }, { &SA1IRAM::write, &memory::sa1iram }, 0, 2048);
|
||||||
//when set, vector addresses are over-ridden with SA-1 register settings:
|
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, { &SA1IRAM::read, &memory::sa1iram }, { &SA1IRAM::write, &memory::sa1iram }, 0, 2048);
|
||||||
//SIV = S-CPU IRQ vector address override
|
|
||||||
//SNV = S-CPU NMI vector address override
|
|
||||||
//
|
|
||||||
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
|
|
||||||
//all other addresses return original mapped data.
|
|
||||||
|
|
||||||
unsigned VSPROM::size() const {
|
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, { &SA1BWRAM::read, &memory::sa1bwram }, { &SA1BWRAM::write, &memory::sa1bwram }, 0, memory::sa1bwram.size());
|
||||||
return memory::cartrom.size();
|
map(MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, { &BitmapRAM::read, &memory::bitmapram }, { &BitmapRAM::write, &memory::bitmapram }, 0, memory::bitmapram.size());
|
||||||
}
|
|
||||||
|
|
||||||
uint8 VSPROM::read(unsigned addr) {
|
|
||||||
//use $7fex instead of $ffex due to linear mapping of 32k granularity ROM data
|
|
||||||
if((addr & 0xffffe0) == 0x007fe0) {
|
|
||||||
if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
|
|
||||||
if(addr == 0x7feb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
|
|
||||||
if(addr == 0x7fee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
|
|
||||||
if(addr == 0x7fef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
|
||||||
}
|
|
||||||
return memory::cartrom.read(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VSPROM::write(unsigned addr, uint8 data) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=======
|
//=======
|
||||||
|
|
|
@ -6,12 +6,6 @@ struct SA1Bus : Bus {
|
||||||
void init();
|
void init();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VSPROM : Memory {
|
|
||||||
unsigned size() const;
|
|
||||||
alwaysinline uint8 read(unsigned);
|
|
||||||
alwaysinline void write(unsigned, uint8);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPUIRAM : Memory {
|
struct CPUIRAM : Memory {
|
||||||
unsigned size() const;
|
unsigned size() const;
|
||||||
alwaysinline uint8 read(unsigned);
|
alwaysinline uint8 read(unsigned);
|
||||||
|
@ -46,7 +40,6 @@ struct BitmapRAM : Memory {
|
||||||
namespace memory {
|
namespace memory {
|
||||||
extern StaticRAM iram;
|
extern StaticRAM iram;
|
||||||
|
|
||||||
extern VSPROM vsprom;
|
|
||||||
extern CPUIRAM cpuiram;
|
extern CPUIRAM cpuiram;
|
||||||
extern SA1IRAM sa1iram;
|
extern SA1IRAM sa1iram;
|
||||||
extern SA1BWRAM sa1bwram;
|
extern SA1BWRAM sa1bwram;
|
||||||
|
|
|
@ -21,4 +21,100 @@ void SA1::op_write(unsigned addr, uint8 data) {
|
||||||
sa1bus.write(addr, data);
|
sa1bus.write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8 SA1::mmc_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;
|
||||||
|
if(addr == 0xffee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
|
||||||
|
if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto read = [](unsigned addr) {
|
||||||
|
return memory::cartrom.read(bus.mirror(addr, memory::cartrom.size()));
|
||||||
|
};
|
||||||
|
|
||||||
|
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
|
||||||
|
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||||
|
if(mmio.cbmode == 0) return read(0x000000 | addr);
|
||||||
|
return read((mmio.cb << 20) | addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xe08000) == 0x208000) { //$20-3f:8000-ffff
|
||||||
|
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||||
|
if(mmio.dbmode == 0) return read(0x100000 | addr);
|
||||||
|
return read((mmio.db << 20) | addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff
|
||||||
|
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||||
|
if(mmio.ebmode == 0) return read(0x200000 | addr);
|
||||||
|
return read((mmio.eb << 20) | addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xe08000) == 0xa08000) { //$a0-bf:8000-ffff
|
||||||
|
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||||
|
if(mmio.fbmode == 0) return read(0x300000 | addr);
|
||||||
|
return read((mmio.fb << 20) | addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xc00000) { //$c0-cf:0000-ffff
|
||||||
|
return read((mmio.cb << 20) | (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xd00000) { //$d0-df:0000-ffff
|
||||||
|
return read((mmio.db << 20) | (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xe00000) { //$e0-ef:0000-ffff
|
||||||
|
return read((mmio.eb << 20) | (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xf00000) { //$f0-ff:0000-ffff
|
||||||
|
return read((mmio.fb << 20) | (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SA1::mmc_write(unsigned addr, uint8 data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SA1::mmc_cpu_read(unsigned addr) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
|
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), memory::cc1bwram.size());
|
||||||
|
return memory::cc1bwram.read(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SA1::mmc_cpu_write(unsigned addr, uint8 data) {
|
||||||
|
cpu.synchronize_coprocessor();
|
||||||
|
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), memory::cc1bwram.size());
|
||||||
|
memory::cc1bwram.write(addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SA1::mmc_sa1_read(unsigned addr) {
|
||||||
|
synchronize_cpu();
|
||||||
|
if(mmio.sw46 == 0) {
|
||||||
|
//$40-43:0000-ffff x 32 projection
|
||||||
|
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), memory::sa1bwram.size());
|
||||||
|
return memory::sa1bwram.read(addr);
|
||||||
|
} else {
|
||||||
|
//$60-6f:0000-ffff x 128 projection
|
||||||
|
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), memory::bitmapram.size());
|
||||||
|
return memory::bitmapram.read(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SA1::mmc_sa1_write(unsigned addr, uint8 data) {
|
||||||
|
synchronize_cpu();
|
||||||
|
if(mmio.sw46 == 0) {
|
||||||
|
//$40-43:0000-ffff x 32 projection
|
||||||
|
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), memory::sa1bwram.size());
|
||||||
|
memory::sa1bwram.write(addr, data);
|
||||||
|
} else {
|
||||||
|
//$60-6f:0000-ffff x 128 projection
|
||||||
|
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), memory::bitmapram.size());
|
||||||
|
memory::bitmapram.write(addr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,4 +2,11 @@ alwaysinline void op_io();
|
||||||
alwaysinline uint8 op_read(unsigned addr);
|
alwaysinline uint8 op_read(unsigned addr);
|
||||||
alwaysinline void op_write(unsigned addr, uint8 data);
|
alwaysinline void op_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
uint8_t vbr_read(unsigned addr);
|
uint8 mmc_read(unsigned addr);
|
||||||
|
void mmc_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 mmc_cpu_read(unsigned addr);
|
||||||
|
void mmc_cpu_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 mmc_sa1_read(unsigned addr);
|
||||||
|
void mmc_sa1_write(unsigned addr, uint8 data);
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
#ifdef SA1_CPP
|
#ifdef SA1_CPP
|
||||||
|
|
||||||
//BS-X flash carts, when present, are mapped to 0x400000+
|
|
||||||
Memory& SA1::mmio_access(unsigned &addr) {
|
|
||||||
if(!memory::bsxflash.data()) return memory::vsprom;
|
|
||||||
if(addr < 0x400000) return memory::vsprom;
|
|
||||||
addr &= 0x3fffff;
|
|
||||||
return bsxflash;
|
|
||||||
}
|
|
||||||
|
|
||||||
//(CCNT) SA-1 control
|
//(CCNT) SA-1 control
|
||||||
void SA1::mmio_w2200(uint8 data) {
|
void SA1::mmio_w2200(uint8 data) {
|
||||||
if(mmio.sa1_resb && !(data & 0x80)) {
|
if(mmio.sa1_resb && !(data & 0x80)) {
|
||||||
|
@ -151,104 +143,35 @@ void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8
|
||||||
void SA1::mmio_w2220(uint8 data) {
|
void SA1::mmio_w2220(uint8 data) {
|
||||||
mmio.cbmode = (data & 0x80);
|
mmio.cbmode = (data & 0x80);
|
||||||
mmio.cb = (data & 0x07);
|
mmio.cb = (data & 0x07);
|
||||||
|
|
||||||
unsigned addr = mmio.cb << 20;
|
|
||||||
Memory &access = mmio_access(addr);
|
|
||||||
|
|
||||||
if(mmio.cbmode == 0) {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::vsprom, 0x000000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::vsprom, 0x000000);
|
|
||||||
} else {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(DXB) Super MMC bank D
|
//(DXB) Super MMC bank D
|
||||||
void SA1::mmio_w2221(uint8 data) {
|
void SA1::mmio_w2221(uint8 data) {
|
||||||
mmio.dbmode = (data & 0x80);
|
mmio.dbmode = (data & 0x80);
|
||||||
mmio.db = (data & 0x07);
|
mmio.db = (data & 0x07);
|
||||||
|
|
||||||
unsigned addr = mmio.db << 20;
|
|
||||||
Memory &access = mmio_access(addr);
|
|
||||||
|
|
||||||
if(mmio.dbmode == 0) {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, memory::vsprom, 0x100000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, memory::vsprom, 0x100000);
|
|
||||||
} else {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(EXB) Super MMC bank E
|
//(EXB) Super MMC bank E
|
||||||
void SA1::mmio_w2222(uint8 data) {
|
void SA1::mmio_w2222(uint8 data) {
|
||||||
mmio.ebmode = (data & 0x80);
|
mmio.ebmode = (data & 0x80);
|
||||||
mmio.eb = (data & 0x07);
|
mmio.eb = (data & 0x07);
|
||||||
|
|
||||||
unsigned addr = mmio.eb << 20;
|
|
||||||
Memory &access = mmio_access(addr);
|
|
||||||
|
|
||||||
if(mmio.ebmode == 0) {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::vsprom, 0x200000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::vsprom, 0x200000);
|
|
||||||
} else {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(FXB) Super MMC bank F
|
//(FXB) Super MMC bank F
|
||||||
void SA1::mmio_w2223(uint8 data) {
|
void SA1::mmio_w2223(uint8 data) {
|
||||||
mmio.fbmode = (data & 0x80);
|
mmio.fbmode = (data & 0x80);
|
||||||
mmio.fb = (data & 0x07);
|
mmio.fb = (data & 0x07);
|
||||||
|
|
||||||
unsigned addr = mmio.fb << 20;
|
|
||||||
Memory &access = mmio_access(addr);
|
|
||||||
|
|
||||||
if(mmio.fbmode == 0) {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, memory::vsprom, 0x300000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, memory::vsprom, 0x300000);
|
|
||||||
} else {
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Linear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BMAPS) S-CPU BW-RAM address mapping
|
//(BMAPS) S-CPU BW-RAM address mapping
|
||||||
void SA1::mmio_w2224(uint8 data) {
|
void SA1::mmio_w2224(uint8 data) {
|
||||||
mmio.sbm = (data & 0x1f);
|
mmio.sbm = (data & 0x1f);
|
||||||
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
|
||||||
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BMAP) SA-1 BW-RAM address mapping
|
//(BMAP) SA-1 BW-RAM address mapping
|
||||||
void SA1::mmio_w2225(uint8 data) {
|
void SA1::mmio_w2225(uint8 data) {
|
||||||
mmio.sw46 = (data & 0x80);
|
mmio.sw46 = (data & 0x80);
|
||||||
mmio.cbm = (data & 0x7f);
|
mmio.cbm = (data & 0x7f);
|
||||||
|
|
||||||
if(mmio.sw46 == 0) {
|
|
||||||
//$[40-43]:[0000-ffff] x 32 projection
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
|
||||||
} else {
|
|
||||||
//$[60-6f]:[0000-ffff] x 128 projection
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
|
||||||
sa1bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SWBE) S-CPU BW-RAM write enable
|
//(SWBE) S-CPU BW-RAM write enable
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
Memory& mmio_access(unsigned &addr);
|
|
||||||
|
|
||||||
struct MMIO {
|
struct MMIO {
|
||||||
//$2200 CCNT
|
//$2200 CCNT
|
||||||
|
@ -64,19 +63,19 @@ struct MMIO {
|
||||||
|
|
||||||
//$2220 CXB
|
//$2220 CXB
|
||||||
bool cbmode;
|
bool cbmode;
|
||||||
uint8 cb;
|
unsigned cb;
|
||||||
|
|
||||||
//$2221 DXB
|
//$2221 DXB
|
||||||
bool dbmode;
|
bool dbmode;
|
||||||
uint8 db;
|
unsigned db;
|
||||||
|
|
||||||
//$2222 EXB
|
//$2222 EXB
|
||||||
bool ebmode;
|
bool ebmode;
|
||||||
uint8 eb;
|
unsigned eb;
|
||||||
|
|
||||||
//$2223 FXB
|
//$2223 FXB
|
||||||
bool fbmode;
|
bool fbmode;
|
||||||
uint8 fb;
|
unsigned fb;
|
||||||
|
|
||||||
//$2224 BMAPS
|
//$2224 BMAPS
|
||||||
uint8 sbm;
|
uint8 sbm;
|
||||||
|
|
|
@ -124,13 +124,13 @@ void SA1::enable() {
|
||||||
void SA1::power() {
|
void SA1::power() {
|
||||||
regs.a = regs.x = regs.y = 0x0000;
|
regs.a = regs.x = regs.y = 0x0000;
|
||||||
regs.s = 0x01ff;
|
regs.s = 0x01ff;
|
||||||
vbrbus.init();
|
|
||||||
sa1bus.init();
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::reset() {
|
void SA1::reset() {
|
||||||
create(SA1::Enter, system.cpu_frequency());
|
create(SA1::Enter, system.cpu_frequency());
|
||||||
|
vbrbus.init();
|
||||||
|
sa1bus.init();
|
||||||
|
|
||||||
memory::cc1bwram.dma = false;
|
memory::cc1bwram.dma = false;
|
||||||
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
||||||
|
@ -220,15 +220,15 @@ void SA1::reset() {
|
||||||
mmio.vcnt = 0x0000;
|
mmio.vcnt = 0x0000;
|
||||||
|
|
||||||
//$2220-2223 CXB, DXB, EXB, FXB
|
//$2220-2223 CXB, DXB, EXB, FXB
|
||||||
mmio.cbmode = 0;
|
mmio.cbmode = 1;
|
||||||
mmio.dbmode = 0;
|
mmio.dbmode = 1;
|
||||||
mmio.ebmode = 0;
|
mmio.ebmode = 1;
|
||||||
mmio.fbmode = 0;
|
mmio.fbmode = 1;
|
||||||
|
|
||||||
mmio.cb = 0x00;
|
mmio.cb = 0x00;
|
||||||
mmio.db = 0x01;
|
mmio.db = 0x01;
|
||||||
mmio.eb = 0x02;
|
mmio.eb = 0x00;
|
||||||
mmio.fb = 0x03;
|
mmio.fb = 0x01;
|
||||||
|
|
||||||
//$2224 BMAPS
|
//$2224 BMAPS
|
||||||
mmio.sbm = 0x00;
|
mmio.sbm = 0x00;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "bus/bus.hpp"
|
#include "bus/bus.hpp"
|
||||||
|
|
||||||
class SA1 : public Coprocessor, public CPUcore, public MMIO {
|
class SA1 : public Coprocessor, public CPUcore {
|
||||||
public:
|
public:
|
||||||
#include "dma/dma.hpp"
|
#include "dma/dma.hpp"
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
|
|
|
@ -11,12 +11,6 @@ SDD1 sdd1;
|
||||||
void SDD1::init() {}
|
void SDD1::init() {}
|
||||||
|
|
||||||
void SDD1::enable() {
|
void SDD1::enable() {
|
||||||
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
|
|
||||||
//buffer address and transfer size information for use in SDD1::read()
|
|
||||||
for(unsigned i = 0x4300; i <= 0x437f; i++) {
|
|
||||||
cpu_mmio[i & 0x7f] = memory::mmio.handle(i);
|
|
||||||
memory::mmio.map(i, *this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::power() {
|
void SDD1::power() {
|
||||||
|
@ -24,6 +18,11 @@ void SDD1::power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::reset() {
|
void SDD1::reset() {
|
||||||
|
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
|
||||||
|
//buffer address and transfer size information for use in SDD1::mcu_read()
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
|
||||||
|
|
||||||
sdd1_enable = 0x00;
|
sdd1_enable = 0x00;
|
||||||
xfer_enable = 0x00;
|
xfer_enable = 0x00;
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ uint8 SDD1::mmio_read(unsigned addr) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if((addr & 0x4380) == 0x4300) {
|
if((addr & 0x4380) == 0x4300) {
|
||||||
return cpu_mmio[addr & 0x7f]->mmio_read(addr);
|
return cpu.mmio_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
@ -70,7 +69,7 @@ void SDD1::mmio_write(unsigned addr, uint8 data) {
|
||||||
case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break;
|
case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break;
|
||||||
case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break;
|
case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break;
|
||||||
}
|
}
|
||||||
return cpu_mmio[addr & 0x7f]->mmio_write(addr, data);
|
return cpu.mmio_write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
@ -84,7 +83,7 @@ void SDD1::mmio_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//SDD1::read() is mapped to $[c0-ff]:[0000-ffff]
|
//SDD1::mcu_read() is mapped to $c0-ff:0000-ffff
|
||||||
//the design is meant to be as close to the hardware design as possible, thus this code
|
//the design is meant to be as close to the hardware design as possible, thus this code
|
||||||
//avoids adding S-DD1 hooks inside S-CPU::DMA emulation.
|
//avoids adding S-DD1 hooks inside S-CPU::DMA emulation.
|
||||||
//
|
//
|
||||||
|
@ -102,7 +101,7 @@ void SDD1::mmio_write(unsigned addr, uint8 data) {
|
||||||
//
|
//
|
||||||
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
|
//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.
|
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
|
||||||
uint8 SDD1::read(unsigned addr) {
|
uint8 SDD1::mcu_read(unsigned addr) {
|
||||||
if(sdd1_enable & xfer_enable) {
|
if(sdd1_enable & xfer_enable) {
|
||||||
//at least one channel has S-DD1 decompression enabled ...
|
//at least one channel has S-DD1 decompression enabled ...
|
||||||
for(unsigned i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
|
@ -142,7 +141,7 @@ uint8 SDD1::read(unsigned addr) {
|
||||||
return memory::cartrom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
|
return memory::cartrom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::write(unsigned addr, uint8 data) {
|
void SDD1::mcu_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SDD1::SDD1() {
|
SDD1::SDD1() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "sdd1emu.hpp"
|
#include "sdd1emu.hpp"
|
||||||
|
|
||||||
class SDD1 : public MMIO, public Memory {
|
class SDD1 {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
@ -10,16 +10,14 @@ public:
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
uint8 mcu_read(unsigned addr);
|
||||||
void write(unsigned addr, uint8 data);
|
void mcu_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
SDD1();
|
SDD1();
|
||||||
~SDD1();
|
~SDD1();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MMIO *cpu_mmio[0x80]; //bus spying hooks to glean information for struct dma[]
|
|
||||||
|
|
||||||
uint8 sdd1_enable; //channel bit-mask
|
uint8 sdd1_enable; //channel bit-mask
|
||||||
uint8 xfer_enable; //channel bit-mask
|
uint8 xfer_enable; //channel bit-mask
|
||||||
unsigned mmc[4]; //memory map controller ROM indices
|
unsigned mmc[4]; //memory map controller ROM indices
|
||||||
|
|
|
@ -31,7 +31,7 @@ understood.
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
typedef uint8 bool8;
|
typedef uint8 bool8;
|
||||||
#define SDD1_read(__addr) (sdd1.read(__addr))
|
#define SDD1_read(__addr) (sdd1.mcu_read(__addr))
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -61,16 +61,16 @@ void Serial::write(uint8 data) {
|
||||||
uint8 Serial::mmio_read(unsigned addr) {
|
uint8 Serial::mmio_read(unsigned addr) {
|
||||||
cpu.synchronize_coprocessor();
|
cpu.synchronize_coprocessor();
|
||||||
switch(addr & 1) { default:
|
switch(addr & 1) { default:
|
||||||
case 0: return r4016->mmio_read(addr);
|
case 0: return cpu.mmio_read(addr);
|
||||||
case 1: return r4017->mmio_read(addr);
|
case 1: return cpu.mmio_read(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Serial::mmio_write(unsigned addr, uint8 data) {
|
void Serial::mmio_write(unsigned addr, uint8 data) {
|
||||||
cpu.synchronize_coprocessor();
|
cpu.synchronize_coprocessor();
|
||||||
switch(addr & 1) { default:
|
switch(addr & 1) { default:
|
||||||
case 0: r4016->mmio_write(addr, data); break;
|
case 0: cpu.mmio_write(addr, data); break;
|
||||||
case 1: r4017->mmio_write(addr, data); break;
|
case 1: cpu.mmio_write(addr, data); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,11 +78,6 @@ void Serial::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Serial::enable() {
|
void Serial::enable() {
|
||||||
r4016 = memory::mmio.handle(0x4016);
|
|
||||||
r4017 = memory::mmio.handle(0x4017);
|
|
||||||
memory::mmio.map(0x4016, *this);
|
|
||||||
memory::mmio.map(0x4017, *this);
|
|
||||||
|
|
||||||
if(opened()) close();
|
if(opened()) close();
|
||||||
string name = notdir(cartridge.basename());
|
string name = notdir(cartridge.basename());
|
||||||
string path = dir(cartridge.basename());
|
string path = dir(cartridge.basename());
|
||||||
|
@ -99,6 +94,9 @@ void Serial::power() {
|
||||||
|
|
||||||
void Serial::reset() {
|
void Serial::reset() {
|
||||||
create(Serial::Enter, baudrate() * 8);
|
create(Serial::Enter, baudrate() * 8);
|
||||||
|
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, { &Serial::mmio_read, &serial }, { &Serial::mmio_write, &serial });
|
||||||
|
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, { &Serial::mmio_read, &serial }, { &Serial::mmio_write, &serial });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Serial : public Coprocessor, public MMIO, public library, public property<Serial> {
|
class Serial : public Coprocessor, public library, public property<Serial> {
|
||||||
public:
|
public:
|
||||||
static void Enter();
|
static void Enter();
|
||||||
void enter();
|
void enter();
|
||||||
|
@ -19,7 +19,6 @@ public:
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MMIO *r4016, *r4017;
|
|
||||||
function<unsigned ()> baudrate;
|
function<unsigned ()> baudrate;
|
||||||
function<bool ()> flowcontrol;
|
function<bool ()> flowcontrol;
|
||||||
function<void (void (*)(unsigned), uint8_t (*)(), void (*)(uint8_t))> main;
|
function<void (void (*)(unsigned), uint8_t (*)(), void (*)(uint8_t))> main;
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
|
|
||||||
SPC7110 spc7110;
|
SPC7110 spc7110;
|
||||||
SPC7110MCU spc7110mcu;
|
|
||||||
SPC7110DCU spc7110dcu;
|
|
||||||
SPC7110RAM spc7110ram;
|
|
||||||
|
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
#include "decomp.cpp"
|
#include "decomp.cpp"
|
||||||
|
@ -634,49 +631,41 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
SPC7110::SPC7110() {
|
SPC7110::SPC7110() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========
|
//============
|
||||||
//SPC7110MCU
|
//SPC7110::MCU
|
||||||
//==========
|
//============
|
||||||
|
|
||||||
unsigned SPC7110MCU::size() const {
|
uint8 SPC7110::mcu_read(unsigned addr) {
|
||||||
return 0x300000;
|
if(addr <= 0xdfffff) return memory::cartrom.read(dx_offset + (addr & 0x0fffff));
|
||||||
}
|
if(addr <= 0xefffff) return memory::cartrom.read(ex_offset + (addr & 0x0fffff));
|
||||||
|
if(addr <= 0xffffff) return memory::cartrom.read(fx_offset + (addr & 0x0fffff));
|
||||||
uint8 SPC7110MCU::read(unsigned addr) {
|
|
||||||
if(addr <= 0xdfffff) return memory::cartrom.read(spc7110.dx_offset + (addr & 0x0fffff));
|
|
||||||
if(addr <= 0xefffff) return memory::cartrom.read(spc7110.ex_offset + (addr & 0x0fffff));
|
|
||||||
if(addr <= 0xffffff) return memory::cartrom.read(spc7110.fx_offset + (addr & 0x0fffff));
|
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110MCU::write(unsigned addr, uint8 data) {
|
void SPC7110::mcu_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========
|
//============
|
||||||
//SPC7110DCU
|
//SPC7110::DCU
|
||||||
//==========
|
//============
|
||||||
|
|
||||||
uint8 SPC7110DCU::read(unsigned) {
|
uint8 SPC7110::dcu_read(unsigned) {
|
||||||
return spc7110.mmio_read(0x4800);
|
return mmio_read(0x4800);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110DCU::write(unsigned, uint8) {
|
void SPC7110::dcu_write(unsigned, uint8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========
|
//============
|
||||||
//SPC7110RAM
|
//SPC7110::RAM
|
||||||
//==========
|
//============
|
||||||
|
|
||||||
unsigned SPC7110RAM::size() const {
|
uint8 SPC7110::ram_read(unsigned addr) {
|
||||||
return 0x2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 SPC7110RAM::read(unsigned addr) {
|
|
||||||
return memory::cartram.read(addr & 0x1fff);
|
return memory::cartram.read(addr & 0x1fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110RAM::write(unsigned addr, uint8 data) {
|
void SPC7110::ram_write(unsigned addr, uint8 data) {
|
||||||
if(spc7110.r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
|
if(r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include "decomp.hpp"
|
#include "decomp.hpp"
|
||||||
|
|
||||||
class SPC7110 : public MMIO {
|
class SPC7110 {
|
||||||
public:
|
public:
|
||||||
unsigned data_rom_offset;
|
unsigned data_rom_offset;
|
||||||
|
|
||||||
|
@ -40,6 +40,15 @@ public:
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 mcu_read(unsigned addr);
|
||||||
|
void mcu_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 dcu_read(unsigned);
|
||||||
|
void dcu_write(unsigned, uint8);
|
||||||
|
|
||||||
|
uint8 ram_read(unsigned addr);
|
||||||
|
void ram_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
//spc7110decomp
|
//spc7110decomp
|
||||||
void decomp_init();
|
void decomp_init();
|
||||||
uint8 decomp_read();
|
uint8 decomp_read();
|
||||||
|
@ -130,32 +139,6 @@ private:
|
||||||
unsigned rtc_index;
|
unsigned rtc_index;
|
||||||
|
|
||||||
static const unsigned months[12];
|
static const unsigned months[12];
|
||||||
friend class SPC7110MCU;
|
|
||||||
friend class SPC7110DCU;
|
|
||||||
friend class SPC7110RAM;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SPC7110MCU : public Memory {
|
|
||||||
public:
|
|
||||||
unsigned size() const;
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
};
|
|
||||||
|
|
||||||
class SPC7110DCU : public Memory {
|
|
||||||
public:
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
};
|
|
||||||
|
|
||||||
class SPC7110RAM : public Memory {
|
|
||||||
public:
|
|
||||||
unsigned size() const;
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SPC7110 spc7110;
|
extern SPC7110 spc7110;
|
||||||
extern SPC7110MCU spc7110mcu;
|
|
||||||
extern SPC7110DCU spc7110dcu;
|
|
||||||
extern SPC7110RAM spc7110ram;
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
|
||||||
return (sum + 1) % 7; //1900-01-01 was a Monday
|
return (sum + 1) % 7; //1900-01-01 was a Monday
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SRTC::mmio_read(unsigned addr) {
|
uint8 SRTC::read(unsigned addr) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if(addr == 0x2800) {
|
if(addr == 0x2800) {
|
||||||
|
@ -176,7 +176,7 @@ uint8 SRTC::mmio_read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SRTC::mmio_write(unsigned addr, uint8 data) {
|
void SRTC::write(unsigned addr, uint8 data) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if(addr == 0x2801) {
|
if(addr == 0x2801) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
class SRTC : public MMIO {
|
class SRTC {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
SRTC();
|
SRTC();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class ST0018 : public MMIO {
|
class ST0018 {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
|
|
|
@ -10,12 +10,10 @@ namespace memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperFXBus::init() {
|
void SuperFXBus::init() {
|
||||||
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x7fff, { &SuperFXGSUROM::read, &memory::gsurom }, { &SuperFXGSUROM::write, &memory::gsurom }, 0, memory::gsurom.size());
|
||||||
|
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, { &SuperFXGSUROM::read, &memory::gsurom }, { &SuperFXGSUROM::write, &memory::gsurom }, 0, memory::gsurom.size());
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x7fff, memory::gsurom);
|
map(MapMode::Linear, 0x40, 0x5f, 0x0000, 0xffff, { &SuperFXGSUROM::read, &memory::gsurom }, { &SuperFXGSUROM::write, &memory::gsurom }, 0, memory::gsurom.size());
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::gsurom);
|
map(MapMode::Linear, 0x60, 0x7f, 0x0000, 0xffff, { &SuperFXGSURAM::read, &memory::gsuram }, { &SuperFXGSURAM::write, &memory::gsuram }, 0, memory::gsuram.size());
|
||||||
map(MapMode::Linear, 0x40, 0x5f, 0x0000, 0xffff, memory::gsurom);
|
|
||||||
map(MapMode::Linear, 0x60, 0x7f, 0x0000, 0xffff, memory::gsuram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ROM / RAM access from the SuperFX CPU
|
//ROM / RAM access from the SuperFX CPU
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "bus/bus.hpp"
|
#include "bus/bus.hpp"
|
||||||
|
|
||||||
class SuperFX : public Coprocessor, public MMIO {
|
class SuperFX : public Coprocessor {
|
||||||
public:
|
public:
|
||||||
#include "core/core.hpp"
|
#include "core/core.hpp"
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
|
class CPU : public Processor, public CPUcore, public PPUcounter {
|
||||||
public:
|
public:
|
||||||
enum : bool { Threaded = true };
|
enum : bool { Threaded = true };
|
||||||
array<Processor*> coprocessors;
|
array<Processor*> coprocessors;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
void mmio_power();
|
public:
|
||||||
void mmio_reset();
|
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void mmio_power();
|
||||||
|
void mmio_reset();
|
||||||
|
|
||||||
uint8 mmio_r2180();
|
uint8 mmio_r2180();
|
||||||
uint8 mmio_r4016();
|
uint8 mmio_r4016();
|
||||||
uint8 mmio_r4017();
|
uint8 mmio_r4017();
|
||||||
|
|
|
@ -51,18 +51,29 @@ MappedRAM::MappedRAM() : data_(0), size_(-1U), write_protect_(false) {}
|
||||||
|
|
||||||
//Bus
|
//Bus
|
||||||
|
|
||||||
uint8 Bus::read(uint24 addr) {
|
uint8 Bus::read(unsigned addr) {
|
||||||
#if defined(CHEAT_SYSTEM)
|
#if defined(CHEAT_SYSTEM)
|
||||||
if(cheat.active() && cheat.exists(addr)) {
|
if(cheat.active() && cheat.exists(addr)) {
|
||||||
uint8 r;
|
uint8 r;
|
||||||
if(cheat.read(addr, r)) return r;
|
if(cheat.read(addr, r)) return r;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Page &p = page[addr >> 8];
|
|
||||||
return p.access->read(p.offset + addr);
|
linear_vector<MappedRead> &map = rdpage[addr >> 13];
|
||||||
|
for(signed n = map.size() - 1; n >= 0; n--) {
|
||||||
|
if(addr - map[n].lo < map[n].hi) {
|
||||||
|
return map[n].read(addr + map[n].offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::write(uint24 addr, uint8 data) {
|
void Bus::write(unsigned addr, uint8 data) {
|
||||||
Page &p = page[addr >> 8];
|
linear_vector<MappedWrite> &map = wrpage[addr >> 13];
|
||||||
p.access->write(p.offset + addr, data);
|
for(signed n = map.size() - 1; n >= 0; n--) {
|
||||||
|
if(addr - map[n].lo < map[n].hi) {
|
||||||
|
return map[n].write(addr + map[n].offset, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,44 +8,13 @@ Bus bus;
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
MMIOAccess mmio;
|
|
||||||
StaticRAM wram(128 * 1024);
|
StaticRAM wram(128 * 1024);
|
||||||
StaticRAM apuram(64 * 1024);
|
StaticRAM apuram(64 * 1024);
|
||||||
StaticRAM vram(64 * 1024);
|
StaticRAM vram(64 * 1024);
|
||||||
StaticRAM oam(544);
|
StaticRAM oam(544);
|
||||||
StaticRAM cgram(512);
|
StaticRAM cgram(512);
|
||||||
|
|
||||||
UnmappedMemory memory_unmapped;
|
|
||||||
UnmappedMMIO mmio_unmapped;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned UnmappedMemory::size() const { return 16 * 1024 * 1024; }
|
|
||||||
uint8 UnmappedMemory::read(unsigned) { return cpu.regs.mdr; }
|
|
||||||
void UnmappedMemory::write(unsigned, uint8) {}
|
|
||||||
|
|
||||||
uint8 UnmappedMMIO::mmio_read(unsigned) { return cpu.regs.mdr; }
|
|
||||||
void UnmappedMMIO::mmio_write(unsigned, uint8) {}
|
|
||||||
|
|
||||||
MMIO* MMIOAccess::handle(unsigned addr) {
|
|
||||||
return mmio[addr & 0x7fff];
|
|
||||||
}
|
|
||||||
|
|
||||||
void MMIOAccess::map(unsigned addr, MMIO &access) {
|
|
||||||
mmio[addr & 0x7fff] = &access;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 MMIOAccess::read(unsigned addr) {
|
|
||||||
return mmio[addr & 0x7fff]->mmio_read(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MMIOAccess::write(unsigned addr, uint8 data) {
|
|
||||||
mmio[addr & 0x7fff]->mmio_write(addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
MMIOAccess::MMIOAccess() {
|
|
||||||
for(unsigned i = 0; i < 0x8000; i++) mmio[i] = &memory::mmio_unmapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned Bus::mirror(unsigned addr, unsigned size) {
|
unsigned Bus::mirror(unsigned addr, unsigned size) {
|
||||||
unsigned base = 0;
|
unsigned base = 0;
|
||||||
if(size) {
|
if(size) {
|
||||||
|
@ -64,60 +33,46 @@ unsigned Bus::mirror(unsigned addr, unsigned size) {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::map(unsigned addr, Memory &access, unsigned offset) {
|
|
||||||
Page &p = page[addr >> 8];
|
|
||||||
p.access = &access;
|
|
||||||
p.offset = offset - addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bus::map(
|
void Bus::map(
|
||||||
MapMode mode,
|
MapMode mode,
|
||||||
uint8 bank_lo, uint8 bank_hi,
|
unsigned bank_lo, unsigned bank_hi,
|
||||||
uint16 addr_lo, uint16 addr_hi,
|
unsigned addr_lo, unsigned addr_hi,
|
||||||
Memory &access, unsigned offset, unsigned size
|
const function<uint8 (unsigned)> &rd,
|
||||||
|
const function<void (unsigned, uint8)> &wr,
|
||||||
|
unsigned base, unsigned length
|
||||||
) {
|
) {
|
||||||
assert(bank_lo <= bank_hi);
|
assert(bank_lo <= bank_hi && bank_lo <= 0xff);
|
||||||
assert(addr_lo <= addr_hi);
|
assert(addr_lo <= addr_hi && addr_lo <= 0xffff);
|
||||||
if(access.size() == -1U) return;
|
|
||||||
|
|
||||||
uint8 page_lo = addr_lo >> 8;
|
unsigned page_lo = addr_lo >> 13;
|
||||||
uint8 page_hi = addr_hi >> 8;
|
unsigned page_hi = addr_hi >> 13;
|
||||||
unsigned index = 0;
|
if(length == 0) length = (bank_hi - bank_lo + 1) * (addr_hi - addr_lo + 1);
|
||||||
|
|
||||||
switch(mode) {
|
unsigned offset = 0;
|
||||||
case MapMode::Direct: {
|
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
|
||||||
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
|
for(unsigned page = page_lo; page <= page_hi; page++) {
|
||||||
for(unsigned page = page_lo; page <= page_hi; page++) {
|
unsigned map_addr = (bank << 16) | (page << 13);
|
||||||
map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8));
|
unsigned map_page = map_addr >> 13;
|
||||||
}
|
unsigned map_lo = map_addr | (page == page_lo ? addr_lo & 0x1fff : 0x0000);
|
||||||
|
unsigned map_hi = map_addr | (page == page_hi ? addr_hi & 0x1fff : 0x1fff);
|
||||||
|
|
||||||
|
unsigned out_adjust, out_length, out_offset;
|
||||||
|
if(mode == MapMode::Direct) {
|
||||||
|
out_offset = 0;
|
||||||
|
out_length = map_hi - map_lo + 1;
|
||||||
|
} else if(mode == MapMode::Linear) {
|
||||||
|
out_offset = base + mirror(offset, length) - map_lo;
|
||||||
|
out_length = min(map_hi - map_lo + 1, length - offset);
|
||||||
|
offset += map_hi - map_lo + 1;
|
||||||
|
offset %= length;
|
||||||
|
} else if(mode == MapMode::Shadow) {
|
||||||
|
out_offset = base + mirror(map_addr, length) - map_lo;
|
||||||
|
out_length = map_hi - map_lo + 1;
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
|
|
||||||
case MapMode::Linear: {
|
if(rd) rdpage[map_page].append({ rd, map_lo, out_length, out_offset });
|
||||||
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
|
if(wr) wrpage[map_page].append({ wr, map_lo, out_length, out_offset });
|
||||||
for(unsigned page = page_lo; page <= page_hi; page++) {
|
}
|
||||||
map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
|
|
||||||
index += 256;
|
|
||||||
if(size) index %= size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MapMode::Shadow: {
|
|
||||||
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
|
|
||||||
index += page_lo * 256;
|
|
||||||
if(size) index %= size;
|
|
||||||
|
|
||||||
for(unsigned page = page_lo; page <= page_hi; page++) {
|
|
||||||
map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
|
|
||||||
index += 256;
|
|
||||||
if(size) index %= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
index += (255 - page_hi) * 256;
|
|
||||||
if(size) index %= size;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,33 +89,55 @@ void Bus::unload_cart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::map_reset() {
|
void Bus::map_reset() {
|
||||||
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
for(unsigned n = 0; n < 2048; n++) {
|
||||||
map(MapMode::Direct, 0x00, 0x3f, 0x2000, 0x5fff, memory::mmio);
|
rdpage[n].reset();
|
||||||
map(MapMode::Direct, 0x80, 0xbf, 0x2000, 0x5fff, memory::mmio);
|
wrpage[n].reset();
|
||||||
for(unsigned i = 0x2000; i <= 0x5fff; i++) memory::mmio.map(i, memory::mmio_unmapped);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::map_xml() {
|
void Bus::map_xml() {
|
||||||
foreach(m, cartridge.mapping) {
|
foreach(m, cartridge.mapping) {
|
||||||
if(m.memory) {
|
map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, m.read, m.write, m.offset, m.size);
|
||||||
map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, *m.memory, m.offset, m.size);
|
|
||||||
} else if(m.mmio) {
|
|
||||||
for(unsigned i = m.addrlo; i <= m.addrhi; i++) memory::mmio.map(i, *m.mmio);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::map_system() {
|
void Bus::map_system() {
|
||||||
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
|
map(
|
||||||
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
|
MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff,
|
||||||
map(MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, memory::wram);
|
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||||
|
0x000000, 0x002000
|
||||||
|
);
|
||||||
|
map(
|
||||||
|
MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff,
|
||||||
|
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||||
|
0x000000, 0x002000
|
||||||
|
);
|
||||||
|
map(
|
||||||
|
MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff,
|
||||||
|
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::power() {
|
void Bus::power() {
|
||||||
foreach(n, memory::wram) n = config.cpu.wram_init_value;
|
foreach(n, memory::wram) n = config.cpu.wram_init_value;
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::reset() {
|
void Bus::reset() {
|
||||||
|
map(MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||||
|
|
||||||
|
map(MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
|
||||||
|
map(MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
|
||||||
|
map(MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
|
||||||
|
map(MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
|
map(MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,6 @@ struct Memory {
|
||||||
virtual void write(unsigned addr, uint8 data) = 0;
|
virtual void write(unsigned addr, uint8 data) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MMIO {
|
|
||||||
virtual uint8 mmio_read(unsigned addr) = 0;
|
|
||||||
virtual void mmio_write(unsigned addr, uint8 data) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnmappedMemory : Memory {
|
|
||||||
unsigned size() const;
|
|
||||||
uint8 read(unsigned);
|
|
||||||
void write(unsigned, uint8);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnmappedMMIO : MMIO {
|
|
||||||
uint8 mmio_read(unsigned);
|
|
||||||
void mmio_write(unsigned, uint8);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StaticRAM : Memory {
|
struct StaticRAM : Memory {
|
||||||
inline uint8* data();
|
inline uint8* data();
|
||||||
inline unsigned size() const;
|
inline unsigned size() const;
|
||||||
|
@ -57,28 +41,11 @@ private:
|
||||||
bool write_protect_;
|
bool write_protect_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MMIOAccess : Memory {
|
|
||||||
MMIO* handle(unsigned addr);
|
|
||||||
void map(unsigned addr, MMIO &access);
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
MMIOAccess();
|
|
||||||
|
|
||||||
private:
|
|
||||||
MMIO *mmio[0x8000];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Bus {
|
struct Bus {
|
||||||
unsigned mirror(unsigned addr, unsigned size);
|
unsigned mirror(unsigned addr, unsigned size);
|
||||||
void map(unsigned addr, Memory &access, unsigned offset);
|
|
||||||
enum class MapMode : unsigned { Direct, Linear, Shadow };
|
|
||||||
void map(MapMode mode,
|
|
||||||
uint8 bank_lo, uint8 bank_hi,
|
|
||||||
uint16 addr_lo, uint16 addr_hi,
|
|
||||||
Memory &access, unsigned offset = 0, unsigned size = 0);
|
|
||||||
|
|
||||||
alwaysinline uint8 read(uint24 addr);
|
alwaysinline uint8 read(unsigned addr);
|
||||||
alwaysinline void write(uint24 addr, uint8 data);
|
alwaysinline void write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
bool load_cart();
|
bool load_cart();
|
||||||
void unload_cart();
|
void unload_cart();
|
||||||
|
@ -86,10 +53,30 @@ struct Bus {
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
struct Page {
|
struct MappedRead {
|
||||||
Memory *access;
|
function<uint8 (unsigned)> read;
|
||||||
|
unsigned lo, hi;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
} page[65536];
|
};
|
||||||
|
|
||||||
|
struct MappedWrite {
|
||||||
|
function<void (unsigned, uint8)> write;
|
||||||
|
unsigned lo, hi;
|
||||||
|
unsigned offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
linear_vector<MappedRead> rdpage[2048];
|
||||||
|
linear_vector<MappedWrite> wrpage[2048];
|
||||||
|
|
||||||
|
enum class MapMode : unsigned { Direct, Linear, Shadow };
|
||||||
|
void map(
|
||||||
|
MapMode mode,
|
||||||
|
unsigned bank_lo, unsigned bank_hi,
|
||||||
|
unsigned addr_lo, unsigned addr_hi,
|
||||||
|
const function<uint8 (unsigned)> &read,
|
||||||
|
const function<void (unsigned, uint8)> &write,
|
||||||
|
unsigned base = 0, unsigned length = 0
|
||||||
|
);
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
|
|
||||||
|
@ -100,15 +87,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
extern MMIOAccess mmio; //S-CPU, S-PPU
|
|
||||||
extern StaticRAM wram; //S-CPU
|
extern StaticRAM wram; //S-CPU
|
||||||
extern StaticRAM apuram; //S-SMP, S-DSP
|
extern StaticRAM apuram; //S-SMP, S-DSP
|
||||||
extern StaticRAM vram; //S-PPU
|
extern StaticRAM vram; //S-PPU
|
||||||
extern StaticRAM oam; //S-PPU
|
extern StaticRAM oam; //S-PPU
|
||||||
extern StaticRAM cgram; //S-PPU
|
extern StaticRAM cgram; //S-PPU
|
||||||
|
|
||||||
extern UnmappedMemory memory_unmapped;
|
|
||||||
extern UnmappedMMIO mmio_unmapped;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Bus bus;
|
extern Bus bus;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class PPU : public Processor, public PPUcounter, public MMIO {
|
class PPU : public Processor, public PPUcounter {
|
||||||
public:
|
public:
|
||||||
enum : bool { Threaded = true };
|
enum : bool { Threaded = true };
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "074.02";
|
static const char Version[] = "074.03";
|
||||||
static const unsigned SerializerVersion = 17;
|
static const unsigned SerializerVersion = 17;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,12 +106,6 @@ void System::power() {
|
||||||
apu_frequency = region() == Region::NTSC ? config.smp.ntsc_frequency : config.smp.pal_frequency;
|
apu_frequency = region() == Region::NTSC ? config.smp.ntsc_frequency : config.smp.pal_frequency;
|
||||||
|
|
||||||
bus.power();
|
bus.power();
|
||||||
for(unsigned i = 0x2100; i <= 0x213f; i++) memory::mmio.map(i, ppu);
|
|
||||||
for(unsigned i = 0x2140; i <= 0x217f; i++) memory::mmio.map(i, cpu);
|
|
||||||
for(unsigned i = 0x2180; i <= 0x2183; i++) memory::mmio.map(i, cpu);
|
|
||||||
for(unsigned i = 0x4016; i <= 0x4017; i++) memory::mmio.map(i, cpu);
|
|
||||||
for(unsigned i = 0x4200; i <= 0x421f; i++) memory::mmio.map(i, cpu);
|
|
||||||
for(unsigned i = 0x4300; i <= 0x437f; i++) memory::mmio.map(i, cpu);
|
|
||||||
|
|
||||||
audio.coprocessor_enable(false);
|
audio.coprocessor_enable(false);
|
||||||
if(expansion() == ExpansionPortDevice::BSX) bsxbase.enable();
|
if(expansion() == ExpansionPortDevice::BSX) bsxbase.enable();
|
||||||
|
|
Loading…
Reference in New Issue