diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index a6d11ee1..6373a42e 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.11"; + static const string Version = "097.12"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/fc/cartridge/cartridge.cpp b/higan/fc/cartridge/cartridge.cpp index e3d1e9e5..d976416d 100644 --- a/higan/fc/cartridge/cartridge.cpp +++ b/higan/fc/cartridge/cartridge.cpp @@ -6,10 +6,6 @@ namespace Famicom { #include "board/board.cpp" Cartridge cartridge; -auto Cartridge::loaded() const -> bool { - return _loaded; -} - auto Cartridge::sha256() const -> string { return _sha256; } @@ -40,14 +36,9 @@ auto Cartridge::load() -> void { sha.data(board->prgrom.data, board->prgrom.size); sha.data(board->chrrom.data, board->chrrom.size); _sha256 = sha.digest(); - - system.load(); - _loaded = true; } auto Cartridge::unload() -> void { - if(!loaded()) return; - _loaded = false; memory.reset(); } diff --git a/higan/fc/cartridge/cartridge.hpp b/higan/fc/cartridge/cartridge.hpp index bb2fd69b..727547b2 100644 --- a/higan/fc/cartridge/cartridge.hpp +++ b/higan/fc/cartridge/cartridge.hpp @@ -5,7 +5,6 @@ struct Cartridge : Thread { static auto Main() -> void; auto main() -> void; - auto loaded() const -> bool; auto sha256() const -> string; auto manifest() const -> string; auto title() const -> string; @@ -31,7 +30,6 @@ struct Cartridge : Thread { //privileged: Board* board = nullptr; - bool _loaded = false; string _sha256; auto prg_read(uint addr) -> uint8; diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 3aaa556c..2d9ce982 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -63,7 +63,7 @@ auto Interface::audioFrequency() -> double { } auto Interface::loaded() -> bool { - return cartridge.loaded(); + return system.loaded(); } auto Interface::sha256() -> string { @@ -86,7 +86,7 @@ auto Interface::group(uint id) -> uint { } auto Interface::load(uint id) -> void { - cartridge.load(); + system.load(); } auto Interface::save() -> void { @@ -133,7 +133,7 @@ auto Interface::save(uint id, const stream& stream) -> void { auto Interface::unload() -> void { save(); - cartridge.unload(); + system.unload(); } auto Interface::power() -> void { @@ -149,7 +149,7 @@ auto Interface::run() -> void { } auto Interface::serialize() -> serializer { - system.runtosave(); + system.runToSave(); return system.serialize(); } diff --git a/higan/fc/system/serialization.cpp b/higan/fc/system/serialization.cpp index da5a5d2e..5b0fb459 100644 --- a/higan/fc/system/serialization.cpp +++ b/higan/fc/system/serialization.cpp @@ -1,5 +1,5 @@ auto System::serialize() -> serializer { - serializer s(serialize_size); + serializer s(_serializeSize); uint signature = 0x31545342, version = Info::SerializerVersion; char hash[64], description[512]; @@ -11,7 +11,7 @@ auto System::serialize() -> serializer { s.array(hash); s.array(description); - serialize_all(s); + serializeAll(s); return s; } @@ -28,14 +28,14 @@ auto System::unserialize(serializer& s) -> bool { if(version != Info::SerializerVersion) return false; power(); - serialize_all(s); + serializeAll(s); return true; } auto System::serialize(serializer& s) -> void { } -auto System::serialize_all(serializer& s) -> void { +auto System::serializeAll(serializer& s) -> void { system.serialize(s); input.serialize(s); cartridge.serialize(s); @@ -44,7 +44,7 @@ auto System::serialize_all(serializer& s) -> void { ppu.serialize(s); } -auto System::serialize_init() -> void { +auto System::serializeInit() -> void { serializer s; uint signature = 0, version = 0; @@ -55,6 +55,6 @@ auto System::serialize_init() -> void { s.array(hash); s.array(description); - serialize_all(s); - serialize_size = s.size(); + serializeAll(s); + _serializeSize = s.size(); } diff --git a/higan/fc/system/system.cpp b/higan/fc/system/system.cpp index a54d7b51..065497f6 100644 --- a/higan/fc/system/system.cpp +++ b/higan/fc/system/system.cpp @@ -5,6 +5,8 @@ namespace Famicom { #include "serialization.cpp" System system; +auto System::loaded() const -> bool { return _loaded; } + auto System::run() -> void { scheduler.enter(); if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { @@ -12,26 +14,26 @@ auto System::run() -> void { } } -auto System::runtosave() -> void { +auto System::runToSave() -> void { scheduler.sync = Scheduler::SynchronizeMode::PPU; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.thread = cpu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.thread = apu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.thread = cartridge.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::None; } -auto System::runthreadtosave() -> void { +auto System::runThreadToSave() -> void { while(true) { scheduler.enter(); if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break; @@ -44,8 +46,15 @@ auto System::runthreadtosave() -> void { auto System::load() -> void { interface->loadRequest(ID::SystemManifest, "manifest.bml", true); auto document = BML::unserialize(information.manifest); + cartridge.load(); + serializeInit(); + _loaded = true; +} - serialize_init(); +auto System::unload() -> void { + if(!loaded()) return; + cartridge.unload(); + _loaded = false; } auto System::power() -> void { diff --git a/higan/fc/system/system.hpp b/higan/fc/system/system.hpp index 728103d0..c7e5242d 100644 --- a/higan/fc/system/system.hpp +++ b/higan/fc/system/system.hpp @@ -1,9 +1,12 @@ struct System { + auto loaded() const -> bool; + auto run() -> void; - auto runtosave() -> void; - auto runthreadtosave() -> void; + auto runToSave() -> void; + auto runThreadToSave() -> void; auto load() -> void; + auto unload() -> void; auto power() -> void; auto reset() -> void; @@ -14,14 +17,16 @@ struct System { auto unserialize(serializer&) -> bool; auto serialize(serializer&) -> void; - auto serialize_all(serializer&) -> void; - auto serialize_init() -> void; + auto serializeAll(serializer&) -> void; + auto serializeInit() -> void; struct Information { string manifest; } information; - uint serialize_size; +private: + bool _loaded = false; + uint _serializeSize = 0; }; extern System system; diff --git a/higan/gb/cartridge/cartridge.cpp b/higan/gb/cartridge/cartridge.cpp index 5ec7b892..ab0e3116 100644 --- a/higan/gb/cartridge/cartridge.cpp +++ b/higan/gb/cartridge/cartridge.cpp @@ -13,15 +13,6 @@ namespace GameBoy { #include "serialization.cpp" Cartridge cartridge; -Cartridge::Cartridge() { - loaded = false; - sha256 = ""; -} - -Cartridge::~Cartridge() { - unload(); -} - auto Cartridge::manifest() const -> string { return information.markup; } @@ -30,25 +21,9 @@ auto Cartridge::title() const -> string { return information.title; } -//intended for use with Super Game Boy for when no Game Boy cartridge is inserted -auto Cartridge::load_empty(System::Revision revision) -> void { - unload(); - romsize = 32768; - romdata = allocate(romsize, 0xff); - ramsize = 0; - mapper = &mbc0; - sha256 = Hash::SHA256(romdata, romsize).digest(); - loaded = true; - system.load(revision); -} - auto Cartridge::load(System::Revision revision) -> void { - unload(); - - system.revision = revision; //needed for ID::Manifest to return correct group ID - if(revision != System::Revision::SuperGameBoy) { - interface->loadRequest(ID::Manifest, "manifest.bml", true); - } + information.markup = ""; + interface->loadRequest(ID::Manifest, "manifest.bml", !system.sgb()); information.mapper = Mapper::Unknown; information.ram = false; @@ -78,21 +53,18 @@ auto Cartridge::load(System::Revision revision) -> void { auto rom = document["board/rom"]; auto ram = document["board/ram"]; - romsize = rom["size"].natural(); + romsize = max(32768u, rom["size"].natural()); romdata = allocate(romsize, 0xff); ramsize = ram["size"].natural(); ramdata = allocate(ramsize, 0xff); - //Super Game Boy core loads memory from Super Famicom core - if(revision != System::Revision::SuperGameBoy) { - if(auto name = rom["name"].text()) interface->loadRequest(ID::ROM, name, true); - if(auto name = ram["name"].text()) interface->loadRequest(ID::RAM, name, false); - if(auto name = ram["name"].text()) memory.append({ID::RAM, name}); - } + if(auto name = rom["name"].text()) interface->loadRequest(ID::ROM, name, !system.sgb()); + if(auto name = ram["name"].text()) interface->loadRequest(ID::RAM, name, false); + if(auto name = ram["name"].text()) memory.append({ID::RAM, name}); - information.romsize = rom["size"].natural(); - information.ramsize = ram["size"].natural(); + information.romsize = romsize; + information.ramsize = ramsize; information.battery = (bool)ram["name"]; switch(information.mapper) { default: @@ -107,14 +79,11 @@ auto Cartridge::load(System::Revision revision) -> void { } sha256 = Hash::SHA256(romdata, romsize).digest(); - loaded = true; - system.load(revision); } auto Cartridge::unload() -> void { if(romdata) { delete[] romdata; romdata = nullptr; romsize = 0; } if(ramdata) { delete[] ramdata; ramdata = nullptr; ramsize = 0; } - loaded = false; } auto Cartridge::rom_read(uint addr) -> uint8 { @@ -144,7 +113,7 @@ auto Cartridge::mmio_read(uint16 addr) -> uint8 { if(bootrom_enable) { const uint8* data = nullptr; - switch(system.revision) { default: + switch(system.revision()) { default: case System::Revision::GameBoy: data = system.bootROM.dmg; break; case System::Revision::SuperGameBoy: data = system.bootROM.sgb; break; case System::Revision::GameBoyColor: data = system.bootROM.cgb; break; diff --git a/higan/gb/cartridge/cartridge.hpp b/higan/gb/cartridge/cartridge.hpp index ec1ff541..ab13d649 100644 --- a/higan/gb/cartridge/cartridge.hpp +++ b/higan/gb/cartridge/cartridge.hpp @@ -1,8 +1,4 @@ struct Cartridge : MMIO, property { - Cartridge(); - ~Cartridge(); - - auto load_empty(System::Revision revision) -> void; auto load(System::Revision revision) -> void; auto unload() -> void; @@ -62,7 +58,6 @@ struct Cartridge : MMIO, property { }; vector memory; - readonly loaded; readonly sha256; uint8* romdata = nullptr; diff --git a/higan/gb/cpu/mmio.cpp b/higan/gb/cpu/mmio.cpp index 6cd4d215..a27174ab 100644 --- a/higan/gb/cpu/mmio.cpp +++ b/higan/gb/cpu/mmio.cpp @@ -18,7 +18,7 @@ auto CPU::mmio_joyp_poll() -> void { dpad |= interface->inputPoll(0, 0, (uint)Input::Left) << 1; dpad |= interface->inputPoll(0, 0, (uint)Input::Right) << 0; - if(system.revision != System::Revision::SuperGameBoy) { + if(system.revision() != System::Revision::SuperGameBoy) { //D-pad pivot makes it impossible to press opposing directions at the same time //however, Super Game Boy BIOS is able to set these bits together if(dpad & 4) dpad &= ~8; //disallow up+down diff --git a/higan/gb/cpu/timing.cpp b/higan/gb/cpu/timing.cpp index 2f71ba26..9ff7d3b5 100644 --- a/higan/gb/cpu/timing.cpp +++ b/higan/gb/cpu/timing.cpp @@ -3,7 +3,7 @@ // 154 scanlines/frame auto CPU::add_clocks(uint clocks) -> void { - if(system.sgb()) system.clocks_executed += clocks; + if(system.sgb()) system._clocksExecuted += clocks; while(clocks--) { if(++status.clock == 0) { diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 01267ff9..d2a8fd26 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -57,7 +57,7 @@ auto Interface::audioFrequency() -> double { } auto Interface::loaded() -> bool { - return cartridge.loaded(); + return system.loaded(); } auto Interface::sha256() -> string { @@ -74,7 +74,7 @@ auto Interface::group(uint id) -> uint { case ID::Manifest: case ID::ROM: case ID::RAM: - switch(system.revision) { + switch(system.revision()) { case System::Revision::GameBoy: return ID::GameBoy; case System::Revision::SuperGameBoy: return ID::SuperGameBoy; case System::Revision::GameBoyColor: return ID::GameBoyColor; @@ -85,9 +85,9 @@ auto Interface::group(uint id) -> uint { } auto Interface::load(uint id) -> void { - if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy); - if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy); - if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor); + if(id == ID::GameBoy) system.load(System::Revision::GameBoy); + if(id == ID::SuperGameBoy) system.load(System::Revision::SuperGameBoy); + if(id == ID::GameBoyColor) system.load(System::Revision::GameBoyColor); } auto Interface::save() -> void { @@ -134,7 +134,7 @@ auto Interface::save(uint id, const stream& stream) -> void { auto Interface::unload() -> void { save(); - cartridge.unload(); + system.unload(); } auto Interface::power() -> void { @@ -150,7 +150,7 @@ auto Interface::run() -> void { } auto Interface::serialize() -> serializer { - system.runtosave(); + system.runToSave(); return system.serialize(); } diff --git a/higan/gb/system/serialization.cpp b/higan/gb/system/serialization.cpp index bded1639..5b56c830 100644 --- a/higan/gb/system/serialization.cpp +++ b/higan/gb/system/serialization.cpp @@ -1,5 +1,5 @@ auto System::serialize() -> serializer { - serializer s(serialize_size); + serializer s(_serializeSize); uint signature = 0x31545342, version = Info::SerializerVersion; char hash[64], description[512]; @@ -11,7 +11,7 @@ auto System::serialize() -> serializer { s.array(hash); s.array(description); - serialize_all(s); + serializeAll(s); return s; } @@ -28,15 +28,15 @@ auto System::unserialize(serializer& s) -> bool { if(version != Info::SerializerVersion) return false; power(); - serialize_all(s); + serializeAll(s); return true; } auto System::serialize(serializer& s) -> void { - s.integer(clocks_executed); + s.integer(_clocksExecuted); } -auto System::serialize_all(serializer& s) -> void { +auto System::serializeAll(serializer& s) -> void { cartridge.serialize(s); system.serialize(s); cpu.serialize(s); @@ -44,7 +44,7 @@ auto System::serialize_all(serializer& s) -> void { apu.serialize(s); } -auto System::serialize_init() -> void { +auto System::serializeInit() -> void { serializer s; uint signature = 0, version = 0, crc32 = 0; @@ -55,6 +55,6 @@ auto System::serialize_init() -> void { s.array(hash); s.array(description); - serialize_all(s); - serialize_size = s.size(); + serializeAll(s); + _serializeSize = s.size(); } diff --git a/higan/gb/system/system.cpp b/higan/gb/system/system.cpp index 1bb6d80b..f264681d 100644 --- a/higan/gb/system/system.cpp +++ b/higan/gb/system/system.cpp @@ -5,6 +5,10 @@ namespace GameBoy { #include "serialization.cpp" System system; +auto System::loaded() const -> bool { return _loaded; } +auto System::revision() const -> Revision { return _revision; } +auto System::clocksExecuted() const -> uint { return _clocksExecuted; } + System::System() { for(auto& byte : bootROM.dmg) byte = 0; for(auto& byte : bootROM.sgb) byte = 0; @@ -20,22 +24,22 @@ auto System::run() -> void { } } -auto System::runtosave() -> void { +auto System::runToSave() -> void { scheduler.sync = Scheduler::SynchronizeMode::CPU; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.active_thread = ppu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.active_thread = apu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::None; } -auto System::runthreadtosave() -> void { +auto System::runThreadToSave() -> void { while(true) { scheduler.enter(); if(scheduler.exit_reason == Scheduler::ExitReason::SynchronizeEvent) break; @@ -50,19 +54,32 @@ auto System::init() -> void { } auto System::load(Revision revision) -> void { - this->revision = revision; - serialize_init(); - if(revision == Revision::SuperGameBoy) return; //Super Famicom core loads boot ROM for SGB + _revision = revision; interface->loadRequest(ID::SystemManifest, "manifest.bml", true); auto document = BML::unserialize(information.manifest); + string path = "system/cpu/rom/name"; + if(revision == Revision::SuperGameBoy) path = "board/icd2/rom/name"; - if(auto bootROM = document["system/cpu/rom/name"].text()) { + if(auto bootROM = document[path].text()) { interface->loadRequest( - revision == Revision::GameBoy ? ID::GameBoyBootROM : ID::GameBoyColorBootROM, + revision == Revision::GameBoy ? ID::GameBoyBootROM + : revision == Revision::SuperGameBoy ? ID::SuperGameBoyBootROM + : revision == Revision::GameBoyColor ? ID::GameBoyColorBootROM + : ID::GameBoyBootROM, bootROM, true ); } + + cartridge.load(revision); + serializeInit(); + _loaded = true; +} + +auto System::unload() -> void { + if(!loaded()) return; + cartridge.unload(); + _loaded = false; } auto System::power() -> void { @@ -74,7 +91,7 @@ auto System::power() -> void { video.power(); scheduler.init(); - clocks_executed = 0; + _clocksExecuted = 0; } } diff --git a/higan/gb/system/system.hpp b/higan/gb/system/system.hpp index 9371d020..45d5c111 100644 --- a/higan/gb/system/system.hpp +++ b/higan/gb/system/system.hpp @@ -9,20 +9,25 @@ struct System { GameBoy, SuperGameBoy, GameBoyColor, - } revision; + }; System(); - inline auto dmg() const { return revision == Revision::GameBoy; } - inline auto sgb() const { return revision == Revision::SuperGameBoy; } - inline auto cgb() const { return revision == Revision::GameBoyColor; } + auto loaded() const -> bool; + auto revision() const -> Revision; + auto clocksExecuted() const -> uint; + + inline auto dmg() const { return _revision == Revision::GameBoy; } + inline auto sgb() const { return _revision == Revision::SuperGameBoy; } + inline auto cgb() const { return _revision == Revision::GameBoyColor; } auto run() -> void; - auto runtosave() -> void; - auto runthreadtosave() -> void; + auto runToSave() -> void; + auto runThreadToSave() -> void; auto init() -> void; auto load(Revision) -> void; + auto unload() -> void; auto power() -> void; //serialization.cpp @@ -30,8 +35,8 @@ struct System { auto unserialize(serializer&) -> bool; auto serialize(serializer&) -> void; - auto serialize_all(serializer&) -> void; - auto serialize_init() -> void; + auto serializeAll(serializer&) -> void; + auto serializeInit() -> void; struct BootROM { uint8 dmg[ 256]; @@ -43,8 +48,10 @@ struct System { string manifest; } information; - uint clocks_executed = 0; - uint serialize_size = 0; + bool _loaded = false; + Revision _revision = Revision::GameBoy; + uint _serializeSize = 0; + uint _clocksExecuted = 0; }; #include diff --git a/higan/gba/cartridge/cartridge.cpp b/higan/gba/cartridge/cartridge.cpp index 7e39ccf2..f8e27c79 100644 --- a/higan/gba/cartridge/cartridge.cpp +++ b/higan/gba/cartridge/cartridge.cpp @@ -23,10 +23,6 @@ Cartridge::~Cartridge() { delete[] flash.data; } -auto Cartridge::loaded() const -> bool { - return isLoaded; -} - auto Cartridge::sha256() const -> string { return information.sha256; } @@ -96,16 +92,10 @@ auto Cartridge::load() -> void { } information.sha256 = Hash::SHA256(mrom.data, mrom.size).digest(); - - system.load(); - isLoaded = true; } auto Cartridge::unload() -> void { - if(isLoaded) { - isLoaded = false; - memory.reset(); - } + memory.reset(); } auto Cartridge::power() -> void { diff --git a/higan/gba/cartridge/cartridge.hpp b/higan/gba/cartridge/cartridge.hpp index de183e11..b0f21c72 100644 --- a/higan/gba/cartridge/cartridge.hpp +++ b/higan/gba/cartridge/cartridge.hpp @@ -1,7 +1,6 @@ struct Cartridge { #include "memory.hpp" - auto loaded() const -> bool; auto sha256() const -> string; auto manifest() const -> string; auto title() const -> string; @@ -31,7 +30,6 @@ struct Cartridge { auto serialize(serializer&) -> void; private: - bool isLoaded = false; bool hasSRAM = false; bool hasEEPROM = false; bool hasFLASH = false; diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index 96ed9499..8b1d78f7 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -57,7 +57,7 @@ auto Interface::audioFrequency() -> double { } auto Interface::loaded() -> bool { - return cartridge.loaded(); + return system.loaded(); } auto Interface::group(uint id) -> uint { @@ -77,7 +77,7 @@ auto Interface::group(uint id) -> uint { } auto Interface::load(uint id) -> void { - cartridge.load(); + system.load(); } auto Interface::save() -> void { @@ -132,7 +132,7 @@ auto Interface::save(uint id, const stream& stream) -> void { auto Interface::unload() -> void { save(); - cartridge.unload(); + system.unload(); } auto Interface::power() -> void { @@ -148,7 +148,7 @@ auto Interface::run() -> void { } auto Interface::serialize() -> serializer { - system.runtosave(); + system.runToSave(); return system.serialize(); } diff --git a/higan/gba/system/serialization.cpp b/higan/gba/system/serialization.cpp index 47f8fabb..e22ce547 100644 --- a/higan/gba/system/serialization.cpp +++ b/higan/gba/system/serialization.cpp @@ -1,5 +1,5 @@ auto System::serialize() -> serializer { - serializer s(serialize_size); + serializer s(_serializeSize); uint signature = 0x31545342, version = Info::SerializerVersion; char hash[64], description[512]; @@ -11,7 +11,7 @@ auto System::serialize() -> serializer { s.array(hash); s.array(description); - serialize_all(s); + serializeAll(s); return s; } @@ -28,7 +28,7 @@ auto System::unserialize(serializer& s) -> bool { if(version != Info::SerializerVersion) return false; power(); - serialize_all(s); + serializeAll(s); return true; } @@ -37,7 +37,7 @@ auto System::serialize(serializer& s) -> void { s.integer(bios.mdr); } -auto System::serialize_all(serializer& s) -> void { +auto System::serializeAll(serializer& s) -> void { cartridge.serialize(s); system.serialize(s); cpu.serialize(s); @@ -46,7 +46,7 @@ auto System::serialize_all(serializer& s) -> void { player.serialize(s); } -auto System::serialize_init() -> void { +auto System::serializeInit() -> void { serializer s; uint signature = 0, version = 0; @@ -57,6 +57,6 @@ auto System::serialize_init() -> void { s.array(hash); s.array(description); - serialize_all(s); - serialize_size = s.size(); + serializeAll(s); + _serializeSize = s.size(); } diff --git a/higan/gba/system/system.cpp b/higan/gba/system/system.cpp index d48a672d..502e3c86 100644 --- a/higan/gba/system/system.cpp +++ b/higan/gba/system/system.cpp @@ -7,6 +7,8 @@ namespace GameBoyAdvance { BIOS bios; System system; +auto System::loaded() const -> bool { return _loaded; } + auto System::init() -> void { } @@ -32,7 +34,15 @@ auto System::load() -> void { interface->loadRequest(ID::BIOS, bios, true); } - serialize_init(); + cartridge.load(); + serializeInit(); + _loaded = true; +} + +auto System::unload() -> void { + if(!loaded()) return; + cartridge.unload(); + _loaded = false; } auto System::run() -> void { @@ -43,22 +53,22 @@ auto System::run() -> void { video.refresh(); } -auto System::runtosave() -> void { +auto System::runToSave() -> void { scheduler.sync = Scheduler::SynchronizeMode::CPU; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.active = ppu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::All; scheduler.active = apu.thread; - runthreadtosave(); + runThreadToSave(); scheduler.sync = Scheduler::SynchronizeMode::None; } -auto System::runthreadtosave() -> void { +auto System::runThreadToSave() -> void { while(true) { scheduler.enter(); if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break; diff --git a/higan/gba/system/system.hpp b/higan/gba/system/system.hpp index c4ad90d9..de33b700 100644 --- a/higan/gba/system/system.hpp +++ b/higan/gba/system/system.hpp @@ -15,26 +15,30 @@ struct BIOS : Memory { }; struct System { + auto loaded() const -> bool; + auto init() -> void; auto term() -> void; auto load() -> void; + auto unload() -> void; auto power() -> void; auto run() -> void; - auto runtosave() -> void; - auto runthreadtosave() -> void; + auto runToSave() -> void; + auto runThreadToSave() -> void; auto serialize() -> serializer; auto unserialize(serializer&) -> bool; auto serialize(serializer&) -> void; - auto serialize_all(serializer&) -> void; - auto serialize_init() -> void; + auto serializeAll(serializer&) -> void; + auto serializeInit() -> void; struct Information { string manifest; } information; - uint serialize_size; + bool _loaded = false; + uint _serializeSize = 0; }; extern BIOS bios; diff --git a/higan/sfc/cartridge/cartridge.cpp b/higan/sfc/cartridge/cartridge.cpp index d0ff1845..b557c25f 100644 --- a/higan/sfc/cartridge/cartridge.cpp +++ b/higan/sfc/cartridge/cartridge.cpp @@ -94,7 +94,7 @@ auto Cartridge::load() -> void { //Game Boy if(cartridge.hasICD2()) { - _sha256 = Hash::SHA256(GameBoy::cartridge.romdata, GameBoy::cartridge.romsize).digest(); + _sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy() } //BS Memory @@ -136,25 +136,13 @@ auto Cartridge::load() -> void { rom.write_protect(true); ram.write_protect(false); - - system.load(); - _loaded = true; } auto Cartridge::loadGameBoy() -> void { - interface->loadRequest(ID::GameBoyManifest, "manifest.bml", true); - auto document = BML::unserialize(information.markup.gameBoy); - information.title.gameBoy = document["information/title"].text(); - - auto rom = document["board/rom"]; - auto ram = document["board/ram"]; - - GameBoy::cartridge.information.markup = information.markup.gameBoy; - GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy); - - if(auto name = rom["name"].text()) interface->loadRequest(ID::GameBoyROM, name, true); - if(auto name = ram["name"].text()) interface->loadRequest(ID::GameBoyRAM, name, false); - if(auto name = ram["name"].text()) memory.append({ID::GameBoyRAM, name}); + //invoked from ICD2::load() + _sha256 = GameBoy::interface->sha256(); + information.markup.gameBoy = GameBoy::interface->manifest(); + information.title.gameBoy = GameBoy::interface->title(); } auto Cartridge::loadBSMemory() -> void { @@ -182,13 +170,13 @@ auto Cartridge::loadSufamiTurboA() -> void { auto ram = document["board/ram"]; if(rom["name"]) { - unsigned size = rom["size"].natural(); + uint size = rom["size"].natural(); sufamiturboA.rom.map(allocate(size, 0xff), size); interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].text(), true); } if(ram["name"]) { - unsigned size = ram["size"].natural(); + uint size = ram["size"].natural(); sufamiturboA.ram.map(allocate(size, 0xff), size); interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].text(), false); memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()}); @@ -208,13 +196,13 @@ auto Cartridge::loadSufamiTurboB() -> void { auto ram = document["board/ram"]; if(rom["name"]) { - unsigned size = rom["size"].natural(); + uint size = rom["size"].natural(); sufamiturboB.rom.map(allocate(size, 0xff), size); interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].text(), true); } if(ram["name"]) { - unsigned size = ram["size"].natural(); + uint size = ram["size"].natural(); sufamiturboB.ram.map(allocate(size, 0xff), size); interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].text(), false); memory.append({ID::SufamiTurboSlotBRAM, ram["name"].text()}); @@ -222,14 +210,9 @@ auto Cartridge::loadSufamiTurboB() -> void { } auto Cartridge::unload() -> void { - if(_loaded) { - system.unload(); - rom.reset(); - ram.reset(); - - _loaded = false; - memory.reset(); - } + rom.reset(); + ram.reset(); + memory.reset(); } } diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 0915744a..3fa72280 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -1,10 +1,6 @@ struct Cartridge : property { enum class Region : unsigned { NTSC, PAL }; - Cartridge() = default; - ~Cartridge() { unload(); } - - auto loaded() const -> bool { return _loaded; } auto sha256() const -> string { return _sha256; } auto region() const -> Region { return _region; } @@ -83,6 +79,7 @@ private: auto loadSufamiTurboA() -> void; auto loadSufamiTurboB() -> void; friend class Interface; + friend class ICD2; //markup.cpp auto parseMarkup(const string&) -> void; @@ -110,7 +107,6 @@ private: auto parseMarkupOBC1(Markup::Node) -> void; auto parseMarkupMSU1(Markup::Node) -> void; - bool _loaded = false; string _sha256; Region _region = Region::NTSC; }; diff --git a/higan/sfc/cartridge/markup.cpp b/higan/sfc/cartridge/markup.cpp index d40ec0d8..6ce726cd 100644 --- a/higan/sfc/cartridge/markup.cpp +++ b/higan/sfc/cartridge/markup.cpp @@ -92,10 +92,7 @@ auto Cartridge::parseMarkupICD2(Markup::Node root) -> void { hasICD2 = true; icd2.revision = max(1, root["revision"].natural()); - GameBoy::cartridge.load_empty(GameBoy::System::Revision::SuperGameBoy); - interface->loadRequest(ID::GameBoy, "Game Boy", "gb", false); - - interface->loadRequest(ID::SuperGameBoyBootROM, root["brom"]["name"].text(), true); + //Game Boy core loads data through ICD2 interface for(auto node : root.find("map")) { parseMarkupMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2}); diff --git a/higan/sfc/controller/usart/usart.cpp b/higan/sfc/controller/usart/usart.cpp index 537a7d73..07b7b516 100644 --- a/higan/sfc/controller/usart/usart.cpp +++ b/higan/sfc/controller/usart/usart.cpp @@ -13,22 +13,11 @@ //Teensy D5 <> Teensy D7 USART::USART(bool port) : Controller(port) { - latched = 0; - data1 = 0; - data2 = 0; - counter = 0; - - rxlength = 0; - rxdata = 0; - - txlength = 0; - txdata = 0; - string filename{interface->path(ID::SuperFamicom), "usart.so"}; if(openAbsolute(filename)) { init = sym("usart_init"); main = sym("usart_main"); - if(init && main) create(Controller::Enter, 10000000); + if(init && main) create(Controller::Enter, 10'000'000); } } @@ -46,9 +35,9 @@ auto USART::enter() -> void { {&USART::writable, this}, {&USART::write, this} ); - main(); + main({}); } - while(true) step(10000000); + while(true) step(10'000'000); } auto USART::quit() -> bool { @@ -56,8 +45,8 @@ auto USART::quit() -> bool { return false; } -auto USART::usleep(unsigned milliseconds) -> void { - step(10 * milliseconds); +auto USART::usleep(uint microseconds) -> void { + step(10 * microseconds); } auto USART::readable() -> bool { @@ -91,7 +80,7 @@ auto USART::data() -> uint2 { if(iobit()) { if(counter >= 16) return 1; uint2 result = 0; - if(counter < 12) result = interface->inputPoll(port, (unsigned)Device::ID::Gamepad, counter); + if(counter < 12) result = interface->inputPoll(port, (uint)Device::ID::Gamepad, counter); if(latched == 0) counter++; return result; } diff --git a/higan/sfc/controller/usart/usart.hpp b/higan/sfc/controller/usart/usart.hpp index 3243489e..53be4610 100644 --- a/higan/sfc/controller/usart/usart.hpp +++ b/higan/sfc/controller/usart/usart.hpp @@ -5,7 +5,7 @@ struct USART : Controller, public library { auto enter() -> void; auto quit() -> bool; - auto usleep(unsigned milliseconds) -> void; + auto usleep(uint microseconds) -> void; auto readable() -> bool; auto read() -> uint8; auto writable() -> bool; @@ -15,26 +15,26 @@ struct USART : Controller, public library { auto latch(bool data) -> void; private: - bool latched; - bool data1; - bool data2; - unsigned counter; + bool latched = 0; + bool data1 = 0; + bool data2 = 0; + uint counter = 0; - uint8 rxlength; - uint8 rxdata; + uint8 rxlength = 0; + uint8 rxdata = 0; vector rxbuffer; - uint8 txlength; - uint8 txdata; + uint8 txlength = 0; + uint8 txdata = 0; vector txbuffer; function, //quit - function, //usleep - function, //readable - function, //read - function, //writable - function //write + function, //quit + function, //usleep + function, //readable + function, //read + function, //writable + function //write )> init; - function main; + function main; }; diff --git a/higan/sfc/coprocessor/icd2/icd2.cpp b/higan/sfc/coprocessor/icd2/icd2.cpp index 03d3a058..a63a6242 100644 --- a/higan/sfc/coprocessor/icd2/icd2.cpp +++ b/higan/sfc/coprocessor/icd2/icd2.cpp @@ -12,14 +12,14 @@ auto ICD2::Enter() -> void { icd2.enter(); } auto ICD2::enter() -> void { while(true) { if(scheduler.sync == Scheduler::SynchronizeMode::All) { - GameBoy::system.runtosave(); + GameBoy::system.runToSave(); scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } if(r6003 & 0x80) { GameBoy::system.run(); - step(GameBoy::system.clocks_executed); - GameBoy::system.clocks_executed = 0; + step(GameBoy::system._clocksExecuted); + GameBoy::system._clocksExecuted = 0; } else { //DMG halted audio.coprocessorSample(0, 0); step(1); @@ -36,9 +36,13 @@ auto ICD2::load() -> void { hook = GameBoy::interface->hook; GameBoy::interface->bind = this; GameBoy::interface->hook = this; + interface->loadRequest(ID::GameBoy, "Game Boy", "gb", false); + GameBoy::interface->load(GameBoy::ID::SuperGameBoy); + cartridge.loadGameBoy(); } auto ICD2::unload() -> void { + GameBoy::interface->unload(); GameBoy::interface->bind = bind; GameBoy::interface->hook = hook; } diff --git a/higan/sfc/coprocessor/icd2/icd2.hpp b/higan/sfc/coprocessor/icd2/icd2.hpp index 721c31ac..fa13c808 100644 --- a/higan/sfc/coprocessor/icd2/icd2.hpp +++ b/higan/sfc/coprocessor/icd2/icd2.hpp @@ -16,10 +16,11 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor { uint revision; private: - Emulator::Interface::Bind* bind = nullptr; - GameBoy::Interface::Hook* hook = nullptr; #include "interface/interface.hpp" #include "mmio/mmio.hpp" + + Emulator::Interface::Bind* bind = nullptr; + GameBoy::Interface::Hook* hook = nullptr; }; extern ICD2 icd2; diff --git a/higan/sfc/coprocessor/icd2/interface/interface.cpp b/higan/sfc/coprocessor/icd2/interface/interface.cpp index 47001e12..0f93a78e 100644 --- a/higan/sfc/coprocessor/icd2/interface/interface.cpp +++ b/higan/sfc/coprocessor/icd2/interface/interface.cpp @@ -85,8 +85,35 @@ auto ICD2::joypWrite(bool p15, bool p14) -> void { packetlock = true; } -auto ICD2::videoColor(uint source, uint16 red, uint16 green, uint16 blue) -> uint32 { - return source; +auto ICD2::loadRequest(uint id, string name, string type, bool required) -> void { +} + +auto ICD2::loadRequest(uint id, string name, bool required) -> void { + if(id == GameBoy::ID::SystemManifest) { + interface->loadRequest(ID::SuperGameBoyManifest, name, required); + } + + if(id == GameBoy::ID::SuperGameBoyBootROM) { + interface->loadRequest(ID::SuperGameBoyBootROM, name, required); + } + + if(id == GameBoy::ID::Manifest) { + interface->loadRequest(ID::GameBoyManifest, name, required); + } + + if(id == GameBoy::ID::ROM) { + interface->loadRequest(ID::GameBoyROM, name, required); + } + + if(id == GameBoy::ID::RAM) { + interface->loadRequest(ID::GameBoyRAM, name, required); + } +} + +auto ICD2::saveRequest(uint id, string name) -> void { + if(id == GameBoy::ID::RAM) { + interface->saveRequest(ID::GameBoyRAM, name); + } } auto ICD2::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { diff --git a/higan/sfc/coprocessor/icd2/interface/interface.hpp b/higan/sfc/coprocessor/icd2/interface/interface.hpp index 859eabfe..f6dcde6c 100644 --- a/higan/sfc/coprocessor/icd2/interface/interface.hpp +++ b/higan/sfc/coprocessor/icd2/interface/interface.hpp @@ -1,11 +1,14 @@ -auto lcdScanline() -> void; -auto lcdOutput(uint2 color) -> void; -auto joypWrite(bool p15, bool p14) -> void; +auto lcdScanline() -> void override; +auto lcdOutput(uint2 color) -> void override; +auto joypWrite(bool p15, bool p14) -> void override; -auto videoColor(uint source, uint16 red, uint16 green, uint16 blue) -> uint32; -auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void; -auto audioSample(int16 lsample, int16 rsample) -> void; -auto inputPoll(uint port, uint device, uint id) -> int16; +auto loadRequest(uint id, string name, string type, bool required) -> void override; +auto loadRequest(uint id, string name, bool required) -> void override; +auto saveRequest(uint id, string name) -> void override; + +auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; +auto audioSample(int16 lsample, int16 rsample) -> void override; +auto inputPoll(uint port, uint device, uint id) -> int16 override; struct Packet { auto operator[](uint addr) -> uint8& { return data[addr & 15]; } diff --git a/higan/sfc/coprocessor/icd2/serialization.cpp b/higan/sfc/coprocessor/icd2/serialization.cpp index cd1f10a1..249685bc 100644 --- a/higan/sfc/coprocessor/icd2/serialization.cpp +++ b/higan/sfc/coprocessor/icd2/serialization.cpp @@ -1,6 +1,6 @@ auto ICD2::serialize(serializer& s) -> void { Thread::serialize(s); - GameBoy::system.serialize_all(s); + GameBoy::system.serializeAll(s); for(auto n : range(64)) s.array(packet[n].data); s.integer(packetsize); diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index c6de2436..48170adf 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -154,7 +154,7 @@ auto Interface::audioFrequency() -> double { } auto Interface::loaded() -> bool { - return cartridge.loaded(); + return system.loaded(); } auto Interface::sha256() -> string { @@ -200,6 +200,7 @@ auto Interface::group(uint id) -> uint { case ID::SDD1ROM: case ID::SDD1RAM: case ID::OBC1RAM: + case ID::SuperGameBoyManifest: case ID::SuperGameBoyBootROM: case ID::MCCROM: case ID::MCCRAM: @@ -229,8 +230,7 @@ auto Interface::group(uint id) -> uint { } auto Interface::load(uint id) -> void { - if(id == ID::SuperFamicom) cartridge.load(); - if(id == ID::GameBoy) cartridge.loadGameBoy(); + if(id == ID::SuperFamicom) system.load(); if(id == ID::BSMemory) cartridge.loadBSMemory(); if(id == ID::SufamiTurboSlotA) cartridge.loadSufamiTurboA(); if(id == ID::SufamiTurboSlotB) cartridge.loadSufamiTurboB(); @@ -327,21 +327,27 @@ auto Interface::load(uint id, const stream& stream) -> void { if(id == ID::OBC1RAM) obc1.ram.read(stream); - if(id == ID::SuperGameBoyBootROM) { - stream.read(GameBoy::system.bootROM.sgb, min(stream.size(), 256u)); - } - if(id == ID::MCCROM) mcc.rom.read(stream); if(id == ID::MCCRAM) mcc.ram.read(stream); - if(id == ID::GameBoyManifest) cartridge.information.markup.gameBoy = stream.text(); + if(id == ID::SuperGameBoyManifest) { + GameBoy::interface->load(GameBoy::ID::SystemManifest, stream); + } + + if(id == ID::SuperGameBoyBootROM) { + GameBoy::interface->load(GameBoy::ID::SuperGameBoyBootROM, stream); + } + + if(id == ID::GameBoyManifest) { + GameBoy::interface->load(GameBoy::ID::Manifest, stream); + } if(id == ID::GameBoyROM) { - stream.read(GameBoy::cartridge.romdata, min(GameBoy::cartridge.romsize, stream.size())); + GameBoy::interface->load(GameBoy::ID::ROM, stream); } if(id == ID::GameBoyRAM) { - stream.read(GameBoy::cartridge.ramdata, min(GameBoy::cartridge.ramsize, stream.size())); + GameBoy::interface->load(GameBoy::ID::RAM, stream); } if(id == ID::BSMemoryManifest) cartridge.information.markup.bsMemory = stream.text(); @@ -395,7 +401,9 @@ auto Interface::save(uint id, const stream& stream) -> void { if(id == ID::SDD1RAM) stream.write(sdd1.ram.data(), sdd1.ram.size()); if(id == ID::OBC1RAM) stream.write(obc1.ram.data(), obc1.ram.size()); - if(id == ID::GameBoyRAM) stream.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); + if(id == ID::GameBoyRAM) { + GameBoy::interface->save(GameBoy::ID::RAM, stream); + } if(id == ID::MCCRAM) stream.write(mcc.ram.data(), mcc.ram.size()); @@ -405,7 +413,7 @@ auto Interface::save(uint id, const stream& stream) -> void { auto Interface::unload() -> void { save(); - cartridge.unload(); + system.unload(); } auto Interface::connect(uint port, uint device) -> void { diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index f7a46b63..3d9995a4 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -60,11 +60,12 @@ struct ID { OBC1RAM, - SuperGameBoyBootROM, - MCCROM, MCCRAM, + SuperGameBoyManifest, + SuperGameBoyBootROM, + GameBoyManifest, GameBoyROM, GameBoyRAM, diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index 60e00d35..4e848986 100644 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -10,6 +10,7 @@ System system; #include +auto System::loaded() const -> bool { return _loaded; } auto System::region() const -> Region { return _region; } auto System::expansionPort() const -> Device::ID { return _expansionPort; } auto System::cpuFrequency() const -> uint { return _cpuFrequency; } @@ -95,6 +96,7 @@ auto System::load() -> void { interface->loadRequest(ID::IPLROM, iplrom, true); } + cartridge.load(); _region = cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL; _expansionPort = (Device::ID)settings.expansionPort; _cpuFrequency = region() == Region::NTSC ? 21477272 : 21281370; @@ -129,9 +131,11 @@ auto System::load() -> void { if(cartridge.hasSufamiTurboSlots()) sufamiturboA.load(), sufamiturboB.load(); serializeInit(); + _loaded = true; } auto System::unload() -> void { + if(!loaded()) return; if(expansionPort() == Device::ID::Satellaview) satellaview.unload(); if(expansionPort() == Device::ID::eBoot) eboot.unload(); @@ -153,6 +157,9 @@ auto System::unload() -> void { if(cartridge.hasBSMemorySlot()) bsmemory.unload(); if(cartridge.hasSufamiTurboSlots()) sufamiturboA.unload(), sufamiturboB.unload(); + + cartridge.unload(); + _loaded = false; } auto System::power() -> void { diff --git a/higan/sfc/system/system.hpp b/higan/sfc/system/system.hpp index c4bb4e39..bea7d06f 100644 --- a/higan/sfc/system/system.hpp +++ b/higan/sfc/system/system.hpp @@ -5,6 +5,7 @@ struct Interface; struct System { enum class Region : bool { NTSC = 0, PAL = 1 }; + auto loaded() const -> bool; auto region() const -> Region; auto expansionPort() const -> Device::ID; auto cpuFrequency() const -> uint; @@ -34,6 +35,7 @@ private: auto serializeAll(serializer&) -> void; auto serializeInit() -> void; + bool _loaded = false; Region _region = Region::NTSC; Device::ID _expansionPort = Device::ID::None; uint _cpuFrequency = 0; diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index 3fd95f0c..c722cf7b 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -192,10 +192,8 @@ auto Presentation::updateEmulator() -> void { if(devices.objectCount() > 1) { auto path = string{emulator->information.name, "/", port.name}.replace(" ", ""); auto device = settings(path).text(); - for(auto object : devices.objects()) { - if(auto item = object.cast()) { - if(item.text() == device) item.setChecked().doActivate(); - } + for(auto item : devices.objects()) { + if(item.text() == device) item.setChecked(); } menu.setVisible(); } diff --git a/higan/target-tomoko/program/interface.cpp b/higan/target-tomoko/program/interface.cpp index 7918574d..1af604ac 100644 --- a/higan/target-tomoko/program/interface.cpp +++ b/higan/target-tomoko/program/interface.cpp @@ -17,7 +17,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void { string pathname = mediaPaths(emulator->group(id)); string location = {pathname, filename}; - if(filename == "manifest.bml" && !pathname.find(".sys/")) { + if(filename == "manifest.bml" && pathname && !pathname.find(".sys/")) { if(!file::exists(location) || settings["Library/IgnoreManifests"].boolean()) { if(auto manifest = execute("icarus", "--manifest", pathname)) { memorystream stream{(const uint8*)manifest.data(), manifest.size()}; diff --git a/higan/target-tomoko/program/media.cpp b/higan/target-tomoko/program/media.cpp index 61e76e47..7db8af2c 100644 --- a/higan/target-tomoko/program/media.cpp +++ b/higan/target-tomoko/program/media.cpp @@ -6,23 +6,24 @@ auto Program::loadMedia(string location) -> void { string type = suffixname(location).ltrim(".", 1L); for(auto& emulator : emulators) { for(auto& media : emulator->media) { - if(media.bootable == false) continue; + if(!media.bootable) continue; if(media.type != type) continue; return loadMedia(*emulator, media, location); } } } -auto Program::loadMedia(Emulator::Interface& emulator_, Emulator::Interface::Media& media, const string& location) -> void { +auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, const string& location) -> void { unloadMedia(); mediaPaths(0) = locate({media.name, ".sys/"}); mediaPaths(media.id) = location; folderPaths.append(location); - emulator = &emulator_; + emulator = &interface; + connectDevices(); //(expansion port) devices must be connected prior to load emulator->load(media.id); - dsp.setFrequency(emulator->audioFrequency()); + updateAudio(); //audio must be updated after load (audio frequency varies by region) emulator->power(); presentation->resizeViewport(); diff --git a/higan/target-tomoko/program/program.hpp b/higan/target-tomoko/program/program.hpp index 435916b9..4248286c 100644 --- a/higan/target-tomoko/program/program.hpp +++ b/higan/target-tomoko/program/program.hpp @@ -30,6 +30,7 @@ struct Program : Emulator::Interface::Bind { //utility.cpp auto powerCycle() -> void; auto softReset() -> void; + auto connectDevices() -> void; auto showMessage(const string& text) -> void; auto updateStatusText() -> void; auto updateVideoShader() -> void; diff --git a/higan/target-tomoko/program/utility.cpp b/higan/target-tomoko/program/utility.cpp index 62687781..5d35592a 100644 --- a/higan/target-tomoko/program/utility.cpp +++ b/higan/target-tomoko/program/utility.cpp @@ -11,6 +11,20 @@ auto Program::softReset() -> void { showMessage("System reset"); } +auto Program::connectDevices() -> void { + if(!emulator) return; + for(auto& port : emulator->port) { + auto path = string{emulator->information.name, "/", port.name}.replace(" ", ""); + auto name = settings(path).text(); + for(auto& device : port.device) { + if(device.name == name) { + emulator->connect(port.id, device.id); + break; + } + } + } +} + auto Program::showMessage(const string& text) -> void { statusTime = time(0); statusMessage = text; @@ -52,8 +66,8 @@ auto Program::updateVideoShader() -> void { auto Program::updateAudio() -> void { if(!audio) return; audio->clear(); - audio->set(Audio::Frequency, settings["Audio/Frequency"].natural()); - audio->set(Audio::Latency, settings["Audio/Latency"].natural()); + audio->set(Audio::Frequency, (uint)settings["Audio/Frequency"].natural()); + audio->set(Audio::Latency, (uint)settings["Audio/Latency"].natural()); if(settings["Audio/Resampler"].text() == "Linear" ) dsp.setResampler(DSP::ResampleEngine::Linear); if(settings["Audio/Resampler"].text() == "Hermite") dsp.setResampler(DSP::ResampleEngine::Hermite); if(settings["Audio/Resampler"].text() == "Sinc" ) dsp.setResampler(DSP::ResampleEngine::Sinc); @@ -72,5 +86,6 @@ auto Program::updateDSP() -> void { double inputRatio = emulator->audioFrequency() / emulator->videoFrequency(); double outputRatio = settings["Timing/Audio"].real() / settings["Timing/Video"].real(); + dsp.setFrequency(inputRatio / outputRatio * settings["Audio/Frequency"].natural()); } diff --git a/higan/ws/cartridge/cartridge.cpp b/higan/ws/cartridge/cartridge.cpp index 4bad3527..bf636c5d 100644 --- a/higan/ws/cartridge/cartridge.cpp +++ b/higan/ws/cartridge/cartridge.cpp @@ -5,10 +5,6 @@ namespace WonderSwan { Cartridge cartridge; #include "memory.cpp" -auto Cartridge::loaded() const -> bool { - return _loaded; -} - auto Cartridge::load() -> void { information.manifest = ""; information.title = ""; @@ -35,12 +31,9 @@ auto Cartridge::load() -> void { information.title = document["information/title"].text(); information.sha256 = Hash::SHA256(rom.data, rom.size).digest(); - _loaded = true; } auto Cartridge::unload() -> void { - _loaded = false; - delete[] rom.data; rom.data = nullptr; rom.size = 0; diff --git a/higan/ws/cartridge/cartridge.hpp b/higan/ws/cartridge/cartridge.hpp index 8a42b7ad..ae74b764 100644 --- a/higan/ws/cartridge/cartridge.hpp +++ b/higan/ws/cartridge/cartridge.hpp @@ -1,6 +1,4 @@ struct Cartridge : IO { - auto loaded() const -> bool; - auto load() -> void; auto unload() -> void; auto power() -> void; @@ -33,9 +31,6 @@ struct Cartridge : IO { string title; string sha256; } information; - -privileged: - bool _loaded = false; }; extern Cartridge cartridge; diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index 2fdcf34b..b06eb945 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -75,7 +75,7 @@ auto Interface::audioFrequency() -> double { } auto Interface::loaded() -> bool { - return cartridge.loaded(); + return system.loaded(); } auto Interface::sha256() -> string { diff --git a/higan/ws/system/system.cpp b/higan/ws/system/system.cpp index 9c124eab..d96b1e6f 100644 --- a/higan/ws/system/system.cpp +++ b/higan/ws/system/system.cpp @@ -4,9 +4,8 @@ namespace WonderSwan { System system; -auto System::revision() const -> Revision { - return _revision; -} +auto System::loaded() const -> bool { return _loaded; } +auto System::revision() const -> Revision { return _revision; } auto System::init() -> void { } @@ -23,6 +22,13 @@ auto System::load(Revision revision) -> void { //note: IPLROM is currently undumped; otherwise we'd load it here ... cartridge.load(); + _loaded = true; +} + +auto System::unload() -> void { + if(!loaded()) return; + cartridge.unload(); + _loaded = false; } auto System::power() -> void { diff --git a/higan/ws/system/system.hpp b/higan/ws/system/system.hpp index 10d90604..6e07ba2b 100644 --- a/higan/ws/system/system.hpp +++ b/higan/ws/system/system.hpp @@ -5,11 +5,13 @@ struct System { SwanCrystal, //SCT-001 (SPHINX2) }; + auto loaded() const -> bool; auto revision() const -> Revision; auto init() -> void; auto term() -> void; auto load(Revision) -> void; + auto unload() -> void; auto power() -> void; auto run() -> void; @@ -18,6 +20,7 @@ struct System { } information; privileged: + bool _loaded = false; Revision _revision = Revision::WonderSwan; }; diff --git a/icarus/Database/Super Famicom.bml b/icarus/Database/Super Famicom.bml index ce2b349a..f0439a32 100644 --- a/icarus/Database/Super Famicom.bml +++ b/icarus/Database/Super Famicom.bml @@ -7827,7 +7827,7 @@ cartridge sha256:4d7fc331a811b8dc630b469262fd6f45e289243cef83101f32038158967d1b2 : map address=40-7d,c0-ff:0000-7fff mask=0x8000 : icd2 revision=1 : map address=00-3f,80-bf:6000-67ff,7000-7fff - : brom name=sgb.boot.rom size=0x100 + : rom name=sgb.boot.rom size=0x100 : :information : serial: SNS-A-SG-USA diff --git a/icarus/heuristics/super-famicom.cpp b/icarus/heuristics/super-famicom.cpp index ee466bdb..ec605082 100644 --- a/icarus/heuristics/super-famicom.cpp +++ b/icarus/heuristics/super-famicom.cpp @@ -218,7 +218,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8* data, uint size, bool " map address=40-7d,c0-ff:0000-7fff mask=0x8000\n" " icd2 revision=1\n" " map address=00-3f,80-bf:6000-67ff,7000-7fff\n" - " brom name=sgb.boot.rom size=0x100\n" + " rom name=sgb.boot.rom size=0x100\n" ); } diff --git a/nall/emulation/super-famicom-usart.hpp b/nall/emulation/super-famicom-usart.hpp index 0dbc87ba..c8a16506 100644 --- a/nall/emulation/super-famicom-usart.hpp +++ b/nall/emulation/super-famicom-usart.hpp @@ -8,18 +8,16 @@ using namespace nall; #include #include -#define usartproc dllexport - static function bool> usart_quit; -static function void> usart_usleep; +static function void> usart_usleep; static function bool> usart_readable; static function uint8> usart_read; static function bool> usart_writable; static function void> usart_write; -extern "C" usartproc auto usart_init( +extern "C" auto usart_init( function bool> quit, - function void> usleep, + function void> usleep, function bool> readable, function uint8> read, function bool> writable, @@ -33,7 +31,7 @@ extern "C" usartproc auto usart_init( usart_write = write; } -extern "C" usartproc auto usart_main(nall::lstring) -> void; +extern "C" auto usart_main(nall::lstring) -> void; // @@ -51,8 +49,8 @@ static auto usarthw_quit() -> bool { return usart_sigint; } -static auto usarthw_usleep(uint milliseconds) -> void { - usleep(milliseconds); +static auto usarthw_usleep(uint microseconds) -> void { + usleep(microseconds); } static auto usarthw_readable() -> bool {