Update to v089r06 release.

byuu says:

Changelog:
- renamed SRTC -> SharpRTC
- renamed RTC4513 -> EpsonRTC (consistent with DSP naming schema)
- full emulation of invalid BCD values for EpsonRTC
- fixed EpsonRTC IRQ mask

Remaining SPC7110 tasks:
- RTC: test 30-second adjust with all values from 00-7f
- RTC: hold is supposed to tick the clock one second after being
  released?
- RTC: wait times are too long (need to use >32KHz oscillation to
  simulate it properly)
- Data Port: test $4818 more thoroughly (not too important)
- Decompression: test $480c more thoroughly (very important)
- Decompression: perform some tests on DMA transferring data, especially
  with $4807 set

Write-offs, at least for now:
- Decompression: emulation of the crash/glitch behavior seen on the real
  chip when fed invalid data
- Decompression: I can find no use of $4808
- ALU: Booth cycles for MUL/DIV (this could actually be rather important
  if the game reads simpler values quickly [some shoddy games did this
  with the CPU ALU])
- RTC: delay after hold release for $4841 accesses
- RTC: 125uS delay after 30-second adjust that will screw with registers
  in odd ways if your read or write too soon
- RTC: psychotic behavior of reading too early returning port address
  - 1
This commit is contained in:
Tim Allen 2012-05-22 22:10:00 +10:00
parent bd61432322
commit d6001a2df4
19 changed files with 554 additions and 475 deletions

View File

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

View File

