mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
bd61432322
commit
d6001a2df4
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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) {
|
||||
|
|
|
@ -16,8 +16,8 @@ struct ID {
|
|||
SufamiTurboSlotBROM,
|
||||
RAM,
|
||||
NecDSPRAM,
|
||||
RTC,
|
||||
RTC4513,
|
||||
EpsonRTC,
|
||||
SharpRTC,
|
||||
BsxRAM,
|
||||
BsxPSRAM,
|
||||
SuperGameBoyRAM,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue