diff --git a/higan/GNUmakefile b/higan/GNUmakefile index ee93ed13..acac7eb2 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -1,7 +1,6 @@ include ../nall/GNUmakefile target := tomoko -# target := loki # console := true flags += -I. -I.. -O3 diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 4339d1cb..b2e7df1d 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -11,7 +11,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "099.07"; + static const string Version = "099.08"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index 42ee1ec8..c375a167 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -27,13 +27,11 @@ struct Interface { struct Device { uint id; - uint portmask; string name; struct Input { - uint id; uint type; //0 = digital, 1 = analog (relative), 2 = rumble string name; - uintptr guid; //user data field + uintptr userData; }; vector inputs; }; @@ -48,7 +46,7 @@ struct Interface { struct Bind { virtual auto path(uint) -> string { return ""; } virtual auto open(uint, string, vfs::file::mode, bool) -> vfs::shared::file { return {}; } - virtual auto load(uint, string, string, bool) -> void {} + virtual auto load(uint, string, string, bool) -> maybe { return nothing; } virtual auto videoRefresh(const uint32*, uint, uint, uint) -> void {} virtual auto audioSample(const double*, uint) -> void {} virtual auto inputPoll(uint, uint, uint) -> int16 { return 0; } @@ -61,7 +59,7 @@ struct Interface { //callback bindings (provided by user interface) auto path(uint id) -> string { return bind->path(id); } auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return bind->open(id, name, mode, required); } - auto load(uint id, string name, string type, bool required = false) -> void { return bind->load(id, name, type, required); } + auto load(uint id, string name, string type, bool required = false) -> maybe { return bind->load(id, name, type, required); } auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { return bind->videoRefresh(data, pitch, width, height); } auto audioSample(const double* samples, uint channels) -> void { return bind->audioSample(samples, channels); } auto inputPoll(uint port, uint device, uint input) -> int16 { return bind->inputPoll(port, device, input); } @@ -84,7 +82,7 @@ struct Interface { //media interface virtual auto loaded() -> bool { return false; } virtual auto sha256() -> string { return ""; } - virtual auto load(uint id) -> void {} + virtual auto load(uint id) -> bool { return false; } virtual auto save() -> void {} virtual auto unload() -> void {} @@ -114,4 +112,12 @@ struct Interface { auto videoColor(uint16 r, uint16 g, uint16 b) -> uint32; }; +//nall/vfs shorthand constants for open(), load() +struct File { + static const auto Read = vfs::file::mode::read; + static const auto Write = vfs::file::mode::write; + static const auto Optional = false; + static const auto Required = true; +}; + } diff --git a/higan/fc/cartridge/board/board.cpp b/higan/fc/cartridge/board/board.cpp index d986212e..4694ff19 100644 --- a/higan/fc/cartridge/board/board.cpp +++ b/higan/fc/cartridge/board/board.cpp @@ -42,22 +42,22 @@ Board::Board(Markup::Node& document) { if(chrram.size) chrram.data = new uint8_t[chrram.size](); if(prgrom.name = prom["name"].text()) { - if(auto fp = interface->open(ID::Famicom, prgrom.name, File::Read, File::Required)) { + if(auto fp = interface->open(cartridge.pathID(), prgrom.name, File::Read, File::Required)) { fp->read(prgrom.data, min(prgrom.size, fp->size())); } } if(prgram.name = pram["name"].text()) { - if(auto fp = interface->open(ID::Famicom, prgram.name, File::Read)) { + if(auto fp = interface->open(cartridge.pathID(), prgram.name, File::Read)) { fp->read(prgram.data, min(prgram.size, fp->size())); } } if(chrrom.name = crom["name"].text()) { - if(auto fp = interface->open(ID::Famicom, chrrom.name, File::Read, File::Required)) { + if(auto fp = interface->open(cartridge.pathID(), chrrom.name, File::Read, File::Required)) { fp->read(chrrom.data, min(chrrom.size, fp->size())); } } if(chrram.name = cram["name"].text()) { - if(auto fp = interface->open(ID::Famicom, chrram.name, File::Read)) { + if(auto fp = interface->open(cartridge.pathID(), chrram.name, File::Read)) { fp->read(chrram.data, min(chrram.size, fp->size())); } } @@ -70,13 +70,13 @@ auto Board::save() -> void { auto document = BML::unserialize(cartridge.manifest()); if(auto name = document["board/prg/ram/name"].text()) { - if(auto fp = interface->open(ID::Famicom, name, File::Write)) { + if(auto fp = interface->open(cartridge.pathID(), name, File::Write)) { fp->write(prgram.data, prgram.size); } } if(auto name = document["board/chr/ram/name"].text()) { - if(auto fp = interface->open(ID::Famicom, name, File::Write)) { + if(auto fp = interface->open(cartridge.pathID(), name, File::Write)) { fp->write(chrram.data, chrram.size); } } diff --git a/higan/fc/cartridge/cartridge.cpp b/higan/fc/cartridge/cartridge.cpp index ebba7b24..e01ac91a 100644 --- a/higan/fc/cartridge/cartridge.cpp +++ b/higan/fc/cartridge/cartridge.cpp @@ -15,7 +15,11 @@ auto Cartridge::main() -> void { } auto Cartridge::load() -> bool { - if(auto fp = interface->open(ID::Famicom, "manifest.bml", File::Read, File::Required)) { + if(auto pathID = interface->load(ID::Famicom, "Famicom", "fc", File::Required)) { + information.pathID = pathID(); + } + + if(auto fp = interface->open(pathID(), "manifest.bml", File::Read, File::Required)) { information.manifest = fp->reads(); } else { return false; diff --git a/higan/fc/cartridge/cartridge.hpp b/higan/fc/cartridge/cartridge.hpp index aff2fae3..12d78f19 100644 --- a/higan/fc/cartridge/cartridge.hpp +++ b/higan/fc/cartridge/cartridge.hpp @@ -5,6 +5,7 @@ struct Cartridge : Thread { static auto Enter() -> void; auto main() -> void; + auto pathID() const -> uint { return information.pathID; } auto sha256() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } @@ -19,6 +20,7 @@ struct Cartridge : Thread { auto serialize(serializer&) -> void; struct Information { + uint pathID = 0; string sha256; string manifest; string title; diff --git a/higan/fc/controller/gamepad/gamepad.cpp b/higan/fc/controller/gamepad/gamepad.cpp index 9a858cbc..38a89476 100644 --- a/higan/fc/controller/gamepad/gamepad.cpp +++ b/higan/fc/controller/gamepad/gamepad.cpp @@ -3,7 +3,7 @@ Gamepad::Gamepad(bool port) : Controller(port) { auto Gamepad::data() -> uint3 { if(counter >= 8) return 1; - if(latched == 1) return interface->inputPoll(port, Device::Gamepad, A); + if(latched == 1) return interface->inputPoll(port, ID::Device::Gamepad, A); switch(counter++) { case 0: return a; @@ -24,7 +24,7 @@ auto Gamepad::latch(bool data) -> void { counter = 0; if(latched == 0) { - auto id = Device::Gamepad; + auto id = ID::Device::Gamepad; a = interface->inputPoll(port, id, A); b = interface->inputPoll(port, id, B); select = interface->inputPoll(port, id, Select); diff --git a/higan/fc/fc.hpp b/higan/fc/fc.hpp index 804c2604..9b647383 100644 --- a/higan/fc/fc.hpp +++ b/higan/fc/fc.hpp @@ -7,12 +7,7 @@ #include namespace Famicom { - struct File { - static const auto Read = vfs::file::mode::read; - static const auto Write = vfs::file::mode::write; - static const auto Optional = false; - static const auto Required = true; - }; + using File = Emulator::File; struct Thread { ~Thread() { diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index ad3a4f45..e869bde0 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -21,32 +21,29 @@ Interface::Interface() { media.append({ID::Famicom, "Famicom", "fc", true}); - { Device device{0, ID::ControllerPort1 | ID::ControllerPort2, "None"}; - devices.append(device); + Port controllerPort1{ID::Port::Controller1, "Controller Port 1"}; + Port controllerPort2{ID::Port::Controller2, "Controller Port 2"}; + + { Device device{ID::Device::None, "None"}; + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); } - { Device device{1, ID::ControllerPort1 | ID::ControllerPort2, "Gamepad"}; - device.inputs.append({0, 0, "Up" }); - device.inputs.append({1, 0, "Down" }); - device.inputs.append({2, 0, "Left" }); - device.inputs.append({3, 0, "Right" }); - device.inputs.append({4, 0, "B" }); - device.inputs.append({5, 0, "A" }); - device.inputs.append({6, 0, "Select"}); - device.inputs.append({7, 0, "Start" }); - devices.append(device); + { Device device{ID::Device::Gamepad, "Gamepad"}; + device.inputs.append({0, "Up" }); + device.inputs.append({0, "Down" }); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right" }); + device.inputs.append({0, "B" }); + device.inputs.append({0, "A" }); + device.inputs.append({0, "Select"}); + device.inputs.append({0, "Start" }); + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); } - ports.append({0, "Port 1"}); - ports.append({1, "Port 2"}); - - for(auto& device : devices) { - for(auto& port : ports) { - if(device.portmask & (1 << port.id)) { - port.devices.append(device); - } - } - } + ports.append(move(controllerPort1)); + ports.append(move(controllerPort2)); } auto Interface::manifest() -> string { @@ -128,8 +125,8 @@ auto Interface::sha256() -> string { return cartridge.sha256(); } -auto Interface::load(uint id) -> void { - system.load(); +auto Interface::load(uint id) -> bool { + return system.load(); } auto Interface::save() -> void { diff --git a/higan/fc/interface/interface.hpp b/higan/fc/interface/interface.hpp index 21b4aedf..bc6d7e05 100644 --- a/higan/fc/interface/interface.hpp +++ b/higan/fc/interface/interface.hpp @@ -1,50 +1,54 @@ namespace Famicom { struct ID { - enum : uint { //paths + enum : uint { System, Famicom, }; - enum : uint { //bitmasks - ControllerPort1 = 1, - ControllerPort2 = 2, - ExpansionPort = 4, - }; + struct Port { enum : uint { + Controller1, + Controller2, + Expansion, + };}; + + struct Device { enum : uint { + None, + Gamepad, + };}; }; struct Interface : Emulator::Interface { + using Emulator::Interface::load; + Interface(); - auto manifest() -> string; - auto title() -> string; - auto videoFrequency() -> double; - auto videoColors() -> uint32; - auto videoColor(uint32 color) -> uint64; - auto audioFrequency() -> double; + auto manifest() -> string override; + auto title() -> string override; + auto videoFrequency() -> double override; + auto videoColors() -> uint32 override; + auto videoColor(uint32 color) -> uint64 override; + auto audioFrequency() -> double override; - auto loaded() -> bool; - auto sha256() -> string; - auto load(uint id) -> void; - auto save() -> void; - auto unload() -> void; + auto loaded() -> bool override; + auto sha256() -> string override; + auto load(uint id) -> bool override; + auto save() -> void override; + auto unload() -> void override; - auto connect(uint port, uint device) -> void; - auto power() -> void; - auto reset() -> void; - auto run() -> void; + auto connect(uint port, uint device) -> void override; + auto power() -> void override; + auto reset() -> void override; + auto run() -> void override; - auto serialize() -> serializer; - auto unserialize(serializer&) -> bool; + auto serialize() -> serializer override; + auto unserialize(serializer&) -> bool override; - auto cheatSet(const lstring&) -> void; + auto cheatSet(const lstring&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; auto set(const string& name, const any& value) -> bool override; - -private: - vector devices; }; struct Settings { diff --git a/higan/fc/system/peripherals.cpp b/higan/fc/system/peripherals.cpp index 8b0fea73..35aab590 100644 --- a/higan/fc/system/peripherals.cpp +++ b/higan/fc/system/peripherals.cpp @@ -8,34 +8,34 @@ auto Peripherals::unload() -> void { } auto Peripherals::reset() -> void { - connect(Port::Controller1, settings.controllerPort1); - connect(Port::Controller2, settings.controllerPort2); + connect(ID::Port::Controller1, settings.controllerPort1); + connect(ID::Port::Controller2, settings.controllerPort2); } auto Peripherals::connect(uint port, uint device) -> void { - if(port == Port::Controller1) { + if(port == ID::Port::Controller1) { settings.controllerPort1 = device; if(!system.loaded()) return; delete controllerPort1; switch(device) { default: - case Device::None: controllerPort1 = new Controller(0); break; - case Device::Gamepad: controllerPort1 = new Gamepad(0); break; + case ID::Device::None: controllerPort1 = new Controller(0); break; + case ID::Device::Gamepad: controllerPort1 = new Gamepad(0); break; } } - if(port == Port::Controller2) { + if(port == ID::Port::Controller2) { settings.controllerPort2 = device; if(!system.loaded()) return; delete controllerPort2; switch(device) { default: - case Device::None: controllerPort2 = new Controller(1); break; - case Device::Gamepad: controllerPort2 = new Gamepad(1); break; + case ID::Device::None: controllerPort2 = new Controller(1); break; + case ID::Device::Gamepad: controllerPort2 = new Gamepad(1); break; } } - if(port == Port::Expansion) { + if(port == ID::Port::Expansion) { settings.expansionPort = device; if(!system.loaded()) return; } diff --git a/higan/fc/system/peripherals.hpp b/higan/fc/system/peripherals.hpp index e26789c6..7c7a5ab7 100644 --- a/higan/fc/system/peripherals.hpp +++ b/higan/fc/system/peripherals.hpp @@ -1,18 +1,3 @@ -struct Port { enum : uint { - Controller1, - Controller2, - Expansion, -};}; - -struct Device { enum : uint { - None, - - //controller port peripherals - Gamepad, - - //expansion port peripherals -};}; - struct Peripherals { auto unload() -> void; auto reset() -> void; diff --git a/higan/fc/system/system.cpp b/higan/fc/system/system.cpp index f7f1ee3b..7318c98b 100644 --- a/higan/fc/system/system.cpp +++ b/higan/fc/system/system.cpp @@ -28,7 +28,7 @@ auto System::load() -> bool { return false; } auto document = BML::unserialize(information.manifest); - cartridge.load(); + if(!cartridge.load()) return false; serializeInit(); return _loaded = true; } diff --git a/higan/gb/cartridge/cartridge.cpp b/higan/gb/cartridge/cartridge.cpp index 60693f78..0a1fc755 100644 --- a/higan/gb/cartridge/cartridge.cpp +++ b/higan/gb/cartridge/cartridge.cpp @@ -16,11 +16,26 @@ Cartridge cartridge; auto Cartridge::load(System::Revision revision) -> bool { information = Information(); - if(revision == System::Revision::GameBoy) information.mode = ID::GameBoy; - if(revision == System::Revision::SuperGameBoy) information.mode = ID::SuperGameBoy; - if(revision == System::Revision::GameBoyColor) information.mode = ID::GameBoyColor; - if(auto fp = interface->open(mode(), "manifest.bml", File::Read, File::Required)) { + switch(revision) { + case System::Revision::GameBoy: + if(auto pathID = interface->load(ID::GameBoy, "Game Boy", "gb", true)) { + information.pathID = pathID(); + } else return false; + break; + case System::Revision::SuperGameBoy: + if(auto pathID = interface->load(ID::SuperGameBoy, "Game Boy", "gb", true)) { + information.pathID = pathID(); + } else return false; + break; + case System::Revision::GameBoyColor: + if(auto pathID = interface->load(ID::GameBoyColor, "Game Boy Color", "gbc", true)) { + information.pathID = pathID(); + } else return false; + break; + } + + if(auto fp = interface->open(pathID(), "manifest.bml", File::Read, File::Required)) { information.manifest = fp->reads(); } else return false; @@ -51,12 +66,12 @@ auto Cartridge::load(System::Revision revision) -> bool { ramdata = allocate(ramsize, 0xff); if(auto name = rom["name"].text()) { - if(auto fp = interface->open(mode(), name, File::Read, File::Required)) { + if(auto fp = interface->open(pathID(), name, File::Read, File::Required)) { fp->read(romdata, min(romsize, fp->size())); } } if(auto name = ram["name"].text()) { - if(auto fp = interface->open(mode(), name, File::Read, File::Optional)) { + if(auto fp = interface->open(pathID(), name, File::Read, File::Optional)) { fp->read(ramdata, min(ramsize, fp->size())); } } @@ -85,7 +100,7 @@ auto Cartridge::save() -> void { auto document = BML::unserialize(information.manifest); if(auto name = document["board/ram/name"].text()) { - if(auto fp = interface->open(mode(), name, File::Write)) { + if(auto fp = interface->open(pathID(), name, File::Write)) { fp->write(ramdata, ramsize); } } diff --git a/higan/gb/cartridge/cartridge.hpp b/higan/gb/cartridge/cartridge.hpp index 19498624..f7dea3b3 100644 --- a/higan/gb/cartridge/cartridge.hpp +++ b/higan/gb/cartridge/cartridge.hpp @@ -1,7 +1,7 @@ struct Cartridge : MMIO, property { + auto pathID() const -> uint { return information.pathID; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } - auto mode() const -> uint { return information.mode; } auto load(System::Revision revision) -> bool; auto save() -> void; @@ -43,9 +43,9 @@ struct Cartridge : MMIO, property { }; struct Information { + uint pathID = 0; string manifest; string title; - uint mode = 0; Mapper mapper = Mapper::Unknown; boolean ram; @@ -57,6 +57,7 @@ struct Cartridge : MMIO, property { uint ramsize = 0; } information; + uint _pathID = 0; readonly sha256; uint8* romdata = nullptr; diff --git a/higan/gb/gb.hpp b/higan/gb/gb.hpp index e9edf363..cdfd5883 100644 --- a/higan/gb/gb.hpp +++ b/higan/gb/gb.hpp @@ -7,12 +7,7 @@ #include namespace GameBoy { - struct File { - static const auto Read = vfs::file::mode::read; - static const auto Write = vfs::file::mode::write; - static const auto Optional = false; - static const auto Required = true; - }; + using File = Emulator::File; struct Thread { ~Thread() { diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index e2d98b09..27a73e6c 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -23,20 +23,21 @@ Interface::Interface() { media.append({ID::GameBoy, "Game Boy", "gb" , true}); media.append({ID::GameBoyColor, "Game Boy Color", "gbc", true}); - { - Device device{0, ID::Device, "Controller"}; - device.inputs.append({0, 0, "Up" }); - device.inputs.append({1, 0, "Down" }); - device.inputs.append({2, 0, "Left" }); - device.inputs.append({3, 0, "Right" }); - device.inputs.append({4, 0, "B" }); - device.inputs.append({5, 0, "A" }); - device.inputs.append({6, 0, "Select"}); - device.inputs.append({7, 0, "Start" }); - devices.append(device); + Port hardwarePort{ID::Port::Hardware, "Hardware"}; + + { Device device{ID::Device::Controls, "Controls"}; + device.inputs.append({0, "Up" }); + device.inputs.append({0, "Down" }); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right" }); + device.inputs.append({0, "B" }); + device.inputs.append({0, "A" }); + device.inputs.append({0, "Select"}); + device.inputs.append({0, "Start" }); + hardwarePort.devices.append(device); } - ports.append({0, "Device", {devices[0]}}); + ports.append(move(hardwarePort)); } auto Interface::manifest() -> string { @@ -124,10 +125,11 @@ auto Interface::sha256() -> string { return cartridge.sha256(); } -auto Interface::load(uint id) -> void { - 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::load(uint id) -> bool { + if(id == ID::GameBoy) return system.load(System::Revision::GameBoy); + if(id == ID::SuperGameBoy) return system.load(System::Revision::SuperGameBoy); + if(id == ID::GameBoyColor) return system.load(System::Revision::GameBoyColor); + return false; } auto Interface::save() -> void { diff --git a/higan/gb/interface/interface.hpp b/higan/gb/interface/interface.hpp index 5adeb35c..bda1b882 100644 --- a/higan/gb/interface/interface.hpp +++ b/higan/gb/interface/interface.hpp @@ -8,46 +8,41 @@ struct ID { GameBoyColor, }; - enum : uint { - SystemManifest, - GameBoyBootROM, - SuperGameBoyBootROM, - GameBoyColorBootROM, + struct Port { enum : uint { + Hardware, + };}; - Manifest, - ROM, - RAM, - }; - - enum : uint { - Device = 1, - }; + struct Device { enum : uint { + Controls, + };}; }; struct Interface : Emulator::Interface { + using Emulator::Interface::load; + Interface(); - auto manifest() -> string; - auto title() -> string; - auto videoFrequency() -> double; - auto videoColors() -> uint32; - auto videoColor(uint32 color) -> uint64; - auto audioFrequency() -> double; + auto manifest() -> string override; + auto title() -> string override; + auto videoFrequency() -> double override; + auto videoColors() -> uint32 override; + auto videoColor(uint32 color) -> uint64 override; + auto audioFrequency() -> double override; - auto loaded() -> bool; - auto sha256() -> string; - auto load(uint id) -> void; - auto save() -> void; - auto unload() -> void; + auto loaded() -> bool override; + auto sha256() -> string override; + auto load(uint id) -> bool override; + auto save() -> void override; + auto unload() -> void override; - auto power() -> void; - auto reset() -> void; - auto run() -> void; + auto power() -> void override; + auto reset() -> void override; + auto run() -> void override; - auto serialize() -> serializer; - auto unserialize(serializer&) -> bool; + auto serialize() -> serializer override; + auto unserialize(serializer&) -> bool override; - auto cheatSet(const lstring&) -> void; + auto cheatSet(const lstring&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -64,9 +59,6 @@ struct Interface : Emulator::Interface { auto lcdScanline() -> void; auto lcdOutput(uint2 color) -> void; auto joypWrite(bool p15, bool p14) -> void; - -private: - vector devices; }; struct Settings { diff --git a/higan/gb/system/system.cpp b/higan/gb/system/system.cpp index 2c9dc6dd..9eddbd96 100644 --- a/higan/gb/system/system.cpp +++ b/higan/gb/system/system.cpp @@ -39,7 +39,7 @@ auto System::load(Revision revision) -> bool { } } - cartridge.load(revision); + if(!cartridge.load(revision)) return false; serializeInit(); return _loaded = true; } diff --git a/higan/gba/cartridge/cartridge.cpp b/higan/gba/cartridge/cartridge.cpp index 75a9daf2..fa7124ec 100644 --- a/higan/gba/cartridge/cartridge.cpp +++ b/higan/gba/cartridge/cartridge.cpp @@ -26,7 +26,11 @@ Cartridge::~Cartridge() { auto Cartridge::load() -> bool { information = Information(); - if(auto fp = interface->open(ID::GameBoyAdvance, "manifest.bml", File::Read, File::Required)) { + if(auto pathID = interface->load(ID::GameBoyAdvance, "Game Boy Advance", "gba", File::Required)) { + information.pathID = pathID(); + } else return false; + + if(auto fp = interface->open(pathID(), "manifest.bml", File::Read, File::Required)) { information.manifest = fp->reads(); } else return false; @@ -39,7 +43,7 @@ auto Cartridge::load() -> bool { if(auto node = document["board/rom"]) { mrom.size = min(32 * 1024 * 1024, node["size"].natural()); - if(auto fp = interface->open(ID::GameBoyAdvance, node["name"].text(), File::Read, File::Required)) { + if(auto fp = interface->open(pathID(), node["name"].text(), File::Read, File::Required)) { fp->read(mrom.data, mrom.size); } } @@ -51,7 +55,7 @@ auto Cartridge::load() -> bool { sram.mask = sram.size - 1; for(auto n : range(sram.size)) sram.data[n] = 0xff; - if(auto fp = interface->open(ID::GameBoyAdvance, node["name"].text(), File::Read)) { + if(auto fp = interface->open(pathID(), node["name"].text(), File::Read)) { fp->read(sram.data, sram.size); } } @@ -65,7 +69,7 @@ auto Cartridge::load() -> bool { eeprom.test = mrom.size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000; for(auto n : range(eeprom.size)) eeprom.data[n] = 0xff; - if(auto fp = interface->open(ID::GameBoyAdvance, node["name"].text(), File::Read)) { + if(auto fp = interface->open(pathID(), node["name"].text(), File::Read)) { fp->read(eeprom.data, eeprom.size); } } @@ -81,7 +85,7 @@ auto Cartridge::load() -> bool { if(!flash.id && flash.size == 64 * 1024) flash.id = 0x1cc2; if(!flash.id && flash.size == 128 * 1024) flash.id = 0x09c2; - if(auto fp = interface->open(ID::GameBoyAdvance, node["name"].text(), File::Read)) { + if(auto fp = interface->open(pathID(), node["name"].text(), File::Read)) { fp->read(flash.data, flash.size); } } @@ -94,7 +98,7 @@ auto Cartridge::load() -> bool { auto Cartridge::save() -> void { auto document = BML::unserialize(information.manifest); if(auto node = document["board/ram"]) { - if(auto fp = interface->open(ID::GameBoyAdvance, node["name"].text(), File::Write)) { + if(auto fp = interface->open(pathID(), node["name"].text(), File::Write)) { if(node["type"].text() == "sram") fp->write(sram.data, sram.size); if(node["type"].text() == "eeprom") fp->write(eeprom.data, eeprom.size); if(node["type"].text() == "flash") fp->write(flash.data, flash.size); diff --git a/higan/gba/cartridge/cartridge.hpp b/higan/gba/cartridge/cartridge.hpp index 3d0cbf22..cdbd9675 100644 --- a/higan/gba/cartridge/cartridge.hpp +++ b/higan/gba/cartridge/cartridge.hpp @@ -1,11 +1,13 @@ struct Cartridge { #include "memory.hpp" + auto pathID() const -> uint { return information.pathID; } auto sha256() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } struct Information { + uint pathID = 0; string sha256; string manifest; string title; diff --git a/higan/gba/gba.hpp b/higan/gba/gba.hpp index f34b5bef..72844083 100644 --- a/higan/gba/gba.hpp +++ b/higan/gba/gba.hpp @@ -7,6 +7,8 @@ #include namespace GameBoyAdvance { + using File = Emulator::File; + enum : uint { //mode flags for bus read, write: Nonsequential = 1, //N cycle Sequential = 2, //S cycle @@ -19,13 +21,6 @@ namespace GameBoyAdvance { Signed = 256, //sign extended }; - struct File { - static const auto Read = vfs::file::mode::read; - static const auto Write = vfs::file::mode::write; - static const auto Optional = false; - static const auto Required = true; - }; - struct Thread { ~Thread() { if(thread) co_delete(thread); diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index 2fa94ffc..1c4cc5a9 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -21,22 +21,24 @@ Interface::Interface() { media.append({ID::GameBoyAdvance, "Game Boy Advance", "gba", true}); - { Device device{0, ID::Device, "Controller"}; - device.inputs.append({ 0, 0, "Up" }); - device.inputs.append({ 1, 0, "Down" }); - device.inputs.append({ 2, 0, "Left" }); - device.inputs.append({ 3, 0, "Right" }); - device.inputs.append({ 4, 0, "B" }); - device.inputs.append({ 5, 0, "A" }); - device.inputs.append({ 6, 0, "L" }); - device.inputs.append({ 7, 0, "R" }); - device.inputs.append({ 8, 0, "Select"}); - device.inputs.append({ 9, 0, "Start" }); - device.inputs.append({10, 2, "Rumble"}); - devices.append(device); + Port hardwarePort{ID::Port::Hardware, "Hardware"}; + + { Device device{ID::Device::Controls, "Controls"}; + device.inputs.append({0, "Up" }); + device.inputs.append({0, "Down" }); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right" }); + device.inputs.append({0, "B" }); + device.inputs.append({0, "A" }); + device.inputs.append({0, "L" }); + device.inputs.append({0, "R" }); + device.inputs.append({0, "Select"}); + device.inputs.append({0, "Start" }); + device.inputs.append({2, "Rumble"}); + hardwarePort.devices.append(device); } - ports.append({0, "Device", {devices[0]}}); + ports.append(move(hardwarePort)); } auto Interface::manifest() -> string { @@ -85,8 +87,8 @@ auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::load(uint id) -> void { - system.load(); +auto Interface::load(uint id) -> bool { + return system.load(); } auto Interface::save() -> void { diff --git a/higan/gba/interface/interface.hpp b/higan/gba/interface/interface.hpp index ded44020..fc2a983f 100644 --- a/higan/gba/interface/interface.hpp +++ b/higan/gba/interface/interface.hpp @@ -6,39 +6,42 @@ struct ID { GameBoyAdvance, }; - enum : uint { - Device = 1, - }; + struct Port { enum : uint { + Hardware, + };}; + + struct Device { enum : uint { + Controls, + };}; }; struct Interface : Emulator::Interface { + using Emulator::Interface::load; + Interface(); - auto manifest() -> string; - auto title() -> string; - auto videoFrequency() -> double; - auto videoColors() -> uint32; - auto videoColor(uint32 color) -> uint64; - auto audioFrequency() -> double; + auto manifest() -> string override; + auto title() -> string override; + auto videoFrequency() -> double override; + auto videoColors() -> uint32 override; + auto videoColor(uint32 color) -> uint64 override; + auto audioFrequency() -> double override; - auto loaded() -> bool; - auto load(uint id) -> void; - auto save() -> void; - auto unload() -> void; + auto loaded() -> bool override; + auto load(uint id) -> bool override; + auto save() -> void override; + auto unload() -> void override; - auto power() -> void; - auto reset() -> void; - auto run() -> void; + auto power() -> void override; + auto reset() -> void override; + auto run() -> void override; - auto serialize() -> serializer; - auto unserialize(serializer&) -> bool; + auto serialize() -> serializer override; + auto unserialize(serializer&) -> bool override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; auto set(const string& name, const any& value) -> bool override; - -private: - vector devices; }; struct Settings { diff --git a/higan/gba/system/system.cpp b/higan/gba/system/system.cpp index 532b98ba..8fd109a1 100644 --- a/higan/gba/system/system.cpp +++ b/higan/gba/system/system.cpp @@ -44,7 +44,7 @@ auto System::load() -> bool { } } - cartridge.load(); + if(!cartridge.load()) return false; serializeInit(); return _loaded = true; } diff --git a/higan/sfc/cartridge/cartridge.cpp b/higan/sfc/cartridge/cartridge.cpp index 8fd22ced..669d79de 100644 --- a/higan/sfc/cartridge/cartridge.cpp +++ b/higan/sfc/cartridge/cartridge.cpp @@ -28,8 +28,10 @@ auto Cartridge::title() const -> string { auto Cartridge::load() -> bool { information = Information(); has = Has(); - _sha256 = ""; - _region = Region::NTSC; + + if(auto pathID = interface->load(ID::SuperFamicom, "Super Famicom", "sfc", File::Required)) { + information.pathID = pathID(); + } else return false; if(auto fp = interface->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) { information.manifest.cartridge = fp->reads(); @@ -39,12 +41,12 @@ auto Cartridge::load() -> bool { //Game Boy if(cartridge.has.ICD2) { - _sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy() + information.sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy() } //BS Memory else if(cartridge.has.MCC && cartridge.has.BSMemorySlot) { - _sha256 = Hash::SHA256(bsmemory.memory.data(), bsmemory.memory.size()).digest(); + information.sha256 = Hash::SHA256(bsmemory.memory.data(), bsmemory.memory.size()).digest(); } //Sufami Turbo @@ -52,7 +54,7 @@ auto Cartridge::load() -> bool { Hash::SHA256 sha; sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size()); sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size()); - _sha256 = sha.digest(); + information.sha256 = sha.digest(); } //Super Famicom @@ -76,7 +78,7 @@ auto Cartridge::load() -> bool { buffer = necdsp.firmware(); sha.data(buffer.data(), buffer.size()); //finalize hash - _sha256 = sha.digest(); + information.sha256 = sha.digest(); } rom.writeProtect(true); @@ -84,35 +86,40 @@ auto Cartridge::load() -> bool { return true; } -auto Cartridge::loadGameBoy() -> void { +auto Cartridge::loadGameBoy() -> bool { #if defined(SFC_SUPERGAMEBOY) //invoked from ICD2::load() - _sha256 = GameBoy::interface->sha256(); + information.sha256 = GameBoy::interface->sha256(); information.manifest.gameBoy = GameBoy::interface->manifest(); information.title.gameBoy = GameBoy::interface->title(); - #endif loadGameBoy(BML::unserialize(information.manifest.gameBoy)); + return true; + #endif + return false; } -auto Cartridge::loadBSMemory() -> void { +auto Cartridge::loadBSMemory() -> bool { if(auto fp = interface->open(ID::BSMemory, "manifest.bml", File::Read, File::Required)) { information.manifest.bsMemory = fp->reads(); - } else return; + } else return false; loadBSMemory(BML::unserialize(information.manifest.bsMemory)); + return true; } -auto Cartridge::loadSufamiTurboA() -> void { +auto Cartridge::loadSufamiTurboA() -> bool { if(auto fp = interface->open(ID::SufamiTurboA, "manifest.bml", File::Read, File::Required)) { information.manifest.sufamiTurboA = fp->reads(); - } else return; + } else return false; loadSufamiTurboA(BML::unserialize(information.manifest.sufamiTurboA)); + return true; } -auto Cartridge::loadSufamiTurboB() -> void { +auto Cartridge::loadSufamiTurboB() -> bool { if(auto fp = interface->open(ID::SufamiTurboB, "manifest.bml", File::Read, File::Required)) { information.manifest.sufamiTurboB = fp->reads(); - } else return; + } else return false; loadSufamiTurboB(BML::unserialize(information.manifest.sufamiTurboB)); + return true; } auto Cartridge::save() -> void { diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 49c43aca..22eda2fe 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -1,8 +1,9 @@ struct Cartridge { enum class Region : uint { NTSC, PAL }; - auto sha256() const -> string { return _sha256; } - auto region() const -> Region { return _region; } + auto pathID() const -> uint { return information.pathID; } + auto sha256() const -> string { return information.sha256; } + auto region() const -> Region { return information.region; } auto manifest() const -> string; auto title() const -> string; @@ -16,6 +17,10 @@ struct Cartridge { MappedRAM ram; struct Information { + uint pathID = 0; + string sha256; + Region region = Region::NTSC; + struct Manifest { string cartridge; string gameBoy; @@ -57,10 +62,10 @@ struct Cartridge { private: //cartridge.cpp - auto loadGameBoy() -> void; - auto loadBSMemory() -> void; - auto loadSufamiTurboA() -> void; - auto loadSufamiTurboB() -> void; + auto loadGameBoy() -> bool; + auto loadBSMemory() -> bool; + auto loadSufamiTurboA() -> bool; + auto loadSufamiTurboB() -> bool; //load.cpp auto loadCartridge(Markup::Node) -> void; @@ -89,7 +94,7 @@ private: auto loadOBC1(Markup::Node) -> void; auto loadMSU1(Markup::Node) -> void; - auto loadMemory(MappedRAM&, Markup::Node, bool required, uint id = 1) -> void; + auto loadMemory(MappedRAM&, Markup::Node, bool required, maybe id = nothing) -> void; auto loadMap(Markup::Node, SuperFamicom::Memory&) -> void; auto loadMap(Markup::Node, const function&, const function&) -> void; @@ -114,10 +119,7 @@ private: auto saveSDD1(Markup::Node) -> void; auto saveOBC1(Markup::Node) -> void; - auto saveMemory(MappedRAM&, Markup::Node, uint = 1) -> void; - - string _sha256; - Region _region = Region::NTSC; + auto saveMemory(MappedRAM&, Markup::Node, maybe = nothing) -> void; friend class Interface; friend class ICD2; diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp index cc62c6e9..4efd3c74 100644 --- a/higan/sfc/cartridge/load.cpp +++ b/higan/sfc/cartridge/load.cpp @@ -1,10 +1,18 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void { information.title.cartridge = node["information/title"].text(); auto board = node["board"]; - _region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; + information.region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; - if(board["mcc"] || board["bsmemory"]) interface->load(ID::BSMemory, "BS Memory", "bs"); - if(board["sufamiturbo"]) interface->load(ID::SufamiTurboA, "Sufami Turbo", "st"); + if(board["mcc"] || board["bsmemory"]) { + if(auto pathID = interface->load(ID::BSMemory, "BS Memory", "bs")) { + bsmemory.pathID = pathID(); + } + } + if(board["sufamiturbo"]) { + if(auto pathID = interface->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { + sufamiturboA.pathID = pathID(); + } + } if(auto node = board["rom"]) loadROM(node); if(auto node = board["ram"]) loadRAM(node); @@ -35,23 +43,27 @@ auto Cartridge::loadBSMemory(Markup::Node node) -> void { information.title.bsMemory = node["information/title"].text(); bsmemory.readonly = (node["board/rom/type"].text() == "mrom"); - loadMemory(bsmemory.memory, node["board/rom"], File::Required, ID::BSMemory); + loadMemory(bsmemory.memory, node["board/rom"], File::Required, bsmemory.pathID); } auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { information.title.sufamiTurboA = node["information/title"].text(); - loadMemory(sufamiturboA.rom, node["board/rom"], File::Required, ID::SufamiTurboA); - loadMemory(sufamiturboA.ram, node["board/ram"], File::Optional, ID::SufamiTurboA); + loadMemory(sufamiturboA.rom, node["board/rom"], File::Required, sufamiturboA.pathID); + loadMemory(sufamiturboA.ram, node["board/ram"], File::Optional, sufamiturboA.pathID); - if(node["board/linkable"]) interface->load(ID::SufamiTurboB, "Sufami Turbo", "st"); + if(node["board/linkable"]) { + if(auto pathID = interface->load(ID::SufamiTurboB, "Sufami Turbo", "st")) { + sufamiturboB.pathID = pathID(); + } + } } auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { information.title.sufamiTurboB = node["information/title"].text(); - loadMemory(sufamiturboB.rom, node["board/rom"], File::Required, ID::SufamiTurboB); - loadMemory(sufamiturboB.ram, node["board/ram"], File::Optional, ID::SufamiTurboB); + loadMemory(sufamiturboB.rom, node["board/rom"], File::Required, sufamiturboB.pathID); + loadMemory(sufamiturboB.ram, node["board/ram"], File::Optional, sufamiturboB.pathID); } // @@ -302,11 +314,12 @@ auto Cartridge::loadMSU1(Markup::Node node) -> void { // -auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, uint id) -> void { +auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, maybe id) -> void { + if(!id) id = pathID(); auto name = node["name"].text(); auto size = node["size"].natural(); ram.allocate(size); - if(auto fp = interface->open(id, name, File::Read, required)) { + if(auto fp = interface->open(id(), name, File::Read, required)) { fp->read(ram.data(), ram.size()); } } diff --git a/higan/sfc/cartridge/save.cpp b/higan/sfc/cartridge/save.cpp index a61d7ff6..2c18272a 100644 --- a/higan/sfc/cartridge/save.cpp +++ b/higan/sfc/cartridge/save.cpp @@ -23,11 +23,11 @@ auto Cartridge::saveBSMemory(Markup::Node node) -> void { } auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void { - saveMemory(sufamiturboA.ram, node["board/ram"], ID::SufamiTurboA); + saveMemory(sufamiturboA.ram, node["board/ram"], sufamiturboA.pathID); } auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void { - saveMemory(sufamiturboB.ram, node["board/ram"], ID::SufamiTurboB); + saveMemory(sufamiturboB.ram, node["board/ram"], sufamiturboB.pathID); } // @@ -113,11 +113,12 @@ auto Cartridge::saveOBC1(Markup::Node node) -> void { // -auto Cartridge::saveMemory(MappedRAM& memory, Markup::Node node, uint id) -> void { +auto Cartridge::saveMemory(MappedRAM& memory, Markup::Node node, maybe id) -> void { + if(!id) id = pathID(); if(!node || node["volatile"]) return; auto name = node["name"].text(); auto size = node["size"].natural(); - if(auto fp = interface->open(id, name, File::Write)) { + if(auto fp = interface->open(id(), name, File::Write)) { fp->write(memory.data(), memory.size()); } } diff --git a/higan/sfc/controller/gamepad/gamepad.cpp b/higan/sfc/controller/gamepad/gamepad.cpp index 7d34331d..c5dd8743 100644 --- a/higan/sfc/controller/gamepad/gamepad.cpp +++ b/higan/sfc/controller/gamepad/gamepad.cpp @@ -9,7 +9,7 @@ Gamepad::Gamepad(bool port) : Controller(port) { auto Gamepad::data() -> uint2 { if(counter >= 16) return 1; - if(latched == 1) return interface->inputPoll(port, Device::Gamepad, B); + if(latched == 1) return interface->inputPoll(port, ID::Device::Gamepad, B); //note: D-pad physically prevents up+down and left+right from being pressed at the same time switch(counter++) { @@ -36,7 +36,7 @@ auto Gamepad::latch(bool data) -> void { counter = 0; if(latched == 0) { - auto id = Device::Gamepad; + auto id = ID::Device::Gamepad; b = interface->inputPoll(port, id, B); y = interface->inputPoll(port, id, Y); select = interface->inputPoll(port, id, Select); diff --git a/higan/sfc/controller/justifier/justifier.cpp b/higan/sfc/controller/justifier/justifier.cpp index fac50497..bfc9b4e8 100644 --- a/higan/sfc/controller/justifier/justifier.cpp +++ b/higan/sfc/controller/justifier/justifier.cpp @@ -1,7 +1,7 @@ Justifier::Justifier(bool port, bool chained): Controller(port), chained(chained), -device(chained == false ? Device::Justifier : Device::Justifiers) +device(!chained ? ID::Device::Justifier : ID::Device::Justifiers) { create(Controller::Enter, 21'477'272); latched = 0; diff --git a/higan/sfc/controller/mouse/mouse.cpp b/higan/sfc/controller/mouse/mouse.cpp index 30660068..f9a3f59f 100644 --- a/higan/sfc/controller/mouse/mouse.cpp +++ b/higan/sfc/controller/mouse/mouse.cpp @@ -64,10 +64,10 @@ auto Mouse::latch(bool data) -> void { latched = data; counter = 0; - x = interface->inputPoll(port, Device::Mouse, X); //-n = left, 0 = center, +n = right - y = interface->inputPoll(port, Device::Mouse, Y); //-n = up, 0 = center, +n = down - l = interface->inputPoll(port, Device::Mouse, Left); - r = interface->inputPoll(port, Device::Mouse, Right); + x = interface->inputPoll(port, ID::Device::Mouse, X); //-n = left, 0 = center, +n = right + y = interface->inputPoll(port, ID::Device::Mouse, Y); //-n = up, 0 = center, +n = down + l = interface->inputPoll(port, ID::Device::Mouse, Left); + r = interface->inputPoll(port, ID::Device::Mouse, Right); dx = x < 0; //0 = right, 1 = left dy = y < 0; //0 = down, 1 = up diff --git a/higan/sfc/controller/multitap/multitap.cpp b/higan/sfc/controller/multitap/multitap.cpp index 33125b2a..96859269 100644 --- a/higan/sfc/controller/multitap/multitap.cpp +++ b/higan/sfc/controller/multitap/multitap.cpp @@ -24,9 +24,9 @@ auto Multitap::data() -> uint2 { port2 = 3; //controller 4 } - bool data1 = interface->inputPoll(port, Device::Multitap, port1 * 12 + index); - bool data2 = interface->inputPoll(port, Device::Multitap, port2 * 12 + index); - return (data2 << 1) | (data1 << 0); + bool data1 = interface->inputPoll(port, ID::Device::Multitap, port1 * 12 + index); + bool data2 = interface->inputPoll(port, ID::Device::Multitap, port2 * 12 + index); + return data2 << 1 | data1 << 0; } auto Multitap::latch(bool data) -> void { diff --git a/higan/sfc/controller/superscope/superscope.cpp b/higan/sfc/controller/superscope/superscope.cpp index 6320061c..079fad1d 100644 --- a/higan/sfc/controller/superscope/superscope.cpp +++ b/higan/sfc/controller/superscope/superscope.cpp @@ -53,8 +53,8 @@ auto SuperScope::main() -> void { if(next < prev) { //Vcounter wrapped back to zero; update cursor coordinates for start of new frame - int nx = interface->inputPoll(port, Device::SuperScope, X); - int ny = interface->inputPoll(port, Device::SuperScope, Y); + int nx = interface->inputPoll(port, ID::Device::SuperScope, X); + int ny = interface->inputPoll(port, ID::Device::SuperScope, Y); nx += x; ny += y; x = max(-16, min(256 + 16, nx)); @@ -73,7 +73,7 @@ auto SuperScope::data() -> uint2 { if(counter == 0) { //turbo is a switch; toggle is edge sensitive - bool newturbo = interface->inputPoll(port, Device::SuperScope, Turbo); + bool newturbo = interface->inputPoll(port, ID::Device::SuperScope, Turbo); if(newturbo && !oldturbo) { turbo = !turbo; //toggle state sprite->setPixels(turbo ? Resource::Sprite::CrosshairRed : Resource::Sprite::CrosshairGreen); @@ -83,7 +83,7 @@ auto SuperScope::data() -> uint2 { //trigger is a button //if turbo is active, trigger is level sensitive; otherwise, it is edge sensitive trigger = false; - bool newtrigger = interface->inputPoll(port, Device::SuperScope, Trigger); + bool newtrigger = interface->inputPoll(port, ID::Device::SuperScope, Trigger); if(newtrigger && (turbo || !triggerlock)) { trigger = true; triggerlock = true; @@ -92,11 +92,11 @@ auto SuperScope::data() -> uint2 { } //cursor is a button; it is always level sensitive - cursor = interface->inputPoll(port, Device::SuperScope, Cursor); + cursor = interface->inputPoll(port, ID::Device::SuperScope, Cursor); //pause is a button; it is always edge sensitive pause = false; - bool newpause = interface->inputPoll(port, Device::SuperScope, Pause); + bool newpause = interface->inputPoll(port, ID::Device::SuperScope, Pause); if(newpause && !pauselock) { pause = true; pauselock = true; diff --git a/higan/sfc/coprocessor/icd2/icd2.cpp b/higan/sfc/coprocessor/icd2/icd2.cpp index 5a2a210f..021b50e7 100644 --- a/higan/sfc/coprocessor/icd2/icd2.cpp +++ b/higan/sfc/coprocessor/icd2/icd2.cpp @@ -33,14 +33,13 @@ auto ICD2::main() -> void { auto ICD2::init() -> void { } -auto ICD2::load() -> void { +auto ICD2::load() -> bool { bind = GameBoy::interface->bind; hook = GameBoy::interface->hook; GameBoy::interface->bind = this; GameBoy::interface->hook = this; - interface->load(ID::GameBoy, "Game Boy", "gb"); GameBoy::interface->load(GameBoy::ID::SuperGameBoy); - cartridge.loadGameBoy(); + return cartridge.loadGameBoy(); } auto ICD2::unload() -> void { diff --git a/higan/sfc/coprocessor/icd2/icd2.hpp b/higan/sfc/coprocessor/icd2/icd2.hpp index 5f68d5bd..8ac34a53 100644 --- a/higan/sfc/coprocessor/icd2/icd2.hpp +++ b/higan/sfc/coprocessor/icd2/icd2.hpp @@ -7,7 +7,7 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Cothread { auto main() -> void; auto init() -> void; - auto load() -> void; + auto load() -> bool; auto unload() -> void; auto power() -> void; auto reset(bool soft = false) -> void; @@ -17,7 +17,8 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Cothread { auto lcdOutput(uint2 color) -> void override; auto joypWrite(bool p15, bool p14) -> void override; - auto load(uint id, string name, string type, bool required) -> void override; + auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; + auto load(uint id, string name, string type, bool required) -> maybe override; auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; auto audioSample(const double* samples, uint channels) -> void override; diff --git a/higan/sfc/coprocessor/icd2/interface.cpp b/higan/sfc/coprocessor/icd2/interface.cpp index d4a1c67e..485fefe6 100644 --- a/higan/sfc/coprocessor/icd2/interface.cpp +++ b/higan/sfc/coprocessor/icd2/interface.cpp @@ -85,39 +85,17 @@ auto ICD2::joypWrite(bool p15, bool p14) -> void { packetLock = true; } -auto ICD2::load(uint id, string name, string type, bool required) -> void { +auto ICD2::open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file { + //redirect system folder to cartridge folder: + //expects "GameBoy.sys"; but this would be "Super Famicom.sys"; redirect to "Super Game Boy.sfc/" + if(id == ID::System) id = cartridge.pathID(); + return interface->open(id, name, mode, required); } -/* -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::load(uint id, string name, string type, bool required) -> maybe { + return interface->load(id, name, type, 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/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 5f828a77..c880fd2b 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -25,105 +25,106 @@ Interface::Interface() { media.append({ID::SuperFamicom, "BS Memory", "bs", false}); media.append({ID::SuperFamicom, "Sufami Turbo", "st", false}); - { Device device{0, ID::ControllerPort1 | ID::ControllerPort2 | ID::ExpansionPort, "None"}; - devices.append(device); + Port controllerPort1{ID::Port::Controller1, "Controller Port 1"}; + Port controllerPort2{ID::Port::Controller2, "Controller Port 2"}; + Port expansionPort{ID::Port::Expansion, "Expansion Port"}; + + { Device device{ID::Device::None, "None"}; + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); + expansionPort.devices.append(device); } - { Device device{1, ID::ControllerPort1 | ID::ControllerPort2, "Gamepad"}; - device.inputs.append({ 0, 0, "Up" }); - device.inputs.append({ 1, 0, "Down" }); - device.inputs.append({ 2, 0, "Left" }); - device.inputs.append({ 3, 0, "Right" }); - device.inputs.append({ 4, 0, "B" }); - device.inputs.append({ 5, 0, "A" }); - device.inputs.append({ 6, 0, "Y" }); - device.inputs.append({ 7, 0, "X" }); - device.inputs.append({ 8, 0, "L" }); - device.inputs.append({ 9, 0, "R" }); - device.inputs.append({10, 0, "Select"}); - device.inputs.append({11, 0, "Start" }); - devices.append(device); + { Device device{ID::Device::Gamepad, "Gamepad"}; + device.inputs.append({0, "Up" }); + device.inputs.append({0, "Down" }); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right" }); + device.inputs.append({0, "B" }); + device.inputs.append({0, "A" }); + device.inputs.append({0, "Y" }); + device.inputs.append({0, "X" }); + device.inputs.append({0, "L" }); + device.inputs.append({0, "R" }); + device.inputs.append({0, "Select"}); + device.inputs.append({0, "Start" }); + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); } - { Device device{2, ID::ControllerPort1 | ID::ControllerPort2, "Multitap"}; + { Device device{ID::Device::Multitap, "Multitap"}; for(uint p = 1, n = 0; p <= 4; p++, n += 12) { - device.inputs.append({n + 0, 0, {"Port ", p, " - ", "Up" }}); - device.inputs.append({n + 1, 0, {"Port ", p, " - ", "Down" }}); - device.inputs.append({n + 2, 0, {"Port ", p, " - ", "Left" }}); - device.inputs.append({n + 3, 0, {"Port ", p, " - ", "Right" }}); - device.inputs.append({n + 4, 0, {"Port ", p, " - ", "B" }}); - device.inputs.append({n + 5, 0, {"Port ", p, " - ", "A" }}); - device.inputs.append({n + 6, 0, {"Port ", p, " - ", "Y" }}); - device.inputs.append({n + 7, 0, {"Port ", p, " - ", "X" }}); - device.inputs.append({n + 8, 0, {"Port ", p, " - ", "L" }}); - device.inputs.append({n + 9, 0, {"Port ", p, " - ", "R" }}); - device.inputs.append({n + 10, 0, {"Port ", p, " - ", "Select"}}); - device.inputs.append({n + 11, 0, {"Port ", p, " - ", "Start" }}); + device.inputs.append({0, {"Port ", p, " - ", "Up" }}); + device.inputs.append({0, {"Port ", p, " - ", "Down" }}); + device.inputs.append({0, {"Port ", p, " - ", "Left" }}); + device.inputs.append({0, {"Port ", p, " - ", "Right" }}); + device.inputs.append({0, {"Port ", p, " - ", "B" }}); + device.inputs.append({0, {"Port ", p, " - ", "A" }}); + device.inputs.append({0, {"Port ", p, " - ", "Y" }}); + device.inputs.append({0, {"Port ", p, " - ", "X" }}); + device.inputs.append({0, {"Port ", p, " - ", "L" }}); + device.inputs.append({0, {"Port ", p, " - ", "R" }}); + device.inputs.append({0, {"Port ", p, " - ", "Select"}}); + device.inputs.append({0, {"Port ", p, " - ", "Start" }}); } - devices.append(device); + //controllerPort1.devices.append(device); //not used by any commercial software (only homebrew) + controllerPort2.devices.append(device); } - { Device device{3, ID::ControllerPort1 | ID::ControllerPort2, "Mouse"}; - device.inputs.append({0, 1, "X-axis"}); - device.inputs.append({1, 1, "Y-axis"}); - device.inputs.append({2, 0, "Left" }); - device.inputs.append({3, 0, "Right" }); - devices.append(device); + { Device device{ID::Device::Mouse, "Mouse"}; + device.inputs.append({1, "X-axis"}); + device.inputs.append({1, "Y-axis"}); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right" }); + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); } - { Device device{4, ID::ControllerPort2, "Super Scope"}; - device.inputs.append({0, 1, "X-axis" }); - device.inputs.append({1, 1, "Y-axis" }); - device.inputs.append({2, 0, "Trigger"}); - device.inputs.append({3, 0, "Cursor" }); - device.inputs.append({4, 0, "Turbo" }); - device.inputs.append({5, 0, "Pause" }); - devices.append(device); + { Device device{ID::Device::SuperScope, "Super Scope"}; + device.inputs.append({1, "X-axis" }); + device.inputs.append({1, "Y-axis" }); + device.inputs.append({0, "Trigger"}); + device.inputs.append({0, "Cursor" }); + device.inputs.append({0, "Turbo" }); + device.inputs.append({0, "Pause" }); + controllerPort2.devices.append(device); } - { Device device{5, ID::ControllerPort2, "Justifier"}; - device.inputs.append({0, 1, "X-axis" }); - device.inputs.append({1, 1, "Y-axis" }); - device.inputs.append({2, 0, "Trigger"}); - device.inputs.append({3, 0, "Start" }); - devices.append(device); + { Device device{ID::Device::Justifier, "Justifier"}; + device.inputs.append({1, "X-axis" }); + device.inputs.append({1, "Y-axis" }); + device.inputs.append({0, "Trigger"}); + device.inputs.append({0, "Start" }); + controllerPort2.devices.append(device); } - { Device device{6, ID::ControllerPort2, "Justifiers"}; - device.inputs.append({0, 1, "Port 1 - X-axis" }); - device.inputs.append({1, 1, "Port 1 - Y-axis" }); - device.inputs.append({2, 0, "Port 1 - Trigger"}); - device.inputs.append({3, 0, "Port 1 - Start" }); - device.inputs.append({4, 1, "Port 2 - X-axis" }); - device.inputs.append({5, 1, "Port 2 - Y-axis" }); - device.inputs.append({6, 0, "Port 2 - Trigger"}); - device.inputs.append({7, 0, "Port 2 - Start" }); - devices.append(device); + { Device device{ID::Device::Justifiers, "Justifiers"}; + device.inputs.append({1, "Port 1 - X-axis" }); + device.inputs.append({1, "Port 1 - Y-axis" }); + device.inputs.append({0, "Port 1 - Trigger"}); + device.inputs.append({0, "Port 1 - Start" }); + device.inputs.append({1, "Port 2 - X-axis" }); + device.inputs.append({1, "Port 2 - Y-axis" }); + device.inputs.append({0, "Port 2 - Trigger"}); + device.inputs.append({0, "Port 2 - Start" }); + controllerPort2.devices.append(device); } - { Device device{7, ID::ExpansionPort, "Satellaview"}; - devices.append(device); + { Device device{ID::Device::Satellaview, "Satellaview"}; + expansionPort.devices.append(device); } - { Device device{8, ID::ExpansionPort, "Super Disc"}; - devices.append(device); + { Device device{ID::Device::SuperDisc, "Super Disc"}; + expansionPort.devices.append(device); } - { Device device{9, ID::ExpansionPort, "21fx"}; - devices.append(device); + { Device device{ID::Device::S21FX, "21fx"}; + expansionPort.devices.append(device); } - ports.append({0, "Controller Port 1"}); - ports.append({1, "Controller Port 2"}); - ports.append({2, "Expansion Port"}); - - for(auto& device : devices) { - for(auto& port : ports) { - if(device.portmask & (1 << port.id)) { - port.devices.append(device); - } - } - } + ports.append(move(controllerPort1)); + ports.append(move(controllerPort2)); + ports.append(move(expansionPort)); } auto Interface::manifest() -> string { @@ -183,11 +184,12 @@ auto Interface::sha256() -> string { return cartridge.sha256(); } -auto Interface::load(uint id) -> void { - if(id == ID::SuperFamicom) system.load(); - if(id == ID::BSMemory) cartridge.loadBSMemory(); - if(id == ID::SufamiTurboA) cartridge.loadSufamiTurboA(); - if(id == ID::SufamiTurboB) cartridge.loadSufamiTurboB(); +auto Interface::load(uint id) -> bool { + if(id == ID::SuperFamicom) return system.load(); + if(id == ID::BSMemory) return cartridge.loadBSMemory(); + if(id == ID::SufamiTurboA) return cartridge.loadSufamiTurboA(); + if(id == ID::SufamiTurboB) return cartridge.loadSufamiTurboB(); + return false; } auto Interface::save() -> void { diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index 6c899a4c..ec93d159 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -8,22 +8,27 @@ struct ID { BSMemory, SufamiTurboA, SufamiTurboB, - - //deprecated - SuperGameBoyManifest, - SuperGameBoyBootROM, - - GameBoyManifest, - GameBoyROM, - GameBoyRAM, }; - enum : uint { - //device ports (bitmask) - ControllerPort1 = 1, - ControllerPort2 = 2, - ExpansionPort = 4, - }; + struct Device { enum : uint { + None, + Gamepad, + Multitap, + Mouse, + SuperScope, + Justifier, + Justifiers, + + Satellaview, + SuperDisc, + S21FX, + };}; + + struct Port { enum : uint { + Controller1, + Controller2, + Expansion, + };}; }; struct Interface : Emulator::Interface { @@ -31,37 +36,35 @@ struct Interface : Emulator::Interface { Interface(); - auto manifest() -> string; - auto title() -> string; - auto videoFrequency() -> double; - auto videoColors() -> uint32; - auto videoColor(uint32 color) -> uint64; - auto audioFrequency() -> double; + auto manifest() -> string override; + auto title() -> string override; + auto videoFrequency() -> double override; + auto videoColors() -> uint32 override; + auto videoColor(uint32 color) -> uint64 override; + auto audioFrequency() -> double override; - auto loaded() -> bool; - auto sha256() -> string; - auto load(uint id) -> void; - auto save() -> void; - auto unload() -> void; + auto loaded() -> bool override; + auto sha256() -> string override; + auto load(uint id) -> bool override; + auto save() -> void override; + auto unload() -> void override; - auto connect(uint port, uint device) -> void; - auto power() -> void; - auto reset() -> void; - auto run() -> void; + auto connect(uint port, uint device) -> void override; + auto power() -> void override; + auto reset() -> void override; + auto run() -> void override; - auto rtc() -> bool; - auto rtcsync() -> void; + auto rtc() -> bool override; + auto rtcsync() -> void override; - auto serialize() -> serializer; - auto unserialize(serializer&) -> bool; + auto serialize() -> serializer override; + auto unserialize(serializer&) -> bool override; - auto cheatSet(const lstring&) -> void; + auto cheatSet(const lstring&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; auto set(const string& name, const any& value) -> bool override; - - vector devices; }; struct Settings { diff --git a/higan/sfc/ppu/background/background.cpp b/higan/sfc/ppu/background/background.cpp index 6003ca36..2ed66795 100644 --- a/higan/sfc/ppu/background/background.cpp +++ b/higan/sfc/ppu/background/background.cpp @@ -116,11 +116,11 @@ auto PPU::Background::getTile() -> void { uint tx = hoffset >> tileWidth; uint ty = voffset >> tileHeight; - uint15 offset = ((ty & 0x1f) << 5) + (tx & 0x1f); + uint16 offset = ((ty & 0x1f) << 5) + (tx & 0x1f); if(tx & 0x20) offset += screenX; if(ty & 0x20) offset += screenY; - uint15 address = r.screenAddress + offset; + uint16 address = r.screenAddress + offset; tile = ppu.vram[address]; bool mirrorY = tile & 0x8000; bool mirrorX = tile & 0x4000; @@ -270,6 +270,6 @@ auto PPU::Background::getTile(uint x, uint y) -> uint { if(x & 0x20) offset += screenX; if(y & 0x20) offset += screenY; - uint15 address = r.screenAddress + offset; + uint16 address = r.screenAddress + offset; return ppu.vram[address]; } diff --git a/higan/sfc/ppu/memory.cpp b/higan/sfc/ppu/memory.cpp index 651f3250..d47dbff9 100644 --- a/higan/sfc/ppu/memory.cpp +++ b/higan/sfc/ppu/memory.cpp @@ -9,7 +9,7 @@ auto PPU::getVramAddress() -> uint16 { unreachable; } -auto PPU::vramRead(bool chip, uint15 addr) -> uint8 { +auto PPU::vramRead(bool chip, uint addr) -> uint8 { uint8 data = 0x00; if(r.displayDisable || vcounter() >= vdisp()) { data = vram[addr].byte(chip); @@ -18,7 +18,7 @@ auto PPU::vramRead(bool chip, uint15 addr) -> uint8 { return data; } -auto PPU::vramWrite(bool chip, uint15 addr, uint8 data) -> void { +auto PPU::vramWrite(bool chip, uint addr, uint8 data) -> void { if(r.displayDisable || vcounter() >= vdisp()) { vram[addr].byte(chip) = data; debugger.vramWrite(addr << 1 | chip, data); diff --git a/higan/sfc/ppu/mmio.cpp b/higan/sfc/ppu/mmio.cpp index 81197088..35dff131 100644 --- a/higan/sfc/ppu/mmio.cpp +++ b/higan/sfc/ppu/mmio.cpp @@ -162,7 +162,7 @@ auto PPU::write(uint24 addr, uint8 data) -> void { //OBSEL case 0x2101: { - obj.r.tiledataAddress = data.bits(0,1) << 13; + obj.r.tiledataAddress = data.bits(0,2) << 13; obj.r.nameSelect = data.bits(3,4); obj.r.baseSize = data.bits(5,7); return; @@ -226,42 +226,42 @@ auto PPU::write(uint24 addr, uint8 data) -> void { //BG1SC case 0x2107: { bg1.r.screenSize = data.bits(0,1); - bg1.r.screenAddress = data.bits(2,6) << 10; + bg1.r.screenAddress = data.bits(2,7) << 10; return; } //BG2SC case 0x2108: { bg2.r.screenSize = data.bits(0,1); - bg2.r.screenAddress = data.bits(2,6) << 10; + bg2.r.screenAddress = data.bits(2,7) << 10; return; } //BG3SC case 0x2109: { bg3.r.screenSize = data.bits(0,1); - bg3.r.screenAddress = data.bits(2,6) << 10; + bg3.r.screenAddress = data.bits(2,7) << 10; return; } //BG4SC case 0x210a: { bg4.r.screenSize = data.bits(0,1); - bg4.r.screenAddress = data.bits(2,6) << 10; + bg4.r.screenAddress = data.bits(2,7) << 10; return; } //BG12NBA case 0x210b: { - bg1.r.tiledataAddress = data.bits(0,2) << 12; - bg2.r.tiledataAddress = data.bits(4,6) << 12; + bg1.r.tiledataAddress = data.bits(0,3) << 12; + bg2.r.tiledataAddress = data.bits(4,7) << 12; return; } //BG34NBA case 0x210c: { - bg3.r.tiledataAddress = data.bits(0,2) << 12; - bg4.r.tiledataAddress = data.bits(4,6) << 12; + bg3.r.tiledataAddress = data.bits(0,3) << 12; + bg4.r.tiledataAddress = data.bits(4,7) << 12; return; } diff --git a/higan/sfc/ppu/ppu.cpp b/higan/sfc/ppu/ppu.cpp index cc9b424f..c898883c 100644 --- a/higan/sfc/ppu/ppu.cpp +++ b/higan/sfc/ppu/ppu.cpp @@ -88,7 +88,7 @@ auto PPU::addClocks(uint clocks) -> void { } auto PPU::power() -> void { - for(auto& n : vram) n = random(0x0000); + for(auto& n : vram.data) n = random(0x0000); for(auto& n : oam) n = random(0x00); for(auto& n : cgram) n = random(0x00); } diff --git a/higan/sfc/ppu/ppu.hpp b/higan/sfc/ppu/ppu.hpp index 861e5f69..0d2a0c73 100644 --- a/higan/sfc/ppu/ppu.hpp +++ b/higan/sfc/ppu/ppu.hpp @@ -18,8 +18,8 @@ struct PPU : Thread, PPUcounter { //memory.cpp alwaysinline auto getVramAddress() -> uint16; - alwaysinline auto vramRead(bool chip, uint15 addr) -> uint8; - alwaysinline auto vramWrite(bool chip, uint15 addr, uint8 data) -> void; + alwaysinline auto vramRead(bool chip, uint addr) -> uint8; + alwaysinline auto vramWrite(bool chip, uint addr, uint8 data) -> void; alwaysinline auto oamRead(uint addr) -> uint8; alwaysinline auto oamWrite(uint addr, uint8 data) -> void; alwaysinline auto cgramRead(uint addr) -> uint8; @@ -32,7 +32,11 @@ struct PPU : Thread, PPUcounter { auto updateVideoMode() -> void; privileged: - uint16 vram[32 * 1024]; + struct VRAM { + auto& operator[](uint offset) { return data[offset & size - 1]; } + uint16 data[64 * 1024]; + uint size = 0x8000; + } vram; uint8 oam[544]; uint8 cgram[512]; diff --git a/higan/sfc/ppu/serialization.cpp b/higan/sfc/ppu/serialization.cpp index 2e43ee14..88efeab4 100644 --- a/higan/sfc/ppu/serialization.cpp +++ b/higan/sfc/ppu/serialization.cpp @@ -14,7 +14,8 @@ auto PPU::serialize(serializer& s) -> void { Thread::serialize(s); PPUcounter::serialize(s); - s.array(vram); + s.integer(vram.size); + s.array(vram.data, vram.size); s.array(oam); s.array(cgram); diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index fba573fc..247d9d17 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -16,12 +16,7 @@ #endif namespace SuperFamicom { - struct File { - static const auto Read = vfs::file::mode::read; - static const auto Write = vfs::file::mode::write; - static const auto Optional = false; - static const auto Required = true; - }; + using File = Emulator::File; struct Thread { virtual ~Thread() { diff --git a/higan/sfc/slot/bsmemory/bsmemory.hpp b/higan/sfc/slot/bsmemory/bsmemory.hpp index d079dce2..6c3abd2a 100644 --- a/higan/sfc/slot/bsmemory/bsmemory.hpp +++ b/higan/sfc/slot/bsmemory/bsmemory.hpp @@ -9,6 +9,7 @@ struct BSMemory : Memory { auto read(uint24 addr, uint8) -> uint8; auto write(uint24 addr, uint8 data) -> void; + uint pathID = 0; MappedRAM memory; bool readonly; diff --git a/higan/sfc/slot/sufamiturbo/sufamiturbo.hpp b/higan/sfc/slot/sufamiturbo/sufamiturbo.hpp index cb9f4450..11fbfc22 100644 --- a/higan/sfc/slot/sufamiturbo/sufamiturbo.hpp +++ b/higan/sfc/slot/sufamiturbo/sufamiturbo.hpp @@ -3,6 +3,7 @@ struct SufamiTurboCartridge { auto unload() -> void; auto serialize(serializer&) -> void; + uint pathID = 0; MappedRAM rom; MappedRAM ram; }; diff --git a/higan/sfc/system/peripherals.cpp b/higan/sfc/system/peripherals.cpp index c20f4b69..2280edcb 100644 --- a/higan/sfc/system/peripherals.cpp +++ b/higan/sfc/system/peripherals.cpp @@ -10,51 +10,51 @@ auto Peripherals::unload() -> void { } auto Peripherals::reset() -> void { - connect(0, settings.controllerPort1); - connect(1, settings.controllerPort2); - connect(2, settings.expansionPort); + connect(ID::Port::Controller1, settings.controllerPort1); + connect(ID::Port::Controller2, settings.controllerPort2); + connect(ID::Port::Expansion, settings.expansionPort); } -auto Peripherals::connect(uint port, uint id) -> void { - if(port == Port::Controller1) { - settings.controllerPort1 = id; +auto Peripherals::connect(uint port, uint device) -> void { + if(port == ID::Port::Controller1) { + settings.controllerPort1 = device; if(!system.loaded()) return; delete controllerPort1; - switch(id) { default: - case Device::None: controllerPort1 = new Controller(0); break; - case Device::Gamepad: controllerPort1 = new Gamepad(0); break; - case Device::Multitap: controllerPort1 = new Multitap(0); break; - case Device::Mouse: controllerPort1 = new Mouse(0); break; + switch(device) { default: + case ID::Device::None: controllerPort1 = new Controller(0); break; + case ID::Device::Gamepad: controllerPort1 = new Gamepad(0); break; + case ID::Device::Multitap: controllerPort1 = new Multitap(0); break; + case ID::Device::Mouse: controllerPort1 = new Mouse(0); break; } } - if(port == Port::Controller2) { - settings.controllerPort2 = id; + if(port == ID::Port::Controller2) { + settings.controllerPort2 = device; if(!system.loaded()) return; delete controllerPort2; - switch(id) { default: - case Device::None: controllerPort2 = new Controller(1); break; - case Device::Gamepad: controllerPort2 = new Gamepad(1); break; - case Device::Multitap: controllerPort2 = new Multitap(1); break; - case Device::Mouse: controllerPort2 = new Mouse(1); break; - case Device::SuperScope: controllerPort2 = new SuperScope(1); break; - case Device::Justifier: controllerPort2 = new Justifier(1, false); break; - case Device::Justifiers: controllerPort2 = new Justifier(1, true); break; + switch(device) { default: + case ID::Device::None: controllerPort2 = new Controller(1); break; + case ID::Device::Gamepad: controllerPort2 = new Gamepad(1); break; + case ID::Device::Multitap: controllerPort2 = new Multitap(1); break; + case ID::Device::Mouse: controllerPort2 = new Mouse(1); break; + case ID::Device::SuperScope: controllerPort2 = new SuperScope(1); break; + case ID::Device::Justifier: controllerPort2 = new Justifier(1, false); break; + case ID::Device::Justifiers: controllerPort2 = new Justifier(1, true); break; } } - if(port == Port::Expansion) { - settings.expansionPort = id; + if(port == ID::Port::Expansion) { + settings.expansionPort = device; if(!system.loaded()) return; delete expansionPort; - switch(id) { default: - case Device::None: expansionPort = new Expansion; break; - case Device::Satellaview: expansionPort = new Satellaview; break; - case Device::SuperDisc: expansionPort = new SuperDisc; break; - case Device::S21FX: expansionPort = new S21FX; break; + switch(device) { default: + case ID::Device::None: expansionPort = new Expansion; break; + case ID::Device::Satellaview: expansionPort = new Satellaview; break; + case ID::Device::SuperDisc: expansionPort = new SuperDisc; break; + case ID::Device::S21FX: expansionPort = new S21FX; break; } } diff --git a/higan/sfc/system/peripherals.hpp b/higan/sfc/system/peripherals.hpp index bf08cc85..358b71b0 100644 --- a/higan/sfc/system/peripherals.hpp +++ b/higan/sfc/system/peripherals.hpp @@ -1,30 +1,7 @@ -struct Port { enum : uint { - Controller1, - Controller2, - Expansion, -};}; - -struct Device { enum : uint { - None, - - //controller port peripherals - Gamepad, - Multitap, - Mouse, - SuperScope, - Justifier, - Justifiers, - - //expansion port peripherals - Satellaview, - SuperDisc, - S21FX, -};}; - struct Peripherals { auto unload() -> void; auto reset() -> void; - auto connect(uint port, uint id) -> void; + auto connect(uint port, uint device) -> void; Controller* controllerPort1 = nullptr; Controller* controllerPort2 = nullptr; diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index 476ff7c1..06cf2542 100644 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -66,7 +66,7 @@ auto System::load() -> bool { } else return false; } - cartridge.load(); + if(!cartridge.load()) return false; _region = cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL; _cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370; _apuFrequency = 24'606'720; diff --git a/higan/target-loki/GNUmakefile b/higan/target-loki/GNUmakefile deleted file mode 100644 index 97b06bfb..00000000 --- a/higan/target-loki/GNUmakefile +++ /dev/null @@ -1,71 +0,0 @@ -name := loki -flags += -DDEBUGGER - -include sfc/GNUmakefile -include processor/GNUmakefile - -ui_objects := ui-loki ui-program -ui_objects += ui-terminal ui-presentation -ui_objects += ruby hiro -ui_objects += $(if $(call streq,$(platform),windows),ui-resource) - -# platform -ifeq ($(platform),windows) - ruby += video.gdi audio.directsound input.windows -else ifeq ($(platform),macosx) - ruby += video.cgl audio.openal input.quartz -else ifeq ($(platform),linux) - ruby += video.xshm audio.openal input.sdl -else ifeq ($(platform),bsd) - ruby += video.xshm audio.oss input.sdl -endif - -# ruby -include ../ruby/GNUmakefile -link += $(rubylink) - -# hiro -include ../hiro/GNUmakefile -link += $(hirolink) - -# rules -objects := $(ui_objects) $(objects) -objects := $(patsubst %,obj/%.o,$(objects)) - -obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/) - $(compiler) $(rubyflags) -c $< -o $@ - -obj/hiro.o: ../hiro/hiro.cpp $(call rwildcard,../hiro/) - $(compiler) $(hiroflags) -c $< -o $@ - -obj/ui-loki.o: $(ui)/loki.cpp $(call rwildcard,$(ui)/) -obj/ui-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/) -obj/ui-terminal.o: $(ui)/terminal/terminal.cpp $(call rwildcard,$(ui)/) -obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/) - -obj/ui-resource.o: - windres data/resource.rc obj/ui-resource.o - -# targets -build: $(objects) - $(call unique,$(compiler) -o out/$(name) $(objects) $(link)) - -install: -ifeq ($(shell id -un),root) - $(error "make install should not be run as root") -else ifneq ($(filter $(platform),linux bsd),) - mkdir -p $(prefix)/bin/ - mkdir -p $(prefix)/share/icons/ - mkdir -p $(prefix)/share/$(name)/ - cp out/$(name) $(prefix)/bin/$(name) - cp data/higan.png $(prefix)/share/icons/$(name).png - cp -R profile/* $(prefix)/share/$(name)/ -endif - -uninstall: -ifeq ($(shell id -un),root) - $(error "make uninstall should not be run as root") -else ifneq ($(filter $(platform),linux bsd),) - if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi - if [ -f $(prefix)/share/icons/$(name).png ]; then rm $(prefix)/share/icons/$(name).png; fi -endif diff --git a/higan/target-loki/loki.cpp b/higan/target-loki/loki.cpp deleted file mode 100644 index f2762555..00000000 --- a/higan/target-loki/loki.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "loki.hpp" -unique_pointer