@ -1,10 +1,11 @@
sfc_objects := sfc-interface sfc-system sfc-controller
sfc_objects += sfc-cartridge sfc-cheat
sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu
sfc_objects += sfc-icd2 sfc-nss sfc-superfx sfc-sa1
sfc_objects += sfc-necdsp sfc-hitachidsp sfc-armdsp
sfc_objects += sfc-bsx sfc-srtc sfc-sdd1 sfc-spc7110 sfc-rtc4513
sfc_objects += sfc-obc1 sfc-sufamiturbo
sfc_objects += sfc-icd2 sfc-bsx sfc-sufamiturbo sfc-nss
sfc_objects += sfc-sa1 sfc-superfx
sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
sfc_objects += sfc-epsonrtc sfc-sharprtc
sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1
sfc_objects += sfc-msu1 sfc-link
objects += $(sfc_objects)
@ -31,27 +32,32 @@ endif
obj/sfc-interface.o : $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface)
obj/sfc-system.o : $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/)
obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/)
obj/sfc-cartridge.o : $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
obj/sfc-cheat.o : $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
obj/sfc-memory.o : $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/)
obj/sfc-cpu.o : $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/)
obj/sfc-smp.o : $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/)
obj/sfc-dsp.o : $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/)
obj/sfc-ppu.o : $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/)
obj/sfc-cartridge.o : $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
obj/sfc-cheat.o : $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
obj/sfc-nss.o : $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/)
obj/sfc-icd2.o : $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
obj/sfc-superfx.o : $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/)
obj/sfc-sa1.o : $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/)
obj/sfc-necdsp.o : $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
obj/sfc-hitachidsp.o : $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/)
obj/sfc-armdsp.o : $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/)
obj/sfc-bsx.o : $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/)
obj/sfc-srtc.o : $(sfc)/chip/srtc/srtc.cpp $(sfc)/chip/srtc/*
obj/sfc-sdd1.o : $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/*
obj/sfc-spc7110.o : $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
obj/sfc-rtc4513.o : $(sfc)/chip/rtc4513/rtc4513.cpp $(sfc)/chip/rtc4513/*
obj/sfc-obc1.o : $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
obj/sfc-sufamiturbo.o: $(sfc)/chip/sufamiturbo/sufamiturbo.cpp $(sfc)/chip/sufamiturbo/*
obj/sfc-nss.o : $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/)
obj/sfc-sa1.o : $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/)
obj/sfc-superfx.o : $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/)
obj/sfc-armdsp.o : $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/)
obj/sfc-hitachidsp.o : $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/)
obj/sfc-necdsp.o : $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
obj/sfc-epsonrtc.o : $(sfc)/chip/epsonrtc/epsonrtc.cpp $(sfc)/chip/epsonrtc/*
obj/sfc-sharprtc.o : $(sfc)/chip/sharprtc/sharprtc.cpp $(sfc)/chip/sharprtc/*
obj/sfc-spc7110.o : $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
obj/sfc-sdd1.o : $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/*
obj/sfc-obc1.o : $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
obj/sfc-msu1.o : $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/*
obj/sfc-link.o : $(sfc)/chip/link/link.cpp $(sfc)/chip/link/*

View File

@ -19,15 +19,15 @@ void Cartridge::load(const string &markup, const stream &stream) {
has_bs_slot = false;
has_st_slots = false;
has_nss_dip = false;
has_superfx = false;
has_sa1 = false;
has_necdsp = false;
has_hitachidsp = false;
has_superfx = false;
has_armdsp = false;
has_srtc = false;
has_sdd1 = false;
has_hitachidsp = false;
has_necdsp = false;
has_epsonrtc = false;
has_sharprtc = false;
has_spc7110 = false;
has_rtc4513 = false;
has_sdd1 = false;
has_obc1 = false;
has_msu1 = false;
has_link = false;

View File

@ -27,15 +27,15 @@ struct Cartridge : property<Cartridge> {
readonly<bool> has_bs_slot;
readonly<bool> has_st_slots;
readonly<bool> has_nss_dip;
readonly<bool> has_superfx;
readonly<bool> has_sa1;
readonly<bool> has_necdsp;
readonly<bool> has_hitachidsp;
readonly<bool> has_superfx;
readonly<bool> has_armdsp;
readonly<bool> has_srtc;
readonly<bool> has_sdd1;
readonly<bool> has_hitachidsp;
readonly<bool> has_necdsp;
readonly<bool> has_epsonrtc;
readonly<bool> has_sharprtc;
readonly<bool> has_spc7110;
readonly<bool> has_rtc4513;
readonly<bool> has_sdd1;
readonly<bool> has_obc1;
readonly<bool> has_msu1;
readonly<bool> has_link;
@ -70,19 +70,19 @@ private:
void parse_markup_rom(XML::Node&);
void parse_markup_ram(XML::Node&);
void parse_markup_nss(XML::Node&);
void parse_markup_icd2(XML::Node&);
void parse_markup_superfx(XML::Node&);
void parse_markup_sa1(XML::Node&);
void parse_markup_necdsp(XML::Node&);
void parse_markup_hitachidsp(XML::Node&);
void parse_markup_armdsp(XML::Node&);
void parse_markup_bsx(XML::Node&);
void parse_markup_sufamiturbo(XML::Node&);
void parse_markup_srtc(XML::Node&);
void parse_markup_sdd1(XML::Node&);
void parse_markup_nss(XML::Node&);
void parse_markup_sa1(XML::Node&);
void parse_markup_superfx(XML::Node&);
void parse_markup_armdsp(XML::Node&);
void parse_markup_hitachidsp(XML::Node&);
void parse_markup_necdsp(XML::Node&);
void parse_markup_epsonrtc(XML::Node&);
void parse_markup_sharprtc(XML::Node&);
void parse_markup_spc7110(XML::Node&);
void parse_markup_rtc4513(XML::Node&);
void parse_markup_sdd1(XML::Node&);
void parse_markup_obc1(XML::Node&);
void parse_markup_msu1(XML::Node&);
void parse_markup_link(XML::Node&);

View File

@ -9,19 +9,19 @@ void Cartridge::parse_markup(const char *markup) {
parse_markup_rom(cartridge["rom"]);
parse_markup_ram(cartridge["ram"]);
parse_markup_nss(cartridge["nss"]);
parse_markup_icd2(cartridge["icd2"]);
parse_markup_sa1(cartridge["sa1"]);
parse_markup_superfx(cartridge["superfx"]);
parse_markup_necdsp(cartridge["necdsp"]);
parse_markup_hitachidsp(cartridge["hitachidsp"]);
parse_markup_armdsp(cartridge["armdsp"]);
parse_markup_bsx(cartridge["bsx"]);
parse_markup_sufamiturbo(cartridge["sufamiturbo"]);
parse_markup_srtc(cartridge["srtc"]);
parse_markup_sdd1(cartridge["sdd1"]);
parse_markup_nss(cartridge["nss"]);
parse_markup_sa1(cartridge["sa1"]);
parse_markup_superfx(cartridge["superfx"]);
parse_markup_armdsp(cartridge["armdsp"]);
parse_markup_hitachidsp(cartridge["hitachidsp"]);
parse_markup_necdsp(cartridge["necdsp"]);
parse_markup_epsonrtc(cartridge["epsonrtc"]);
parse_markup_sharprtc(cartridge["sharprtc"]);
parse_markup_spc7110(cartridge["spc7110"]);
parse_markup_rtc4513(cartridge["rtc4513"]);
parse_markup_sdd1(cartridge["sdd1"]);
parse_markup_obc1(cartridge["obc1"]);
parse_markup_msu1(cartridge["msu1"]);
parse_markup_link(cartridge["link"]);
@ -86,13 +86,6 @@ void Cartridge::parse_markup_ram(XML::Node &root) {
}
}
void Cartridge::parse_markup_nss(XML::Node &root) {
if(root.exists() == false) return;
has_nss_dip = true;
nss.dip = interface->dipSettings(root);
}
void Cartridge::parse_markup_icd2(XML::Node &root) {
if(root.exists() == false) return;
has_gb_slot = true;
@ -116,190 +109,6 @@ void Cartridge::parse_markup_icd2(XML::Node &root) {
}
}
void Cartridge::parse_markup_superfx(XML::Node &root) {
if(root.exists() == false) return;
has_superfx = true;
for(auto &node : root) {
if(node.name == "rom") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m(superfx.rom);
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "ram") {
for(auto &leaf : node) {
if(leaf.name == "size") {
ram_size = numeral(leaf.data);
continue;
}
if(leaf.name != "map") continue;
Mapping m(superfx.ram);
parse_markup_map(m, leaf);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
}
}
if(node.name == "mmio") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_sa1(XML::Node &root) {
if(root.exists() == false) return;
has_sa1 = true;
auto &mcurom = root["mcu"]["rom"];
auto &mcuram = root["mcu"]["ram"];
auto &iram = root["iram"];
auto &bwram = root["bwram"];
auto &mmio = root["mmio"];
for(auto &node : mcurom) {
if(node.name != "map") continue;
Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : mcuram) {
if(node.name != "map") continue;
Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : iram) {
if(node.name != "map") continue;
Mapping m(sa1.cpuiram);
parse_markup_map(m, node);
if(m.size == 0) m.size = 2048;
mapping.append(m);
}
ram_size = numeral(bwram["size"].data);
for(auto &node : bwram) {
if(node.name != "map") continue;
Mapping m(sa1.cpubwram);
parse_markup_map(m, node);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
}
for(auto &node : mmio) {
if(node.name != "map") continue;
Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_necdsp(XML::Node &root) {
if(root.exists() == false) return;
has_necdsp = true;
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
necdsp.frequency = numeral(root["frequency"].data);
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
necdsp.revision
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
: NECDSP::Revision::uPD7725;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
if(necdsp.revision == NECDSP::Revision::uPD7725) {
interface->loadRequest(ID::Nec7725DSP, firmware);
}
if(necdsp.revision == NECDSP::Revision::uPD96050) {
interface->loadRequest(ID::Nec96050DSP, firmware);
}
for(auto &node : root) {
if(node.name == "dr") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "sr") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "dp") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
if(root.exists() == false) return;
has_hitachidsp = true;
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
hitachidsp.frequency = numeral(root["frequency"].data);
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
interface->loadRequest(ID::HitachiDSP, firmware);
for(auto &node : root) {
if(node.name == "rom") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "mmio") {
for(auto &leaf : node) {
Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_armdsp(XML::Node &root) {
if(root.exists() == false) return;
has_armdsp = true;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
interface->loadRequest(ID::ArmDSP, firmware);
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({ &ArmDSP::mmio_read, &armdsp }, { &ArmDSP::mmio_write, &armdsp });
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_bsx(XML::Node &root) {
if(root.exists() == false) return;
has_bs_cart = root["mmio"].exists();
@ -365,32 +174,216 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
}
}
void Cartridge::parse_markup_srtc(XML::Node &root) {
void Cartridge::parse_markup_nss(XML::Node &root) {
if(root.exists() == false) return;
has_srtc = true;
has_nss_dip = true;
for(auto &node : root) {
nss.dip = interface->dipSettings(root);
}
void Cartridge::parse_markup_sa1(XML::Node &root) {
if(root.exists() == false) return;
has_sa1 = true;
auto &mcurom = root["mcu"]["rom"];
auto &mcuram = root["mcu"]["ram"];
auto &iram = root["iram"];
auto &bwram = root["bwram"];
auto &mmio = root["mmio"];
for(auto &node : mcurom) {
if(node.name != "map") continue;
Mapping m({ &SRTC::read, &srtc }, { &SRTC::write, &srtc });
Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : mcuram) {
if(node.name != "map") continue;
Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : iram) {
if(node.name != "map") continue;
Mapping m(sa1.cpuiram);
parse_markup_map(m, node);
if(m.size == 0) m.size = 2048;
mapping.append(m);
}
ram_size = numeral(bwram["size"].data);
for(auto &node : bwram) {
if(node.name != "map") continue;
Mapping m(sa1.cpubwram);
parse_markup_map(m, node);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
}
for(auto &node : mmio) {
if(node.name != "map") continue;
Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 });
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_sdd1(XML::Node &root) {
void Cartridge::parse_markup_superfx(XML::Node &root) {
if(root.exists() == false) return;
has_sdd1 = true;
has_superfx = true;
for(auto &node : root["mmio"]) {
for(auto &node : root) {
if(node.name == "rom") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m(superfx.rom);
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "ram") {
for(auto &leaf : node) {
if(leaf.name == "size") {
ram_size = numeral(leaf.data);
continue;
}
if(leaf.name != "map") continue;
Mapping m(superfx.ram);
parse_markup_map(m, leaf);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
}
}
if(node.name == "mmio") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_armdsp(XML::Node &root) {
if(root.exists() == false) return;
has_armdsp = true;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
interface->loadRequest(ID::ArmDSP, firmware);
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
Mapping m({ &ArmDSP::mmio_read, &armdsp }, { &ArmDSP::mmio_write, &armdsp });
parse_markup_map(m, node);
mapping.append(m);
}
}
for(auto &node : root["mcu"]) {
void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
if(root.exists() == false) return;
has_hitachidsp = true;
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
hitachidsp.frequency = numeral(root["frequency"].data);
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
interface->loadRequest(ID::HitachiDSP, firmware);
for(auto &node : root) {
if(node.name == "rom") {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "mmio") {
for(auto &leaf : node) {
Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_necdsp(XML::Node &root) {
if(root.exists() == false) return;
has_necdsp = true;
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
necdsp.frequency = numeral(root["frequency"].data);
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
necdsp.revision
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
: NECDSP::Revision::uPD7725;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
if(necdsp.revision == NECDSP::Revision::uPD7725) {
interface->loadRequest(ID::Nec7725DSP, firmware);
}
if(necdsp.revision == NECDSP::Revision::uPD96050) {
interface->loadRequest(ID::Nec96050DSP, firmware);
}
for(auto &node : root) {
if(node.name == "dr") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "sr") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
if(node.name == "dp") {
for(auto &leaf : node) {
Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp });
parse_markup_map(m, leaf);
mapping.append(m);
}
}
}
}
void Cartridge::parse_markup_epsonrtc(XML::Node &root) {
if(root.exists() == false) return;
has_epsonrtc = true;
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 });
Mapping m({&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_sharprtc(XML::Node &root) {
if(root.exists() == false) return;
has_sharprtc = true;
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
parse_markup_map(m, node);
mapping.append(m);
}
@ -442,13 +435,20 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
}
}
void Cartridge::parse_markup_rtc4513(XML::Node &root) {
void Cartridge::parse_markup_sdd1(XML::Node &root) {
if(root.exists() == false) return;
has_rtc4513 = true;
has_sdd1 = true;
for(auto &node : root) {
for(auto &node : root["mmio"]) {
if(node.name != "map") continue;
Mapping m({&RTC4513::read, &rtc4513}, {&RTC4513::write, &rtc4513});
Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
parse_markup_map(m, node);
mapping.append(m);
}
for(auto &node : root["mcu"]) {
if(node.name != "map") continue;
Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 });
parse_markup_map(m, node);
mapping.append(m);
}

View File

@ -4,19 +4,24 @@ struct Coprocessor : Thread {
};
#include <sfc/chip/icd2/icd2.hpp>
#include <sfc/chip/nss/nss.hpp>
#include <sfc/chip/superfx/superfx.hpp>
#include <sfc/chip/sa1/sa1.hpp>
#include <sfc/chip/necdsp/necdsp.hpp>
#include <sfc/chip/hitachidsp/hitachidsp.hpp>
#include <sfc/chip/armdsp/armdsp.hpp>
#include <sfc/chip/bsx/bsx.hpp>
#include <sfc/chip/srtc/srtc.hpp>
#include <sfc/chip/sdd1/sdd1.hpp>
#include <sfc/chip/spc7110/spc7110.hpp>
#include <sfc/chip/rtc4513/rtc4513.hpp>
#include <sfc/chip/obc1/obc1.hpp>
#include <sfc/chip/sufamiturbo/sufamiturbo.hpp>
#include <sfc/chip/nss/nss.hpp>
#include <sfc/chip/sa1/sa1.hpp>
#include <sfc/chip/superfx/superfx.hpp>
#include <sfc/chip/armdsp/armdsp.hpp>
#include <sfc/chip/hitachidsp/hitachidsp.hpp>
#include <sfc/chip/necdsp/necdsp.hpp>
#include <sfc/chip/epsonrtc/epsonrtc.hpp>
#include <sfc/chip/sharprtc/sharprtc.hpp>
#include <sfc/chip/spc7110/spc7110.hpp>
#include <sfc/chip/sdd1/sdd1.hpp>
#include <sfc/chip/obc1/obc1.hpp>
#include <sfc/chip/msu1/msu1.hpp>
#include <sfc/chip/link/link.hpp>

View File

@ -1,18 +1,18 @@
#include <sfc/sfc.hpp>
#define RTC4513_CPP
#define EPSONRTC_CPP
namespace SuperFamicom {
#include "memory.cpp"
#include "time.cpp"
#include "serialization.cpp"
RTC4513 rtc4513;
EpsonRTC epsonrtc;
void RTC4513::Enter() {
rtc4513.enter();
void EpsonRTC::Enter() {
epsonrtc.enter();
}
void RTC4513::enter() {
void EpsonRTC::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
@ -37,22 +37,22 @@ void RTC4513::enter() {
}
}
void RTC4513::init() {
void EpsonRTC::init() {
}
void RTC4513::load() {
if(cartridge.has_rtc4513()) interface->memory.append({ID::RTC4513, "rtc.ram"});
void EpsonRTC::load() {
if(cartridge.has_epsonrtc()) interface->memory.append({ID::EpsonRTC, "rtc.ram"});
batteryfailure = 1;
}
void RTC4513::unload() {
void EpsonRTC::unload() {
}
void RTC4513::power() {
void EpsonRTC::power() {
}
void RTC4513::reset() {
create(RTC4513::Enter, 32768);
void EpsonRTC::reset() {
create(EpsonRTC::Enter, 32768);
clocks = 0;
seconds = 0;
@ -64,7 +64,7 @@ void RTC4513::reset() {
ready = false;
}
uint8 RTC4513::read(unsigned addr) {
uint8 EpsonRTC::read(unsigned addr) {
cpu.synchronize_coprocessors();
addr &= 3;
@ -87,7 +87,7 @@ uint8 RTC4513::read(unsigned addr) {
}
}
void RTC4513::write(unsigned addr, uint8 data) {
void EpsonRTC::write(unsigned addr, uint8 data) {
cpu.synchronize_coprocessors();
addr &= 3, data &= 15;

View File

@ -1,6 +1,6 @@
//Epson RTC-4513 Real-Time Clock
struct RTC4513 : Coprocessor {
struct EpsonRTC : Coprocessor {
static void Enter();
void enter();
@ -69,20 +69,6 @@ struct RTC4513 : Coprocessor {
uint1 test;
//memory.cpp
unsigned second();
unsigned minute();
unsigned hour();
unsigned day();
unsigned month();
unsigned year();
void second(unsigned);
void minute(unsigned);
void hour(unsigned);
void day(unsigned);
void month(unsigned);
void year(unsigned);
void rtc_reset();
uint4 rtc_read(uint4 addr);
void rtc_write(uint4 addr, uint4 data);
@ -102,4 +88,4 @@ struct RTC4513 : Coprocessor {
void tick_year();
};
extern RTC4513 rtc4513;
extern EpsonRTC epsonrtc;

View File

@ -1,20 +1,6 @@
#ifdef RTC4513_CPP
#ifdef EPSONRTC_CPP
unsigned RTC4513::second() { return secondlo + secondhi * 10; }
unsigned RTC4513::minute() { return minutelo + minutehi * 10; }
unsigned RTC4513::hour () { return hourlo + hourhi * 10; }
unsigned RTC4513::day () { return daylo + dayhi * 10; }
unsigned RTC4513::month () { return monthlo + monthhi * 10; }
unsigned RTC4513::year () { return yearlo + yearhi * 10; }
void RTC4513::second(unsigned data) { secondlo = data % 10; secondhi = (data / 10) % 10; }
void RTC4513::minute(unsigned data) { minutelo = data % 10; minutehi = (data / 10) % 10; }
void RTC4513::hour (unsigned data) { hourlo = data % 10; hourhi = (data / 10) % 10; }
void RTC4513::day (unsigned data) { daylo = data % 10; dayhi = (data / 10) % 10; }
void RTC4513::month (unsigned data) { monthlo = data % 10; monthhi = (data / 10) % 10; }
void RTC4513::year (unsigned data) { yearlo = data % 10; yearhi = (data / 10) % 10; }
void RTC4513::rtc_reset() {
void EpsonRTC::rtc_reset() {
state = State::Mode;
offset = 0;
@ -23,7 +9,7 @@ void RTC4513::rtc_reset() {
minutecarry = 0;
}
uint4 RTC4513::rtc_read(uint4 addr) {
uint4 EpsonRTC::rtc_read(uint4 addr) {
switch(addr) {
case 0: return secondlo;
case 1: return secondhi | batteryfailure << 3;
@ -39,7 +25,7 @@ uint4 RTC4513::rtc_read(uint4 addr) {
case 11: return yearhi;
case 12: return weekday | weekdaycarry << 3;
case 13: {
uint1 readflag = irqflag & irqmask;
uint1 readflag = irqflag & !irqmask;
irqflag = 0;
return hold | calendar << 1 | readflag << 2 | roundseconds << 3;
}
@ -48,7 +34,7 @@ uint4 RTC4513::rtc_read(uint4 addr) {
}
}
void RTC4513::rtc_write(uint4 addr, uint4 data) {
void EpsonRTC::rtc_write(uint4 addr, uint4 data) {
switch(addr) {
case 0:
secondlo = data;
@ -107,8 +93,9 @@ void RTC4513::rtc_write(uint4 addr, uint4 data) {
roundseconds = data >> 3;
if(roundseconds) {
roundseconds = 0;
if(second() >= 30) tick_minute();
second(0);
if(secondhi >= 3) tick_minute();
secondlo = 0;
secondhi = 0;
}
break;
case 14:
@ -123,12 +110,15 @@ void RTC4513::rtc_write(uint4 addr, uint4 data) {
test = data >> 3;
if(atime == 1) meridian = 0;
if(atime == 0) hourhi &= 1;
if(pause) second(0);
if(pause) {
secondlo = 0;
secondhi = 0;
}
break;
}
}
void RTC4513::load(const uint8 *data) {
void EpsonRTC::load(const uint8 *data) {
for(unsigned byte = 0; byte < 8; byte++) {
rtc_write(byte * 2 + 0, data[byte] >> 0);
rtc_write(byte * 2 + 1, data[byte] >> 4);
@ -146,7 +136,7 @@ void RTC4513::load(const uint8 *data) {
while(diff--) tick_second();
}
void RTC4513::save(uint8 *data) {
void EpsonRTC::save(uint8 *data) {
for(unsigned byte = 0; byte < 8; byte++) {
data[byte] = rtc_read(byte * 2 + 0) << 0;
data[byte] |= rtc_read(byte * 2 + 1) << 4;

View File

@ -1,6 +1,6 @@
#ifdef RTC4513_CPP
#ifdef EPSONRTC_CPP
void RTC4513::serialize(serializer &s) {
void EpsonRTC::serialize(serializer &s) {
Thread::serialize(s);
s.integer(clocks);

169
bsnes/sfc/chip/epsonrtc/time.cpp Executable file
View File

@ -0,0 +1,169 @@
#ifdef EPSONRTC_CPP
void EpsonRTC::irq(uint2 period) {
if(period == irqperiod) irqflag = 1;
}
void EpsonRTC::duty() {
if(irqduty) irqflag = 0;
}
void EpsonRTC::tick() {
if(hold) return;
if(pause) return;
if(stop) return;
minutecarry = true;
tick_second();
}
void EpsonRTC::tick_second() {
if(secondlo <= 8 || secondlo == 12) {
secondlo++;
} else {
secondlo = 0;
if(secondhi < 5) {
secondhi++;
} else {
secondhi = 0;
tick_minute();
}
}
}
void EpsonRTC::tick_minute() {
if(minutelo <= 8 || minutelo == 12) {
minutelo++;
} else {
minutelo = 0;
if(minutehi < 5) {
minutehi++;
} else {
minutehi = 0;
tick_hour();
}
}
}
void EpsonRTC::tick_hour() {
if(atime) {
if(hourhi < 2) {
if(hourlo <= 8 || hourlo == 12) {
hourlo++;
} else {
hourlo = !(hourlo & 1);
hourhi++;
}
} else {
if(hourlo != 3 && !(hourlo & 4)) {
if(hourlo <= 8 || hourlo >= 12) {
hourlo++;
} else {
hourlo = !(hourlo & 1);
hourhi++;
}
} else {
hourlo = !(hourlo & 1);
hourhi = 0;
tick_day();
}
}
} else {
if(hourhi == 0) {
if(hourlo <= 8 || hourlo == 12) {
hourlo++;
} else {
hourlo = !(hourlo & 1);
hourhi ^= 1;
}
} else {
if(hourlo & 1) meridian ^= 1;
if(hourlo < 2 || hourlo == 4 || hourlo == 5 || hourlo == 8 || hourlo == 12) {
hourlo++;
} else {
hourlo = !(hourlo & 1);
hourhi ^= 1;
}
if(meridian == 0 && !(hourlo & 1)) tick_day();
}
}
}
void EpsonRTC::tick_day() {
if(calendar == false) return;
weekday = (weekday + 1) + (weekday == 6);
//January - December = 0x01 - 0x09; 0x10 - 0x12
static const unsigned daysinmonth[32] = {
30, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
};
unsigned days = daysinmonth[monthhi << 4 | monthlo];
if(days == 28) {
//add one day for leap years
if((yearhi & 1) == 0 && ((yearlo - 0) & 3) == 0) days++;
if((yearhi & 1) == 1 && ((yearlo - 2) & 3) == 0) days++;
}
if(days == 28 && (dayhi == 3 || (dayhi == 2 && daylo >= 8))) {
daylo = 1;
dayhi = 0;
return tick_month();
}
if(days == 29 && (dayhi == 3 || (dayhi == 2 && (daylo > 8 && daylo != 12)))) {
daylo = 1;
dayhi = 0;
return tick_month();
}
if(days == 30 && (dayhi == 3 || (dayhi == 2 && (daylo == 10 || daylo == 14)))) {
daylo = 1;
dayhi = 0;
return tick_month();
}
if(days == 31 && (dayhi == 3 && (daylo & 3))) {
daylo = 1;
dayhi = 0;
return tick_month();
}
if(daylo <= 8 || daylo == 12) {
daylo++;
} else {
daylo = !(daylo & 1);
dayhi++;
}
}
void EpsonRTC::tick_month() {
if(monthhi == 0 || !(monthlo & 2)) {
if(monthlo <= 8 || monthlo == 12) {
monthlo++;
} else {
monthlo = !(monthlo & 1);
monthhi ^= 1;
}
} else {
monthlo = !(monthlo & 1);
monthhi = 0;
tick_year();
}
}
void EpsonRTC::tick_year() {
if(yearlo <= 8 || yearlo == 12) {
yearlo++;
} else {
yearlo = !(yearlo & 1);
if(yearhi <= 8 || yearhi == 12) {
yearhi++;
} else {
yearhi = !(yearhi & 1);
}
}
}
#endif

View File

@ -1,73 +0,0 @@
#ifdef RTC4513_CPP
void RTC4513::irq(uint2 period) {
if(period == irqperiod) irqflag = 1;
}
void RTC4513::duty() {
if(irqduty) irqflag = 0;
}
void RTC4513::tick() {
if(hold) return;
if(pause) return;
if(stop) return;
minutecarry = true;
tick_second();
}
void RTC4513::tick_second() {
if(second() < 59) return second(second() + 1);
second(0);
tick_minute();
}
void RTC4513::tick_minute() {
if(minute() < 59) return minute(minute() + 1);
minute(0);
tick_hour();
}
void RTC4513::tick_hour() {
if(atime) {
if(hour() < 23) return hour(hour() + 1);
hour(0);
tick_day();
}
else {
if(hour() < 12) return hour(hour() + 1);
hour(1);
meridian ^= 1;
if(meridian == 0) tick_day();
}
}
void RTC4513::tick_day() {
if(calendar == false) return;
static const unsigned daysinmonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
unsigned days = daysinmonth[month() - 1];
if(year() % 4 == 0 && month() == 2) days++;
if(day() < days) return day(day() + 1);
day(1);
if(weekday < 6) weekday++;
else weekday = 0;
tick_month();
}
void RTC4513::tick_month() {
if(month() < 12) return month(month() + 1);
month(1);
tick_year();
}
void RTC4513::tick_year() {
year(year() + 1);
}
#endif

View File

@ -1,6 +1,6 @@
#ifdef SRTC_CPP
#ifdef SHARPRTC_CPP
void SRTC::serialize(serializer &s) {
void SharpRTC::serialize(serializer &s) {
s.array(rtc);
s.integer(rtc_mode);
s.integer(rtc_index);

View File

@ -1,35 +1,35 @@
#include <sfc/sfc.hpp>
#define SRTC_CPP
#define SHARPRTC_CPP
namespace SuperFamicom {
SRTC srtc;
SharpRTC sharprtc;
#include "serialization.cpp"
const unsigned SRTC::months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const unsigned SharpRTC::months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void SRTC::init() {
void SharpRTC::init() {
}
void SRTC::load() {
void SharpRTC::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
interface->memory.append({ID::RTC, "rtc.ram"});
interface->memory.append({ID::SharpRTC, "rtc.ram"});
}
void SRTC::unload() {
void SharpRTC::unload() {
}
void SRTC::power() {
void SharpRTC::power() {
}
void SRTC::reset() {
void SharpRTC::reset() {
rtc_mode = RtcRead;
rtc_index = -1;
update_time();
}
void SRTC::update_time() {
void SharpRTC::update_time() {
time_t rtc_time = (rtc[16] << 0) | (rtc[17] << 8) | (rtc[18] << 16) | (rtc[19] << 24);
time_t current_time = time(0);
@ -119,7 +119,7 @@ void SRTC::update_time() {
//returns day of week for specified date
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008
unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
unsigned SharpRTC::weekday(unsigned year, unsigned month, unsigned day) {
unsigned y = 1900, m = 1; //epoch is 1900-01-01
unsigned sum = 0; //number of days passed since epoch
@ -155,7 +155,7 @@ unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
return (sum + 1) % 7; //1900-01-01 was a Monday
}
uint8 SRTC::read(unsigned addr) {
uint8 SharpRTC::read(unsigned addr) {
addr &= 0xffff;
if(addr == 0x2800) {
@ -176,7 +176,7 @@ uint8 SRTC::read(unsigned addr) {
return cpu.regs.mdr;
}
void SRTC::write(unsigned addr, uint8 data) {
void SharpRTC::write(unsigned addr, uint8 data) {
addr &= 0xffff;
if(addr == 0x2801) {
@ -225,7 +225,4 @@ void SRTC::write(unsigned addr, uint8 data) {
}
}
SRTC::SRTC() {
}
}

View File

@ -1,4 +1,4 @@
struct SRTC {
struct SharpRTC {
uint8 rtc[20];
void init();
@ -11,7 +11,6 @@ struct SRTC {
void write(unsigned addr, uint8 data);
void serialize(serializer&);
SRTC();
private:
static const unsigned months[12];
@ -23,4 +22,4 @@ private:
unsigned weekday(unsigned year, unsigned month, unsigned day);
};
extern SRTC srtc;
extern SharpRTC sharprtc;

View File

@ -32,8 +32,8 @@ unsigned Interface::group(unsigned id) {
case ID::ROM:
case ID::RAM:
case ID::NecDSPRAM:
case ID::RTC:
case ID::RTC4513:
case ID::EpsonRTC:
case ID::SharpRTC:
case ID::BsxRAM:
case ID::BsxPSRAM:
return 0;
@ -105,14 +105,14 @@ void Interface::load(unsigned id, const stream &stream, const string &markup) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2);
}
if(id == ID::RTC) {
stream.read(srtc.rtc, min(stream.size(), sizeof srtc.rtc));
}
if(id == ID::RTC4513) {
if(id == ID::EpsonRTC) {
uint8 data[16] = {0};
stream.read(data, min(stream.size(), sizeof data));
rtc4513.load(data);
epsonrtc.load(data);
}
if(id == ID::SharpRTC) {
stream.read(sharprtc.rtc, min(stream.size(), sizeof sharprtc.rtc));
}
if(id == ID::BsxRAM) {
@ -145,14 +145,14 @@ void Interface::save(unsigned id, const stream &stream) {
for(unsigned n = 0; n < 2048; n++) stream.writel(necdsp.dataRAM[n], 2);
}
if(id == ID::RTC) {
stream.write(srtc.rtc, sizeof srtc.rtc);
if(id == ID::EpsonRTC) {
uint8 data[16];
epsonrtc.save(data);
stream.write(data, sizeof data);
}
if(id == ID::RTC4513) {
uint8 data[16];
rtc4513.save(data);
stream.write(data, sizeof data);
if(id == ID::SharpRTC) {
stream.write(sharprtc.rtc, sizeof sharprtc.rtc);
}
if(id == ID::BsxRAM) {

View File

@ -16,8 +16,8 @@ struct ID {
SufamiTurboSlotBROM,
RAM,
NecDSPRAM,
RTC,
RTC4513,
EpsonRTC,
SharpRTC,
BsxRAM,
BsxPSRAM,
SuperGameBoyRAM,

View File

@ -60,15 +60,15 @@ void System::serialize_all(serializer &s) {
if(cartridge.has_gb_slot()) icd2.serialize(s);
if(cartridge.has_bs_cart()) bsxcartridge.serialize(s);
if(cartridge.has_st_slots()) sufamiturbo.serialize(s);
if(cartridge.has_superfx()) superfx.serialize(s);
if(cartridge.has_sa1()) sa1.serialize(s);
if(cartridge.has_necdsp()) necdsp.serialize(s);
if(cartridge.has_hitachidsp()) hitachidsp.serialize(s);
if(cartridge.has_superfx()) superfx.serialize(s);
if(cartridge.has_armdsp()) armdsp.serialize(s);
if(cartridge.has_srtc()) srtc.serialize(s);
if(cartridge.has_sdd1()) sdd1.serialize(s);
if(cartridge.has_hitachidsp()) hitachidsp.serialize(s);
if(cartridge.has_necdsp()) necdsp.serialize(s);
if(cartridge.has_epsonrtc()) epsonrtc.serialize(s);
if(cartridge.has_sharprtc()) sharprtc.serialize(s);
if(cartridge.has_spc7110()) spc7110.serialize(s);
if(cartridge.has_rtc4513()) rtc4513.serialize(s);
if(cartridge.has_sdd1()) sdd1.serialize(s);
if(cartridge.has_obc1()) obc1.serialize(s);
if(cartridge.has_msu1()) msu1.serialize(s);
}

View File

@ -62,22 +62,22 @@ void System::runthreadtosave() {
}
void System::init() {
assert(interface != 0);
assert(interface != nullptr);
icd2.init();
nss.init();
superfx.init();
sa1.init();
necdsp.init();
hitachidsp.init();
armdsp.init();
bsxsatellaview.init();
icd2.init();
bsxcartridge.init();
bsxflash.init();
srtc.init();
sdd1.init();
nss.init();
sa1.init();
superfx.init();
armdsp.init();
hitachidsp.init();
necdsp.init();
epsonrtc.init();
sharprtc.init();
spc7110.init();
rtc4513.init();
sdd1.init();
obc1.init();
msu1.init();
link.init();
@ -116,15 +116,15 @@ void System::load() {
if(cartridge.has_bs_slot()) bsxflash.load();
if(cartridge.has_st_slots()) sufamiturbo.load();
if(cartridge.has_nss_dip()) nss.load();
if(cartridge.has_superfx()) superfx.load();
if(cartridge.has_sa1()) sa1.load();
if(cartridge.has_necdsp()) necdsp.load();
if(cartridge.has_hitachidsp()) hitachidsp.load();
if(cartridge.has_superfx()) superfx.load();
if(cartridge.has_armdsp()) armdsp.load();
if(cartridge.has_srtc()) srtc.load();
if(cartridge.has_sdd1()) sdd1.load();
if(cartridge.has_hitachidsp()) hitachidsp.load();
if(cartridge.has_necdsp()) necdsp.load();
if(cartridge.has_epsonrtc()) epsonrtc.load();
if(cartridge.has_sharprtc()) sharprtc.load();
if(cartridge.has_spc7110()) spc7110.load();
if(cartridge.has_rtc4513()) rtc4513.load();
if(cartridge.has_sdd1()) sdd1.load();
if(cartridge.has_obc1()) obc1.load();
if(cartridge.has_msu1()) msu1.load();
if(cartridge.has_link()) link.load();
@ -140,15 +140,15 @@ void System::unload() {
if(cartridge.has_bs_slot()) bsxflash.unload();
if(cartridge.has_st_slots()) sufamiturbo.unload();
if(cartridge.has_nss_dip()) nss.unload();
if(cartridge.has_superfx()) superfx.unload();
if(cartridge.has_sa1()) sa1.unload();
if(cartridge.has_necdsp()) necdsp.unload();
if(cartridge.has_hitachidsp()) hitachidsp.unload();
if(cartridge.has_superfx()) superfx.unload();
if(cartridge.has_armdsp()) armdsp.unload();
if(cartridge.has_srtc()) srtc.unload();
if(cartridge.has_sdd1()) sdd1.unload();
if(cartridge.has_hitachidsp()) hitachidsp.unload();
if(cartridge.has_necdsp()) necdsp.unload();
if(cartridge.has_epsonrtc()) epsonrtc.unload();
if(cartridge.has_sharprtc()) sharprtc.unload();
if(cartridge.has_spc7110()) spc7110.unload();
if(cartridge.has_rtc4513()) rtc4513.unload();
if(cartridge.has_sdd1()) sdd1.unload();
if(cartridge.has_obc1()) obc1.unload();
if(cartridge.has_msu1()) msu1.unload();
if(cartridge.has_link()) link.unload();
@ -167,15 +167,15 @@ void System::power() {
if(cartridge.has_bs_cart()) bsxcartridge.power();
if(cartridge.has_bs_slot()) bsxflash.power();
if(cartridge.has_nss_dip()) nss.power();
if(cartridge.has_superfx()) superfx.power();
if(cartridge.has_sa1()) sa1.power();
if(cartridge.has_necdsp()) necdsp.power();
if(cartridge.has_hitachidsp()) hitachidsp.power();
if(cartridge.has_superfx()) superfx.power();
if(cartridge.has_armdsp()) armdsp.power();
if(cartridge.has_srtc()) srtc.power();
if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_hitachidsp()) hitachidsp.power();
if(cartridge.has_necdsp()) necdsp.power();
if(cartridge.has_sharprtc()) sharprtc.power();
if(cartridge.has_epsonrtc()) epsonrtc.power();
if(cartridge.has_spc7110()) spc7110.power();
if(cartridge.has_rtc4513()) rtc4513.power();
if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_obc1()) obc1.power();
if(cartridge.has_msu1()) msu1.power();
if(cartridge.has_link()) link.power();
@ -194,27 +194,27 @@ void System::reset() {
if(cartridge.has_bs_cart()) bsxcartridge.reset();
if(cartridge.has_bs_slot()) bsxflash.reset();
if(cartridge.has_nss_dip()) nss.reset();
if(cartridge.has_superfx()) superfx.reset();
if(cartridge.has_sa1()) sa1.reset();
if(cartridge.has_necdsp()) necdsp.reset();
if(cartridge.has_hitachidsp()) hitachidsp.reset();
if(cartridge.has_superfx()) superfx.reset();
if(cartridge.has_armdsp()) armdsp.reset();
if(cartridge.has_srtc()) srtc.reset();
if(cartridge.has_sdd1()) sdd1.reset();
if(cartridge.has_hitachidsp()) hitachidsp.reset();
if(cartridge.has_necdsp()) necdsp.reset();
if(cartridge.has_epsonrtc()) epsonrtc.reset();
if(cartridge.has_sharprtc()) sharprtc.reset();
if(cartridge.has_spc7110()) spc7110.reset();
if(cartridge.has_rtc4513()) rtc4513.reset();
if(cartridge.has_sdd1()) sdd1.reset();
if(cartridge.has_obc1()) obc1.reset();
if(cartridge.has_msu1()) msu1.reset();
if(cartridge.has_link()) link.reset();
if(cartridge.has_gb_slot()) cpu.coprocessors.append(&icd2);
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp);
if(cartridge.has_hitachidsp()) cpu.coprocessors.append(&hitachidsp);
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
if(cartridge.has_armdsp()) cpu.coprocessors.append(&armdsp);
if(cartridge.has_hitachidsp()) cpu.coprocessors.append(&hitachidsp);
if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp);
if(cartridge.has_epsonrtc()) cpu.coprocessors.append(&epsonrtc);
if(cartridge.has_spc7110()) cpu.coprocessors.append(&spc7110);
if(cartridge.has_rtc4513()) cpu.coprocessors.append(&rtc4513);
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
if(cartridge.has_link()) cpu.coprocessors.append(&link);