#include #define SYSTEM_CPP namespace SuperFamicom { System system; Configuration configuration; Random random; #include "video.cpp" #include "audio.cpp" #include "device.cpp" #include "serialization.cpp" #include System::System() { region = Region::Autodetect; expansionPort = Device::ID::eBoot; } auto System::run() -> void { scheduler.sync = Scheduler::SynchronizeMode::None; scheduler.enter(); if(scheduler.exit_reason == Scheduler::ExitReason::FrameEvent) { video.update(); } } auto System::runToSave() -> void { if(CPU::Threaded == true) { scheduler.sync = Scheduler::SynchronizeMode::CPU; runThreadToSave(); } if(SMP::Threaded == true) { scheduler.thread = smp.thread; runThreadToSave(); } if(PPU::Threaded == true) { scheduler.thread = ppu.thread; runThreadToSave(); } if(DSP::Threaded == true) { scheduler.thread = dsp.thread; runThreadToSave(); } for(unsigned i = 0; i < cpu.coprocessors.size(); i++) { auto& chip = *cpu.coprocessors[i]; scheduler.thread = chip.thread; runThreadToSave(); } } auto System::runThreadToSave() -> void { while(true) { scheduler.enter(); if(scheduler.exit_reason == Scheduler::ExitReason::SynchronizeEvent) break; if(scheduler.exit_reason == Scheduler::ExitReason::FrameEvent) { video.update(); } } } auto System::init() -> void { assert(interface != nullptr); eboot.init(); satellaviewbaseunit.init(); icd2.init(); mcc.init(); nss.init(); event.init(); sa1.init(); superfx.init(); armdsp.init(); hitachidsp.init(); necdsp.init(); epsonrtc.init(); sharprtc.init(); spc7110.init(); sdd1.init(); obc1.init(); msu1.init(); satellaviewcartridge.init(); video.init(); audio.init(); device.connect(0, configuration.controllerPort1); device.connect(1, configuration.controllerPort2); } auto System::term() -> void { } auto System::load() -> void { interface->loadRequest(ID::SystemManifest, "manifest.bml", true); auto document = BML::unserialize(information.manifest); if(auto iplrom = document["system/smp/rom/name"].text()) { interface->loadRequest(ID::IPLROM, iplrom, true); } region = configuration.region; if(region == Region::Autodetect) { region = (cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL); } expansionPort = configuration.expansionPort; cpuFrequency = region() == Region::NTSC ? 21477272 : 21281370; apuFrequency = 24606720; audio.coprocessor_enable(false); bus.reset(); bus.map(); cpu.enable(); ppu.enable(); if(expansionPort() == Device::ID::Satellaview) satellaviewbaseunit.load(); if(expansionPort() == Device::ID::eBoot) eboot.load(); if(cartridge.hasICD2()) icd2.load(); if(cartridge.hasMCC()) mcc.load(); if(cartridge.hasNSSDIP()) nss.load(); if(cartridge.hasEvent()) event.load(); if(cartridge.hasSA1()) sa1.load(); if(cartridge.hasSuperFX()) superfx.load(); if(cartridge.hasARMDSP()) armdsp.load(); if(cartridge.hasHitachiDSP()) hitachidsp.load(); if(cartridge.hasNECDSP()) necdsp.load(); if(cartridge.hasEpsonRTC()) epsonrtc.load(); if(cartridge.hasSharpRTC()) sharprtc.load(); if(cartridge.hasSPC7110()) spc7110.load(); if(cartridge.hasSDD1()) sdd1.load(); if(cartridge.hasOBC1()) obc1.load(); if(cartridge.hasMSU1()) msu1.load(); if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.load(); if(cartridge.hasSufamiTurboSlots()) sufamiturboA.load(), sufamiturboB.load(); serializeInit(); } auto System::unload() -> void { if(expansionPort() == Device::ID::Satellaview) satellaviewbaseunit.unload(); if(expansionPort() == Device::ID::eBoot) eboot.unload(); if(cartridge.hasICD2()) icd2.unload(); if(cartridge.hasMCC()) mcc.unload(); if(cartridge.hasNSSDIP()) nss.unload(); if(cartridge.hasEvent()) event.unload(); if(cartridge.hasSA1()) sa1.unload(); if(cartridge.hasSuperFX()) superfx.unload(); if(cartridge.hasARMDSP()) armdsp.unload(); if(cartridge.hasHitachiDSP()) hitachidsp.unload(); if(cartridge.hasNECDSP()) necdsp.unload(); if(cartridge.hasEpsonRTC()) epsonrtc.unload(); if(cartridge.hasSharpRTC()) sharprtc.unload(); if(cartridge.hasSPC7110()) spc7110.unload(); if(cartridge.hasSDD1()) sdd1.unload(); if(cartridge.hasOBC1()) obc1.unload(); if(cartridge.hasMSU1()) msu1.unload(); if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.unload(); if(cartridge.hasSufamiTurboSlots()) sufamiturboA.unload(), sufamiturboB.unload(); } auto System::power() -> void { random.seed((uint)time(0)); cpu.power(); smp.power(); dsp.power(); ppu.power(); if(expansionPort() == Device::ID::Satellaview) satellaviewbaseunit.power(); if(expansionPort() == Device::ID::eBoot) eboot.power(); if(cartridge.hasICD2()) icd2.power(); if(cartridge.hasMCC()) mcc.power(); if(cartridge.hasNSSDIP()) nss.power(); if(cartridge.hasEvent()) event.power(); if(cartridge.hasSA1()) sa1.power(); if(cartridge.hasSuperFX()) superfx.power(); if(cartridge.hasARMDSP()) armdsp.power(); if(cartridge.hasHitachiDSP()) hitachidsp.power(); if(cartridge.hasNECDSP()) necdsp.power(); if(cartridge.hasEpsonRTC()) epsonrtc.power(); if(cartridge.hasSharpRTC()) sharprtc.power(); if(cartridge.hasSPC7110()) spc7110.power(); if(cartridge.hasSDD1()) sdd1.power(); if(cartridge.hasOBC1()) obc1.power(); if(cartridge.hasMSU1()) msu1.power(); if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.power(); reset(); } auto System::reset() -> void { cpu.reset(); smp.reset(); dsp.reset(); ppu.reset(); if(expansionPort() == Device::ID::Satellaview) satellaviewbaseunit.reset(); if(expansionPort() == Device::ID::eBoot) eboot.reset(); if(cartridge.hasICD2()) icd2.reset(); if(cartridge.hasMCC()) mcc.reset(); if(cartridge.hasNSSDIP()) nss.reset(); if(cartridge.hasEvent()) event.reset(); if(cartridge.hasSA1()) sa1.reset(); if(cartridge.hasSuperFX()) superfx.reset(); if(cartridge.hasARMDSP()) armdsp.reset(); if(cartridge.hasHitachiDSP()) hitachidsp.reset(); if(cartridge.hasNECDSP()) necdsp.reset(); if(cartridge.hasEpsonRTC()) epsonrtc.reset(); if(cartridge.hasSharpRTC()) sharprtc.reset(); if(cartridge.hasSPC7110()) spc7110.reset(); if(cartridge.hasSDD1()) sdd1.reset(); if(cartridge.hasOBC1()) obc1.reset(); if(cartridge.hasMSU1()) msu1.reset(); if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.reset(); if(cartridge.hasICD2()) cpu.coprocessors.append(&icd2); if(cartridge.hasEvent()) cpu.coprocessors.append(&event); if(cartridge.hasSA1()) cpu.coprocessors.append(&sa1); if(cartridge.hasSuperFX()) cpu.coprocessors.append(&superfx); if(cartridge.hasARMDSP()) cpu.coprocessors.append(&armdsp); if(cartridge.hasHitachiDSP()) cpu.coprocessors.append(&hitachidsp); if(cartridge.hasNECDSP()) cpu.coprocessors.append(&necdsp); if(cartridge.hasEpsonRTC()) cpu.coprocessors.append(&epsonrtc); if(cartridge.hasSharpRTC()) cpu.coprocessors.append(&sharprtc); if(cartridge.hasSPC7110()) cpu.coprocessors.append(&spc7110); if(cartridge.hasMSU1()) cpu.coprocessors.append(&msu1); scheduler.init(); device.connect(0, configuration.controllerPort1); device.connect(1, configuration.controllerPort2); } auto System::scanline() -> void { video.scanline(); if(cpu.vcounter() == 241) scheduler.exit(Scheduler::ExitReason::FrameEvent); } auto System::frame() -> void { } }