From 32a95a976168620c7dad0d65a9bd6d88f6473d4d Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Mon, 8 Feb 2016 14:17:59 +1100 Subject: [PATCH] Update to v097r12 release. byuu says: Nothing WS-related this time. First, I fixed expansion port device mapping. On first load, it was mapping the expansion port device too late, so it ended up not taking effect. I had to spin out the logic for that into Program::connectDevices(). This was proving to be quite annoying while testing eBoot (SNES-Hook simulation.) Second, I fixed the audio->set(Frequency, Latency) functions to take (uint) parameters from the configuration file, so the weird behavior around changing settings in the audio panel should hopefully be gone now. Third, I rewrote the interface->load,unload functions to call into the (Emulator)::System::load,unload functions. And I have those call out to Cartridge::load,unload. Before, this was inverted, and Cartridge::load() was invoking System::load(), which I felt was kind of backward. The Super Game Boy really didn't like this change, however. And it took me a few hours to power through it. Before, I had the Game Boy core dummying out all the interface->(load,save)Request calls, and having the SNES core make them for it. This is because the folder paths and IDs will be different between the two cores. I've redesigned things so that ICD2's Emulator::Interface overloads loadRequest and saveRequest, and translates the requests into new requests for the SuperFamicom core. This allows the Game Boy code to do its own loading for everything without a bunch of Super Game Boy special casing, and without any awkwardness around powering on with no cartridge inserted. This also lets the SNES side of things simply call into higher-level GameBoy::interface->load,save(id, stream) functions instead of stabbing at the raw underlying state inside of various Game Boy core emulation classes. So things are a lot better abstracted now. --- higan/emulator/emulator.hpp | 2 +- higan/fc/cartridge/cartridge.cpp | 9 ---- higan/fc/cartridge/cartridge.hpp | 2 - higan/fc/interface/interface.cpp | 8 +-- higan/fc/system/serialization.cpp | 14 +++--- higan/fc/system/system.cpp | 23 ++++++--- higan/fc/system/system.hpp | 15 ++++-- higan/gb/cartridge/cartridge.cpp | 49 ++++--------------- higan/gb/cartridge/cartridge.hpp | 5 -- higan/gb/cpu/mmio.cpp | 2 +- higan/gb/cpu/timing.cpp | 2 +- higan/gb/interface/interface.cpp | 14 +++--- higan/gb/system/serialization.cpp | 16 +++--- higan/gb/system/system.cpp | 39 ++++++++++----- higan/gb/system/system.hpp | 27 ++++++---- higan/gba/cartridge/cartridge.cpp | 12 +---- higan/gba/cartridge/cartridge.hpp | 2 - higan/gba/interface/interface.cpp | 8 +-- higan/gba/system/serialization.cpp | 14 +++--- higan/gba/system/system.cpp | 22 ++++++--- higan/gba/system/system.hpp | 14 ++++-- higan/sfc/cartridge/cartridge.cpp | 41 +++++----------- higan/sfc/cartridge/cartridge.hpp | 6 +-- higan/sfc/cartridge/markup.cpp | 5 +- higan/sfc/controller/usart/usart.cpp | 23 +++------ higan/sfc/controller/usart/usart.hpp | 32 ++++++------ higan/sfc/coprocessor/icd2/icd2.cpp | 10 ++-- higan/sfc/coprocessor/icd2/icd2.hpp | 5 +- .../coprocessor/icd2/interface/interface.cpp | 31 +++++++++++- .../coprocessor/icd2/interface/interface.hpp | 17 ++++--- higan/sfc/coprocessor/icd2/serialization.cpp | 2 +- higan/sfc/interface/interface.cpp | 32 +++++++----- higan/sfc/interface/interface.hpp | 5 +- higan/sfc/system/system.cpp | 7 +++ higan/sfc/system/system.hpp | 2 + .../presentation/presentation.cpp | 6 +-- higan/target-tomoko/program/interface.cpp | 2 +- higan/target-tomoko/program/media.cpp | 9 ++-- higan/target-tomoko/program/program.hpp | 1 + higan/target-tomoko/program/utility.cpp | 19 ++++++- higan/ws/cartridge/cartridge.cpp | 7 --- higan/ws/cartridge/cartridge.hpp | 5 -- higan/ws/interface/interface.cpp | 2 +- higan/ws/system/system.cpp | 12 +++-- higan/ws/system/system.hpp | 3 ++ icarus/Database/Super Famicom.bml | 2 +- icarus/heuristics/super-famicom.cpp | 2 +- nall/emulation/super-famicom-usart.hpp | 14 +++--- 48 files changed, 311 insertions(+), 290 deletions(-) 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 {