diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index f82705a5..74c38fff 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.04"; + static const string Version = "103.05"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/fc/controller/controller.cpp b/higan/fc/controller/controller.cpp index 836861e6..05b561f9 100644 --- a/higan/fc/controller/controller.cpp +++ b/higan/fc/controller/controller.cpp @@ -2,9 +2,11 @@ namespace Famicom { +ControllerPort controllerPort1; +ControllerPort controllerPort2; #include "gamepad/gamepad.cpp" -Controller::Controller(bool port) : port(port) { +Controller::Controller(uint port) : port(port) { if(!handle()) create(Controller::Enter, 1); } @@ -15,8 +17,8 @@ Controller::~Controller() { auto Controller::Enter() -> void { while(true) { scheduler.synchronize(); - if(peripherals.controllerPort1->active()) peripherals.controllerPort1->main(); - if(peripherals.controllerPort2->active()) peripherals.controllerPort2->main(); + if(controllerPort1.device->active()) controllerPort1.device->main(); + if(controllerPort2.device->active()) controllerPort2.device->main(); } } @@ -25,4 +27,32 @@ auto Controller::main() -> void { synchronize(cpu); } +// + +auto ControllerPort::connect(uint deviceID) -> void { + if(!system.loaded()) return; + delete device; + + switch(deviceID) { default: + case ID::Device::None: device = new Controller(port); break; + case ID::Device::Gamepad: device = new Gamepad(port); break; + } + + cpu.peripherals.reset(); + if(auto device = controllerPort1.device) cpu.peripherals.append(device); + if(auto device = controllerPort2.device) cpu.peripherals.append(device); +} + +auto ControllerPort::power(uint port) -> void { + this->port = port; +} + +auto ControllerPort::unload() -> void { + delete device; + device = nullptr; +} + +auto ControllerPort::serialize(serializer& s) -> void { +} + } diff --git a/higan/fc/controller/controller.hpp b/higan/fc/controller/controller.hpp index 4515a6a3..7bbd8435 100644 --- a/higan/fc/controller/controller.hpp +++ b/higan/fc/controller/controller.hpp @@ -17,9 +17,7 @@ // 7: gnd struct Controller : Thread { - enum : bool { Port1 = 0, Port2 = 1 }; - - Controller(bool port); + Controller(uint port); virtual ~Controller(); static auto Enter() -> void; @@ -27,7 +25,21 @@ struct Controller : Thread { virtual auto data() -> uint3 { return 0; } virtual auto latch(bool data) -> void {} - const bool port; + const uint port; }; +struct ControllerPort { + auto connect(uint deviceID) -> void; + + auto power(uint port) -> void; + auto unload() -> void; + auto serialize(serializer&) -> void; + + uint port; + Controller* device = nullptr; +}; + +extern ControllerPort controllerPort1; +extern ControllerPort controllerPort2; + #include "gamepad/gamepad.hpp" diff --git a/higan/fc/controller/gamepad/gamepad.cpp b/higan/fc/controller/gamepad/gamepad.cpp index c7c925b9..911cfae3 100644 --- a/higan/fc/controller/gamepad/gamepad.cpp +++ b/higan/fc/controller/gamepad/gamepad.cpp @@ -1,4 +1,4 @@ -Gamepad::Gamepad(bool port) : Controller(port) { +Gamepad::Gamepad(uint port) : Controller(port) { } auto Gamepad::data() -> uint3 { diff --git a/higan/fc/controller/gamepad/gamepad.hpp b/higan/fc/controller/gamepad/gamepad.hpp index 23883b5c..7d0ffc4f 100644 --- a/higan/fc/controller/gamepad/gamepad.hpp +++ b/higan/fc/controller/gamepad/gamepad.hpp @@ -3,7 +3,7 @@ struct Gamepad : Controller { Up, Down, Left, Right, B, A, Select, Start, }; - Gamepad(bool port); + Gamepad(uint port); auto data() -> uint3; auto latch(bool data) -> void; diff --git a/higan/fc/cpu/memory.cpp b/higan/fc/cpu/memory.cpp index d1746020..7cc51d54 100644 --- a/higan/fc/cpu/memory.cpp +++ b/higan/fc/cpu/memory.cpp @@ -10,12 +10,12 @@ auto CPU::readIO(uint16 addr) -> uint8 { switch(addr) { case 0x4016: { - auto data = Famicom::peripherals.controllerPort1->data(); + auto data = controllerPort1.device->data(); return (mdr() & 0xc0) | data.bit(2) << 4 | data.bit(1) << 3 | data.bit(0) << 0; } case 0x4017: { - auto data = Famicom::peripherals.controllerPort2->data(); + auto data = controllerPort2.device->data(); return (mdr() & 0xc0) | data.bit(2) << 4 | data.bit(1) << 3 | data.bit(0) << 0; } @@ -34,8 +34,8 @@ auto CPU::writeIO(uint16 addr, uint8 data) -> void { } case 0x4016: { - Famicom::peripherals.controllerPort1->latch(data.bit(0)); - Famicom::peripherals.controllerPort2->latch(data.bit(0)); + controllerPort1.device->latch(data.bit(0)); + controllerPort2.device->latch(data.bit(0)); return; } diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index b3a9bbf8..5aca4e9a 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -132,7 +132,8 @@ auto Interface::unload() -> void { } auto Interface::connect(uint port, uint device) -> void { - peripherals.connect(port, device); + if(port == ID::Port::Controller1) controllerPort1.connect(settings.controllerPort1 = device); + if(port == ID::Port::Controller2) controllerPort2.connect(settings.controllerPort2 = device); } auto Interface::power() -> void { diff --git a/higan/fc/system/peripherals.cpp b/higan/fc/system/peripherals.cpp deleted file mode 100644 index 35aab590..00000000 --- a/higan/fc/system/peripherals.cpp +++ /dev/null @@ -1,46 +0,0 @@ -Peripherals peripherals; - -auto Peripherals::unload() -> void { - delete controllerPort1; - delete controllerPort2; - controllerPort1 = nullptr; - controllerPort2 = nullptr; -} - -auto Peripherals::reset() -> void { - connect(ID::Port::Controller1, settings.controllerPort1); - connect(ID::Port::Controller2, settings.controllerPort2); -} - -auto Peripherals::connect(uint port, uint device) -> void { - if(port == ID::Port::Controller1) { - settings.controllerPort1 = device; - if(!system.loaded()) return; - - delete controllerPort1; - switch(device) { default: - case ID::Device::None: controllerPort1 = new Controller(0); break; - case ID::Device::Gamepad: controllerPort1 = new Gamepad(0); break; - } - } - - if(port == ID::Port::Controller2) { - settings.controllerPort2 = device; - if(!system.loaded()) return; - - delete controllerPort2; - switch(device) { default: - case ID::Device::None: controllerPort2 = new Controller(1); break; - case ID::Device::Gamepad: controllerPort2 = new Gamepad(1); break; - } - } - - if(port == ID::Port::Expansion) { - settings.expansionPort = device; - if(!system.loaded()) return; - } - - cpu.peripherals.reset(); - cpu.peripherals.append(controllerPort1); - cpu.peripherals.append(controllerPort2); -} diff --git a/higan/fc/system/serialization.cpp b/higan/fc/system/serialization.cpp index ddfe098d..0c11bc0c 100644 --- a/higan/fc/system/serialization.cpp +++ b/higan/fc/system/serialization.cpp @@ -45,6 +45,8 @@ auto System::serializeAll(serializer& s) -> void { cpu.serialize(s); apu.serialize(s); ppu.serialize(s); + controllerPort1.serialize(s); + controllerPort2.serialize(s); } auto System::serializeInit() -> void { diff --git a/higan/fc/system/system.cpp b/higan/fc/system/system.cpp index 18350906..84332a6b 100644 --- a/higan/fc/system/system.cpp +++ b/higan/fc/system/system.cpp @@ -2,7 +2,6 @@ namespace Famicom { -#include "peripherals.cpp" #include "video.cpp" #include "serialization.cpp" System system; @@ -56,7 +55,9 @@ auto System::save() -> void { auto System::unload() -> void { if(!loaded()) return; - peripherals.unload(); + cpu.peripherals.reset(); + controllerPort1.unload(); + controllerPort2.unload(); cartridge.unload(); information.loaded = false; } @@ -76,7 +77,12 @@ auto System::power() -> void { apu.power(); ppu.power(); scheduler.primary(cpu); - peripherals.reset(); + + controllerPort1.power(ID::Port::Controller1); + controllerPort2.power(ID::Port::Controller2); + + controllerPort1.connect(settings.controllerPort1); + controllerPort2.connect(settings.controllerPort2); } auto System::init() -> void { diff --git a/higan/fc/system/system.hpp b/higan/fc/system/system.hpp index a72375d9..abebe2df 100644 --- a/higan/fc/system/system.hpp +++ b/higan/fc/system/system.hpp @@ -41,17 +41,7 @@ private: uint _serializeSize = 0; }; -struct Peripherals { - auto unload() -> void; - auto reset() -> void; - auto connect(uint port, uint device) -> void; - - Controller* controllerPort1 = nullptr; - Controller* controllerPort2 = nullptr; -}; - extern System system; -extern Peripherals peripherals; auto Region::NTSCJ() -> bool { return system.region() == System::Region::NTSCJ; } auto Region::NTSCU() -> bool { return system.region() == System::Region::NTSCU; } diff --git a/higan/md/controller/gamepad/gamepad.hpp b/higan/md/controller/gamepad/gamepad.hpp index f0e9311a..59becc9e 100644 --- a/higan/md/controller/gamepad/gamepad.hpp +++ b/higan/md/controller/gamepad/gamepad.hpp @@ -1,6 +1,6 @@ struct Gamepad : Controller { enum : uint { - Up, Down, Left, Right, A, B, C, X, Y, Z, Start, + Up, Down, Left, Right, A, B, C, Start, }; Gamepad(uint port); diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index d3c7aadf..64cb6d1f 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -34,9 +34,6 @@ Interface::Interface() { device.inputs.append({0, "A" }); device.inputs.append({0, "B" }); device.inputs.append({0, "C" }); - device.inputs.append({0, "X" }); - device.inputs.append({0, "Y" }); - device.inputs.append({0, "Z" }); device.inputs.append({0, "Start"}); controllerPort1.devices.append(device); controllerPort2.devices.append(device); diff --git a/higan/ms/bus/bus.cpp b/higan/ms/bus/bus.cpp index 875c1c19..4e3ad1f0 100644 --- a/higan/ms/bus/bus.cpp +++ b/higan/ms/bus/bus.cpp @@ -45,8 +45,8 @@ auto Bus::in(uint8 addr) -> uint8 { case 3: { if(Model::MasterSystem()) { bool reset = !platform->inputPoll(ID::Port::Hardware, ID::Device::MasterSystemControls, 0); - auto port1 = peripherals.controllerPort1->readData(); - auto port2 = peripherals.controllerPort2->readData(); + auto port1 = controllerPort1.device->readData(); + auto port2 = controllerPort2.device->readData(); if(addr.bit(0) == 0) { return port1.bits(0,5) << 0 | port2.bits(0,1) << 6; } else { diff --git a/higan/ms/controller/controller.cpp b/higan/ms/controller/controller.cpp index 12c279cf..91bcfa38 100644 --- a/higan/ms/controller/controller.cpp +++ b/higan/ms/controller/controller.cpp @@ -2,6 +2,8 @@ namespace MasterSystem { +ControllerPort controllerPort1; +ControllerPort controllerPort2; #include "gamepad/gamepad.cpp" Controller::Controller(uint port) : port(port) { @@ -15,8 +17,8 @@ Controller::~Controller() { auto Controller::Enter() -> void { while(true) { scheduler.synchronize(); - if(auto device = peripherals.controllerPort1) if(device->active()) device->main(); - if(auto device = peripherals.controllerPort2) if(device->active()) device->main(); + if(controllerPort1.device->active()) controllerPort1.device->main(); + if(controllerPort2.device->active()) controllerPort2.device->main(); } } @@ -25,4 +27,33 @@ auto Controller::main() -> void { synchronize(cpu); } +// + +auto ControllerPort::connect(uint deviceID) -> void { + delete device; + if(!system.loaded()) return; + if(!Model::MasterSystem()) return; + + switch(deviceID) { default: + case ID::Device::None: device = new Controller(port); break; + case ID::Device::Gamepad: device = new Gamepad(port); break; + } + + cpu.peripherals.reset(); + if(auto device = controllerPort1.device) cpu.peripherals.append(device); + if(auto device = controllerPort2.device) cpu.peripherals.append(device); +} + +auto ControllerPort::power(uint port) -> void { + this->port = port; +} + +auto ControllerPort::unload() -> void { + delete device; + device = nullptr; +} + +auto ControllerPort::serialize(serializer& s) -> void { +} + } diff --git a/higan/ms/controller/controller.hpp b/higan/ms/controller/controller.hpp index ce9fbb5b..9007b81c 100644 --- a/higan/ms/controller/controller.hpp +++ b/higan/ms/controller/controller.hpp @@ -10,4 +10,18 @@ struct Controller : Thread { const uint port; }; +struct ControllerPort { + auto connect(uint deviceID) -> void; + + auto power(uint port) -> void; + auto unload() -> void; + auto serialize(serializer&) -> void; + + uint port; + Controller* device = nullptr; +}; + +extern ControllerPort controllerPort1; +extern ControllerPort controllerPort2; + #include "gamepad/gamepad.hpp" diff --git a/higan/ms/interface/interface.cpp b/higan/ms/interface/interface.cpp index f9e24184..28adc687 100644 --- a/higan/ms/interface/interface.cpp +++ b/higan/ms/interface/interface.cpp @@ -30,10 +30,6 @@ auto Interface::unload() -> void { system.unload(); } -auto Interface::connect(uint port, uint device) -> void { - peripherals.connect(port, device); -} - auto Interface::power() -> void { system.power(); } diff --git a/higan/ms/interface/interface.hpp b/higan/ms/interface/interface.hpp index e861942b..1d61f052 100644 --- a/higan/ms/interface/interface.hpp +++ b/higan/ms/interface/interface.hpp @@ -31,7 +31,7 @@ struct Interface : Emulator::Interface { auto save() -> void override; auto unload() -> void override; - auto connect(uint port, uint device) -> void override; + auto connect(uint port, uint device) -> void override {} auto power() -> void override; auto run() -> void override; @@ -56,6 +56,8 @@ struct MasterSystemInterface : Interface { auto videoColor(uint32 color) -> uint64 override; auto load(uint id) -> bool override; + + auto connect(uint port, uint device) -> void override; }; struct GameGearInterface : Interface { diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 480a78b9..2ba1ecd8 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -68,3 +68,8 @@ auto MasterSystemInterface::load(uint id) -> bool { if(id == ID::MasterSystem) return system.load(this, System::Model::MasterSystem); return false; } + +auto MasterSystemInterface::connect(uint port, uint device) -> void { + if(port == ID::Port::Controller1) controllerPort1.connect(settings.controllerPort1 = device); + if(port == ID::Port::Controller2) controllerPort2.connect(settings.controllerPort2 = device); +} diff --git a/higan/ms/system/peripherals.cpp b/higan/ms/system/peripherals.cpp deleted file mode 100644 index da23e6b0..00000000 --- a/higan/ms/system/peripherals.cpp +++ /dev/null @@ -1,44 +0,0 @@ -Peripherals peripherals; - -auto Peripherals::unload() -> void { - delete controllerPort1; - delete controllerPort2; - controllerPort1 = nullptr; - controllerPort2 = nullptr; -} - -auto Peripherals::reset() -> void { - connect(ID::Port::Controller1, settings.controllerPort1); - connect(ID::Port::Controller2, settings.controllerPort2); -} - -auto Peripherals::connect(uint port, uint device) -> void { - cpu.peripherals.reset(); - - if(Model::MasterSystem()) { - if(port == ID::Port::Controller1) { - settings.controllerPort1 = device; - if(!system.loaded()) return; - - delete controllerPort1; - switch(device) { default: - case ID::Device::None: controllerPort1 = new Controller(ID::Port::Controller1); break; - case ID::Device::Gamepad: controllerPort1 = new Gamepad(ID::Port::Controller1); break; - } - } - - if(port == ID::Port::Controller2) { - settings.controllerPort2 = device; - if(!system.loaded()) return; - - delete controllerPort2; - switch(device) { default: - case ID::Device::None: controllerPort2 = new Controller(ID::Port::Controller2); break; - case ID::Device::Gamepad: controllerPort2 = new Gamepad(ID::Port::Controller2); break; - } - } - - cpu.peripherals.append(controllerPort1); - cpu.peripherals.append(controllerPort2); - } -} diff --git a/higan/ms/system/serialization.cpp b/higan/ms/system/serialization.cpp index e3638bbb..2b7fd172 100644 --- a/higan/ms/system/serialization.cpp +++ b/higan/ms/system/serialization.cpp @@ -60,6 +60,8 @@ auto System::serializeAll(serializer& s) -> void { cpu.serialize(s); vdp.serialize(s); psg.serialize(s); + controllerPort1.serialize(s); + controllerPort2.serialize(s); } auto System::serialize(serializer& s) -> void { diff --git a/higan/ms/system/system.cpp b/higan/ms/system/system.cpp index 13b320a1..835b5edc 100644 --- a/higan/ms/system/system.cpp +++ b/higan/ms/system/system.cpp @@ -5,7 +5,6 @@ namespace MasterSystem { System system; Scheduler scheduler; Cheat cheat; -#include "peripherals.cpp" #include "serialization.cpp" auto System::run() -> void { @@ -51,7 +50,11 @@ auto System::save() -> void { } auto System::unload() -> void { - peripherals.unload(); + if(MasterSystem::Model::MasterSystem()) { + cpu.peripherals.reset(); + controllerPort1.unload(); + controllerPort2.unload(); + } cartridge.unload(); } @@ -70,7 +73,13 @@ auto System::power() -> void { psg.power(); scheduler.primary(cpu); - peripherals.reset(); + if(MasterSystem::Model::MasterSystem()) { + controllerPort1.power(ID::Port::Controller1); + controllerPort2.power(ID::Port::Controller2); + + controllerPort1.connect(settings.controllerPort1); + controllerPort2.connect(settings.controllerPort2); + } } } diff --git a/higan/ms/system/system.hpp b/higan/ms/system/system.hpp index e786b07a..222a7141 100644 --- a/higan/ms/system/system.hpp +++ b/higan/ms/system/system.hpp @@ -36,17 +36,7 @@ private: } information; }; -struct Peripherals { - auto unload() -> void; - auto reset() -> void; - auto connect(uint port, uint device) -> void; - - Controller* controllerPort1 = nullptr; - Controller* controllerPort2 = nullptr; -}; - extern System system; -extern Peripherals peripherals; auto Model::MasterSystem() -> bool { return system.model() == System::Model::MasterSystem; } auto Model::GameGear() -> bool { return system.model() == System::Model::GameGear; } diff --git a/higan/pce/controller/controller.cpp b/higan/pce/controller/controller.cpp index 63e0c0f3..f491b095 100644 --- a/higan/pce/controller/controller.cpp +++ b/higan/pce/controller/controller.cpp @@ -2,10 +2,11 @@ namespace PCEngine { +ControllerPort controllerPort; #include "gamepad/gamepad.cpp" Controller::Controller() { - if(!handle()) create(Controller::Enter, 100); + if(!handle()) create(Controller::Enter, 1); } Controller::~Controller() { @@ -15,7 +16,7 @@ Controller::~Controller() { auto Controller::Enter() -> void { while(true) { scheduler.synchronize(); - if(peripherals.controllerPort->active()) peripherals.controllerPort->main(); + if(controllerPort.device->active()) controllerPort.device->main(); } } @@ -24,4 +25,30 @@ auto Controller::main() -> void { synchronize(cpu); } +// + +auto ControllerPort::connect(uint deviceID) -> void { + delete device; + if(!system.loaded()) return; + + switch(deviceID) { default: + case ID::Device::None: device = new Controller; break; + case ID::Device::Gamepad: device = new Gamepad; break; + } + + cpu.peripherals.reset(); + if(auto device = controllerPort.device) cpu.peripherals.append(device); +} + +auto ControllerPort::power() -> void { +} + +auto ControllerPort::unload() -> void { + delete device; + device = nullptr; +} + +auto ControllerPort::serialize(serializer& s) -> void { +} + } diff --git a/higan/pce/controller/controller.hpp b/higan/pce/controller/controller.hpp index 6fc3e5c5..919bc36d 100644 --- a/higan/pce/controller/controller.hpp +++ b/higan/pce/controller/controller.hpp @@ -9,4 +9,16 @@ struct Controller : Thread { virtual auto writeData(uint2) -> void {} }; +struct ControllerPort { + auto connect(uint deviceID) -> void; + + auto power() -> void; + auto unload() -> void; + auto serialize(serializer&) -> void; + + Controller* device = nullptr; +}; + +extern ControllerPort controllerPort; + #include "gamepad/gamepad.hpp" diff --git a/higan/pce/cpu/io.cpp b/higan/pce/cpu/io.cpp index ab68c4f1..a4da34f2 100644 --- a/higan/pce/cpu/io.cpp +++ b/higan/pce/cpu/io.cpp @@ -54,7 +54,7 @@ auto CPU::read_(uint8 bank, uint13 addr) -> uint8 { //note 2: we state that the CD-ROM drive is present. //this is so games can use its backup RAM for save data. return ( - PCEngine::peripherals.controllerPort->readData() << 0 + controllerPort.device->readData() << 0 | 1 << 4 | 1 << 5 | 0 << 6 //device (0 = Turbografx-16; 1 = PC Engine) @@ -162,7 +162,7 @@ auto CPU::write(uint8 bank, uint13 addr, uint8 data) -> void { //$1000-13ff I/O if((addr & 0x1c00) == 0x1000) { io.mdr = data; - PCEngine::peripherals.controllerPort->writeData(data.bits(0,1)); + controllerPort.device->writeData(data.bits(0,1)); return; } diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index ac495041..4b765978 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -85,7 +85,7 @@ auto Interface::unload() -> void { } auto Interface::connect(uint port, uint device) -> void { - PCEngine::peripherals.connect(port, device); + if(port == ID::Port::Controller) controllerPort.connect(settings.controllerPort = device); } auto Interface::power() -> void { diff --git a/higan/pce/system/peripherals.cpp b/higan/pce/system/peripherals.cpp deleted file mode 100644 index e4595ccf..00000000 --- a/higan/pce/system/peripherals.cpp +++ /dev/null @@ -1,26 +0,0 @@ -Peripherals peripherals; - -auto Peripherals::unload() -> void { - delete controllerPort; - controllerPort = nullptr; -} - -auto Peripherals::reset() -> void { - connect(ID::Port::Controller, settings.controllerPort); -} - -auto Peripherals::connect(uint port, uint device) -> void { - if(port == ID::Port::Controller) { - settings.controllerPort = device; - if(!system.loaded()) return; - - delete controllerPort; - switch(device) { default: - case ID::Device::None: controllerPort = new Controller; break; - case ID::Device::Gamepad: controllerPort = new Gamepad; break; - } - } - - cpu.peripherals.reset(); - cpu.peripherals.append(controllerPort); -} diff --git a/higan/pce/system/serialization.cpp b/higan/pce/system/serialization.cpp index 3670f997..2eb1e9ad 100644 --- a/higan/pce/system/serialization.cpp +++ b/higan/pce/system/serialization.cpp @@ -61,6 +61,7 @@ auto System::serializeAll(serializer& s) -> void { vdc0.serialize(s); vdc1.serialize(s); psg.serialize(s); + controllerPort.serialize(s); } auto System::serialize(serializer& s) -> void { diff --git a/higan/pce/system/system.cpp b/higan/pce/system/system.cpp index f5c44b82..e64a2017 100644 --- a/higan/pce/system/system.cpp +++ b/higan/pce/system/system.cpp @@ -5,7 +5,6 @@ namespace PCEngine { System system; Scheduler scheduler; Cheat cheat; -#include "peripherals.cpp" #include "serialization.cpp" auto System::run() -> void { @@ -44,7 +43,8 @@ auto System::save() -> void { } auto System::unload() -> void { - peripherals.unload(); + cpu.peripherals.reset(); + controllerPort.unload(); cartridge.unload(); } @@ -66,7 +66,8 @@ auto System::power() -> void { psg.power(); scheduler.primary(cpu); - peripherals.reset(); + controllerPort.power(); + controllerPort.connect(settings.controllerPort); } } diff --git a/higan/pce/system/system.hpp b/higan/pce/system/system.hpp index 16e80138..e1e443eb 100644 --- a/higan/pce/system/system.hpp +++ b/higan/pce/system/system.hpp @@ -33,16 +33,7 @@ private: } information; }; -struct Peripherals { - auto unload() -> void; - auto reset() -> void; - auto connect(uint port, uint device) -> void; - - Controller* controllerPort = nullptr; -}; - extern System system; -extern Peripherals peripherals; auto Model::PCEngine() -> bool { return system.model() == System::Model::PCEngine; } auto Model::SuperGrafx() -> bool { return system.model() == System::Model::SuperGrafx; } diff --git a/higan/processor/spc700/instructions.cpp b/higan/processor/spc700/instructions.cpp index 6dcf9a28..daf20101 100644 --- a/higan/processor/spc700/instructions.cpp +++ b/higan/processor/spc700/instructions.cpp @@ -413,7 +413,7 @@ auto SPC700::instructionIndirectXWrite(uint8& data) -> void { auto SPC700::instructionIndirectXIncrementRead(uint8& data) -> void { idle(PC); - idle(); //quirk: does not read internal SMP registers + idle(page(X), false); //quirk: does not read internal SMP registers data = read(page(X++)); ZF = data == 0; NF = data & 0x80; @@ -421,7 +421,7 @@ auto SPC700::instructionIndirectXIncrementRead(uint8& data) -> void { auto SPC700::instructionIndirectXIncrementWrite(uint8& data) -> void { idle(PC); - idle(); //quirk: does not read internal SMP registers + idle(page(X), false); //quirk: does not read internal SMP registers write(page(X++), data); } diff --git a/higan/processor/spc700/spc700.cpp b/higan/processor/spc700/spc700.cpp index 0e1cfce6..c0cf0bd1 100644 --- a/higan/processor/spc700/spc700.cpp +++ b/higan/processor/spc700/spc700.cpp @@ -28,10 +28,6 @@ namespace Processor { #include "serialization.cpp" #include "disassembler.cpp" -auto SPC700::idle(uint16 address) -> void { - read(address); -} - auto SPC700::page(uint8 address) const -> uint16 { return PF << 8 | address; } diff --git a/higan/processor/spc700/spc700.hpp b/higan/processor/spc700/spc700.hpp index 81493c76..243bd7ea 100644 --- a/higan/processor/spc700/spc700.hpp +++ b/higan/processor/spc700/spc700.hpp @@ -3,7 +3,7 @@ namespace Processor { struct SPC700 { - virtual auto idle() -> void = 0; + virtual auto idle(uint16 address, bool read = true) -> void = 0; virtual auto read(uint16 address) -> uint8 = 0; virtual auto write(uint16 addessr, uint8 data) -> void = 0; virtual auto synchronizing() const -> bool = 0; @@ -11,7 +11,6 @@ struct SPC700 { virtual auto readDisassembler(uint16 address) -> uint8 { return 0; } //spc700.cpp - inline auto idle(uint16 address) -> void; inline auto page(uint8 address) const -> uint16; inline auto stack(uint8 address) const -> uint16; diff --git a/higan/sfc/controller/controller.cpp b/higan/sfc/controller/controller.cpp index 18ef751f..5e087e1d 100644 --- a/higan/sfc/controller/controller.cpp +++ b/higan/sfc/controller/controller.cpp @@ -10,7 +10,7 @@ ControllerPort controllerPort2; #include "super-scope/super-scope.cpp" #include "justifier/justifier.cpp" -Controller::Controller(bool port) : port(port) { +Controller::Controller(uint port) : port(port) { if(!handle()) create(Controller::Enter, 1); } @@ -33,15 +33,16 @@ auto Controller::main() -> void { auto Controller::iobit() -> bool { switch(port) { - case Controller::Port1: return cpu.pio() & 0x40; - case Controller::Port2: return cpu.pio() & 0x80; + case ID::Port::Controller1: return cpu.pio() & 0x40; + case ID::Port::Controller2: return cpu.pio() & 0x80; } + unreachable; } auto Controller::iobit(bool data) -> void { switch(port) { - case Controller::Port1: bus.write(0x4201, (cpu.pio() & ~0x40) | (data << 6)); break; - case Controller::Port2: bus.write(0x4201, (cpu.pio() & ~0x80) | (data << 7)); break; + case ID::Port::Controller1: bus.write(0x4201, (cpu.pio() & ~0x40) | (data << 6)); break; + case ID::Port::Controller2: bus.write(0x4201, (cpu.pio() & ~0x80) | (data << 7)); break; } } diff --git a/higan/sfc/controller/controller.hpp b/higan/sfc/controller/controller.hpp index 023aaca1..508bdb46 100644 --- a/higan/sfc/controller/controller.hpp +++ b/higan/sfc/controller/controller.hpp @@ -12,9 +12,7 @@ // 7: gnd struct Controller : Thread { - enum : bool { Port1 = 0, Port2 = 1 }; - - Controller(bool port); + Controller(uint port); virtual ~Controller(); static auto Enter() -> void; @@ -24,7 +22,7 @@ struct Controller : Thread { virtual auto data() -> uint2 { return 0; } virtual auto latch(bool data) -> void {} - const bool port; + const uint port; }; struct ControllerPort { diff --git a/higan/sfc/controller/gamepad/gamepad.cpp b/higan/sfc/controller/gamepad/gamepad.cpp index 90539566..bdef37e7 100644 --- a/higan/sfc/controller/gamepad/gamepad.cpp +++ b/higan/sfc/controller/gamepad/gamepad.cpp @@ -1,4 +1,4 @@ -Gamepad::Gamepad(bool port) : Controller(port) { +Gamepad::Gamepad(uint port) : Controller(port) { latched = 0; counter = 0; } diff --git a/higan/sfc/controller/gamepad/gamepad.hpp b/higan/sfc/controller/gamepad/gamepad.hpp index f96808a5..b28c7ba2 100644 --- a/higan/sfc/controller/gamepad/gamepad.hpp +++ b/higan/sfc/controller/gamepad/gamepad.hpp @@ -3,7 +3,7 @@ struct Gamepad : Controller { Up, Down, Left, Right, B, A, Y, X, L, R, Select, Start, }; - Gamepad(bool port); + Gamepad(uint port); auto data() -> uint2; auto latch(bool data) -> void; diff --git a/higan/sfc/controller/justifier/justifier.cpp b/higan/sfc/controller/justifier/justifier.cpp index 106b9239..82ce55ed 100644 --- a/higan/sfc/controller/justifier/justifier.cpp +++ b/higan/sfc/controller/justifier/justifier.cpp @@ -1,9 +1,9 @@ -Justifier::Justifier(bool port, bool chained): +Justifier::Justifier(uint port, bool chained): Controller(port), chained(chained), device(!chained ? ID::Device::Justifier : ID::Device::Justifiers) { - create(Controller::Enter, 21'477'272); + create(Controller::Enter, system.cpuFrequency()); latched = 0; counter = 0; active = 0; diff --git a/higan/sfc/controller/justifier/justifier.hpp b/higan/sfc/controller/justifier/justifier.hpp index 6b99b103..a4d8ece6 100644 --- a/higan/sfc/controller/justifier/justifier.hpp +++ b/higan/sfc/controller/justifier/justifier.hpp @@ -3,7 +3,7 @@ struct Justifier : Controller { X, Y, Trigger, Start, }; - Justifier(bool port, bool chained); + Justifier(uint port, bool chained); ~Justifier(); auto main() -> void; diff --git a/higan/sfc/controller/mouse/mouse.cpp b/higan/sfc/controller/mouse/mouse.cpp index 0d31fc10..88e450c5 100644 --- a/higan/sfc/controller/mouse/mouse.cpp +++ b/higan/sfc/controller/mouse/mouse.cpp @@ -1,4 +1,4 @@ -Mouse::Mouse(bool port) : Controller(port) { +Mouse::Mouse(uint port) : Controller(port) { latched = 0; counter = 0; diff --git a/higan/sfc/controller/mouse/mouse.hpp b/higan/sfc/controller/mouse/mouse.hpp index 2ab71a56..a094d23e 100644 --- a/higan/sfc/controller/mouse/mouse.hpp +++ b/higan/sfc/controller/mouse/mouse.hpp @@ -3,7 +3,7 @@ struct Mouse : Controller { X, Y, Left, Right, }; - Mouse(bool port); + Mouse(uint port); auto data() -> uint2; auto latch(bool data) -> void; diff --git a/higan/sfc/controller/super-multitap/super-multitap.cpp b/higan/sfc/controller/super-multitap/super-multitap.cpp index 439189bc..7ef141be 100644 --- a/higan/sfc/controller/super-multitap/super-multitap.cpp +++ b/higan/sfc/controller/super-multitap/super-multitap.cpp @@ -1,4 +1,4 @@ -SuperMultitap::SuperMultitap(bool port) : Controller(port) { +SuperMultitap::SuperMultitap(uint port) : Controller(port) { latched = 0; counter1 = 0; counter2 = 0; diff --git a/higan/sfc/controller/super-multitap/super-multitap.hpp b/higan/sfc/controller/super-multitap/super-multitap.hpp index f49dfc29..7ab21273 100644 --- a/higan/sfc/controller/super-multitap/super-multitap.hpp +++ b/higan/sfc/controller/super-multitap/super-multitap.hpp @@ -3,7 +3,7 @@ struct SuperMultitap : Controller { Up, Down, Left, Right, B, A, Y, X, L, R, Select, Start, }; - SuperMultitap(bool port); + SuperMultitap(uint port); auto data() -> uint2; auto latch(bool data) -> void; diff --git a/higan/sfc/controller/super-scope/super-scope.cpp b/higan/sfc/controller/super-scope/super-scope.cpp index 9b311593..a46578c2 100644 --- a/higan/sfc/controller/super-scope/super-scope.cpp +++ b/higan/sfc/controller/super-scope/super-scope.cpp @@ -10,8 +10,8 @@ //require manual polling of PIO ($4201.d6) to determine when iobit was written. //Note that no commercial game ever utilizes a Super Scope in port 1. -SuperScope::SuperScope(bool port) : Controller(port) { - create(Controller::Enter, 21'477'272); +SuperScope::SuperScope(uint port) : Controller(port) { + create(Controller::Enter, system.cpuFrequency()); sprite = Emulator::video.createSprite(32, 32); sprite->setPixels(Resource::Sprite::CrosshairGreen); diff --git a/higan/sfc/controller/super-scope/super-scope.hpp b/higan/sfc/controller/super-scope/super-scope.hpp index bcf467bf..6bb23bc8 100644 --- a/higan/sfc/controller/super-scope/super-scope.hpp +++ b/higan/sfc/controller/super-scope/super-scope.hpp @@ -5,7 +5,7 @@ struct SuperScope : Controller { X, Y, Trigger, Cursor, Turbo, Pause, }; - SuperScope(bool port); + SuperScope(uint port); ~SuperScope(); auto main() -> void; diff --git a/higan/sfc/cpu/cpu.cpp b/higan/sfc/cpu/cpu.cpp index b29a5791..ee43f054 100644 --- a/higan/sfc/cpu/cpu.cpp +++ b/higan/sfc/cpu/cpu.cpp @@ -116,9 +116,6 @@ auto CPU::power() -> void { channel.hdmaDoTransfer = false; } - //$2140-217f - for(auto& port : io.port) port = 0x00; - //$2181-$2183 io.wramAddress = 0x000000; diff --git a/higan/sfc/cpu/cpu.hpp b/higan/sfc/cpu/cpu.hpp index 09febb1e..34db5ff1 100644 --- a/higan/sfc/cpu/cpu.hpp +++ b/higan/sfc/cpu/cpu.hpp @@ -4,11 +4,9 @@ struct CPU : Processor::WDC65816, Thread, PPUcounter { auto joylatch() const -> bool; auto synchronizing() const -> bool override; + //cpu.cpp CPU(); - auto readPort(uint2 port) const -> uint8; - auto writePort(uint2 port, uint8 data) -> void; - static auto Enter() -> void; auto main() -> void; auto load(Markup::Node) -> bool; @@ -135,9 +133,6 @@ private: } status; struct IO { - //$2140-217f - uint8 port[4]; - //$2181-$2183 uint17 wramAddress; diff --git a/higan/sfc/cpu/io.cpp b/higan/sfc/cpu/io.cpp index a590b1e4..d84ee4f3 100644 --- a/higan/sfc/cpu/io.cpp +++ b/higan/sfc/cpu/io.cpp @@ -1,6 +1,6 @@ auto CPU::readAPU(uint24 addr, uint8 data) -> uint8 { synchronize(smp); - return smp.readPort(addr.bits(0,1)); + return smp.portRead(addr.bits(0,1)); } auto CPU::readCPU(uint24 addr, uint8 data) -> uint8 { @@ -158,7 +158,7 @@ auto CPU::readDMA(uint24 addr, uint8 data) -> uint8 { auto CPU::writeAPU(uint24 addr, uint8 data) -> void { synchronize(smp); - return writePort(addr.bits(0,1), data); + return smp.portWrite(addr.bits(0,1), data); } auto CPU::writeCPU(uint24 addr, uint8 data) -> void { diff --git a/higan/sfc/cpu/memory.cpp b/higan/sfc/cpu/memory.cpp index 05d05f96..3e21c70e 100644 --- a/higan/sfc/cpu/memory.cpp +++ b/higan/sfc/cpu/memory.cpp @@ -1,11 +1,3 @@ -auto CPU::readPort(uint2 port) const -> uint8 { - return io.port[port]; -} - -auto CPU::writePort(uint2 port, uint8 data) -> void { - io.port[port] = data; -} - auto CPU::idle() -> void { status.clockCount = 6; dmaEdge(); diff --git a/higan/sfc/cpu/serialization.cpp b/higan/sfc/cpu/serialization.cpp index 70817760..deff2249 100644 --- a/higan/sfc/cpu/serialization.cpp +++ b/higan/sfc/cpu/serialization.cpp @@ -49,8 +49,6 @@ auto CPU::serialize(serializer& s) -> void { s.integer(status.autoJoypadLatch); s.integer(status.autoJoypadCounter); - s.array(io.port); - s.integer(io.wramAddress); s.integer(io.joypadStrobeLatch); diff --git a/higan/sfc/dsp/brr.cpp b/higan/sfc/dsp/brr.cpp index 255b3304..7fae1908 100644 --- a/higan/sfc/dsp/brr.cpp +++ b/higan/sfc/dsp/brr.cpp @@ -1,6 +1,6 @@ auto DSP::brrDecode(Voice& v) -> void { //state.t_brr_byte = ram[v.brr_addr + v.brr_offset] cached from previous clock cycle - int nybbles = (state._brrByte << 8) + smp.apuram[(uint16)(v.brrAddress + v.brrOffset + 1)]; + int nybbles = (state._brrByte << 8) + apuram[(uint16)(v.brrAddress + v.brrOffset + 1)]; const int filter = (state._brrHeader >> 2) & 3; const int scale = (state._brrHeader >> 4); diff --git a/higan/sfc/dsp/dsp.cpp b/higan/sfc/dsp/dsp.cpp index f61d6460..b92d65e2 100644 --- a/higan/sfc/dsp/dsp.cpp +++ b/higan/sfc/dsp/dsp.cpp @@ -232,6 +232,8 @@ auto DSP::power() -> void { create(Enter, system.apuFrequency()); stream = Emulator::audio.createStream(2, frequency() / 768.0); + for(auto& byte : apuram) byte = random(0x00); + memory::fill(&state, sizeof(State)); state.noise = 0x4000; state.echoHistoryOffset = 0; diff --git a/higan/sfc/dsp/dsp.hpp b/higan/sfc/dsp/dsp.hpp index 2b561a44..68695bed 100644 --- a/higan/sfc/dsp/dsp.hpp +++ b/higan/sfc/dsp/dsp.hpp @@ -2,6 +2,7 @@ struct DSP : Thread { shared_pointer stream; + uint8 apuram[64 * 1024]; DSP(); diff --git a/higan/sfc/dsp/echo.cpp b/higan/sfc/dsp/echo.cpp index 301e4ae0..7a1805e0 100644 --- a/higan/sfc/dsp/echo.cpp +++ b/higan/sfc/dsp/echo.cpp @@ -11,8 +11,8 @@ auto DSP::echoOutput(bool channel) -> int { auto DSP::echoRead(bool channel) -> void { uint addr = state._echoPointer + channel * 2; - uint8 lo = smp.apuram[(uint16)(addr + 0)]; - uint8 hi = smp.apuram[(uint16)(addr + 1)]; + uint8 lo = apuram[(uint16)(addr + 0)]; + uint8 hi = apuram[(uint16)(addr + 1)]; int s = (int16)((hi << 8) + lo); state.echoHistory[channel][state.echoHistoryOffset] = s >> 1; } @@ -21,8 +21,8 @@ auto DSP::echoWrite(bool channel) -> void { if(!(state._echoDisabled & 0x20)) { uint addr = state._echoPointer + channel * 2; int s = state._echoOut[channel]; - smp.apuram[(uint16)(addr + 0)] = s; - smp.apuram[(uint16)(addr + 1)] = s >> 8; + apuram[(uint16)(addr + 0)] = s; + apuram[(uint16)(addr + 1)] = s >> 8; } state._echoOut[channel] = 0; diff --git a/higan/sfc/dsp/serialization.cpp b/higan/sfc/dsp/serialization.cpp index 1182f873..8518b667 100644 --- a/higan/sfc/dsp/serialization.cpp +++ b/higan/sfc/dsp/serialization.cpp @@ -1,6 +1,8 @@ void DSP::serialize(serializer& s) { Thread::serialize(s); + s.array(apuram); + s.array(state.regs, 128); s.array(state.echoHistory[0]); s.array(state.echoHistory[1]); diff --git a/higan/sfc/dsp/voice.cpp b/higan/sfc/dsp/voice.cpp index baa9abdd..14f5dca4 100644 --- a/higan/sfc/dsp/voice.cpp +++ b/higan/sfc/dsp/voice.cpp @@ -22,8 +22,8 @@ auto DSP::voice2(Voice& v) -> void { //read sample pointer (ignored if not needed) uint16 addr = state._dirAddress; if(!v.konDelay) addr += 2; - uint8 lo = smp.apuram[(uint16)(addr + 0)]; - uint8 hi = smp.apuram[(uint16)(addr + 1)]; + uint8 lo = apuram[(uint16)(addr + 0)]; + uint8 hi = apuram[(uint16)(addr + 1)]; state._brrNextAddress = ((hi << 8) + lo); state._adsr0 = VREG(ADSR0); @@ -43,8 +43,8 @@ auto DSP::voice3a(Voice& v) -> void { } auto DSP::voice3b(Voice& v) -> void { - state._brrByte = smp.apuram[(uint16)(v.brrAddress + v.brrOffset)]; - state._brrHeader = smp.apuram[(uint16)(v.brrAddress)]; + state._brrByte = apuram[(uint16)(v.brrAddress + v.brrOffset)]; + state._brrHeader = apuram[(uint16)(v.brrAddress)]; } auto DSP::voice3c(Voice& v) -> void { diff --git a/higan/sfc/smp/memory.cpp b/higan/sfc/smp/memory.cpp index af57334d..c325de0b 100644 --- a/higan/sfc/smp/memory.cpp +++ b/higan/sfc/smp/memory.cpp @@ -1,30 +1,37 @@ -alwaysinline auto SMP::readRAM(uint16 addr) -> uint8 { +alwaysinline auto SMP::ramRead(uint16 addr) -> uint8 { if(addr >= 0xffc0 && io.iplromEnable) return iplrom[addr & 0x3f]; if(io.ramDisable) return 0x5a; //0xff on mini-SNES - return apuram[addr]; + return dsp.apuram[addr]; } -alwaysinline auto SMP::writeRAM(uint16 addr, uint8 data) -> void { +alwaysinline auto SMP::ramWrite(uint16 addr, uint8 data) -> void { //writes to $ffc0-$ffff always go to apuram, even if the iplrom is enabled - if(io.ramWritable && !io.ramDisable) apuram[addr] = data; + if(io.ramWritable && !io.ramDisable) dsp.apuram[addr] = data; } -auto SMP::readPort(uint2 port) const -> uint8 { - return io.port[0xf4 + port]; +auto SMP::portRead(uint2 port) const -> uint8 { + if(port == 0) return io.cpu0; + if(port == 1) return io.cpu1; + if(port == 2) return io.cpu2; + if(port == 3) return io.cpu3; + unreachable; } -auto SMP::writePort(uint2 port, uint8 data) -> void { - io.port[0xf4 + port] = data; +auto SMP::portWrite(uint2 port, uint8 data) -> void { + if(port == 0) io.apu0 = data; + if(port == 1) io.apu1 = data; + if(port == 2) io.apu2 = data; + if(port == 3) io.apu3 = data; } -auto SMP::readBus(uint16 addr) -> uint8 { +auto SMP::busRead(uint16 addr) -> uint8 { uint result; switch(addr) { - case 0xf0: //TEST -- write-only register + case 0xf0: //TEST (write-only register) return 0x00; - case 0xf1: //CONTROL -- write-only register + case 0xf1: //CONTROL (write-only register) return 0x00; case 0xf2: //DSPADDR @@ -35,55 +42,64 @@ auto SMP::readBus(uint16 addr) -> uint8 { return dsp.read(io.dspAddr & 0x7f); case 0xf4: //CPUIO0 + synchronize(cpu); + return io.apu0; + case 0xf5: //CPUIO1 + synchronize(cpu); + return io.apu1; + case 0xf6: //CPUIO2 + synchronize(cpu); + return io.apu2; + case 0xf7: //CPUIO3 synchronize(cpu); - return cpu.readPort(addr); + return io.apu3; - case 0xf8: //RAM0 - return io.ram00f8; + case 0xf8: //AUXIO4 + return io.aux4; - case 0xf9: //RAM1 - return io.ram00f9; + case 0xf9: //AUXIO5 + return io.aux5; case 0xfa: //T0TARGET case 0xfb: //T1TARGET - case 0xfc: //T2TARGET -- write-only registers + case 0xfc: //T2TARGET (write-only registers) return 0x00; - case 0xfd: //T0OUT -- 4-bit counter value + case 0xfd: //T0OUT (4-bit counter value) result = timer0.stage3; timer0.stage3 = 0; return result; - case 0xfe: //T1OUT -- 4-bit counter value + case 0xfe: //T1OUT (4-bit counter value) result = timer1.stage3; timer1.stage3 = 0; return result; - case 0xff: //T2OUT -- 4-bit counter value + case 0xff: //T2OUT (4-bit counter value) result = timer2.stage3; timer2.stage3 = 0; return result; } - return readRAM(addr); + return ramRead(addr); } -auto SMP::writeBus(uint16 addr, uint8 data) -> void { +auto SMP::busWrite(uint16 addr, uint8 data) -> void { switch(addr) { case 0xf0: //TEST if(r.p.p) break; //writes only valid when P flag is clear - io.clockSpeed = (data >> 6) & 3; - io.timerSpeed = (data >> 4) & 3; - io.timersEnable = data & 0x08; - io.ramDisable = data & 0x04; - io.ramWritable = data & 0x02; - io.timersDisable = data & 0x01; + io.timersDisable = data.bit (0); + io.ramWritable = data.bit (1); + io.ramDisable = data.bit (2); + io.timersEnable = data.bit (3); + io.ramSpeed = data.bits(4,5); + io.romIOSpeed = data.bits(6,7); - io.timerStep = (1 << io.clockSpeed) + (2 << io.timerSpeed); + io.timerStep = (1 << io.romIOSpeed) + (2 << io.ramSpeed); timer0.synchronizeStage1(); timer1.synchronizeStage1(); @@ -91,40 +107,38 @@ auto SMP::writeBus(uint16 addr, uint8 data) -> void { break; case 0xf1: //CONTROL - io.iplromEnable = data & 0x80; - - if(data & 0x30) { - //one-time clearing of APU port read registers, - //emulated by simulating CPU writes of 0x00 - synchronize(cpu); - if(data & 0x20) { - cpu.writePort(2, 0x00); - cpu.writePort(3, 0x00); - } - if(data & 0x10) { - cpu.writePort(0, 0x00); - cpu.writePort(1, 0x00); - } - } - //0->1 transistion resets timers - if(!timer2.enable && (data & 0x04)) { - timer2.stage2 = 0; - timer2.stage3 = 0; - } - timer2.enable = data & 0x04; - - if(!timer1.enable && (data & 0x02)) { - timer1.stage2 = 0; - timer1.stage3 = 0; - } - timer1.enable = data & 0x02; - - if(!timer0.enable && (data & 0x01)) { + if(!timer0.enable && data.bit(0)) { timer0.stage2 = 0; timer0.stage3 = 0; } - timer0.enable = data & 0x01; + timer0.enable = data.bit(0); + + if(!timer1.enable && data.bit(1)) { + timer1.stage2 = 0; + timer1.stage3 = 0; + } + timer1.enable = data.bit(1); + + if(!timer2.enable && data.bit(2)) { + timer2.stage2 = 0; + timer2.stage3 = 0; + } + timer2.enable = data.bit(2); + + if(data.bit(4)) { + synchronize(cpu); + io.apu0 = 0x00; + io.apu1 = 0x00; + } + + if(data.bit(5)) { + synchronize(cpu); + io.apu2 = 0x00; + io.apu3 = 0x00; + } + + io.iplromEnable = data.bit(7); break; case 0xf2: //DSPADDR @@ -137,19 +151,31 @@ auto SMP::writeBus(uint16 addr, uint8 data) -> void { break; case 0xf4: //CPUIO0 + synchronize(cpu); + io.cpu0 = data; + break; + case 0xf5: //CPUIO1 + synchronize(cpu); + io.cpu1 = data; + break; + case 0xf6: //CPUIO2 + synchronize(cpu); + io.cpu2 = data; + break; + case 0xf7: //CPUIO3 synchronize(cpu); - writePort(addr, data); + io.cpu3 = data; break; - case 0xf8: //RAM0 - io.ram00f8 = data; + case 0xf8: //AUXIO4 + io.aux4 = data; break; - case 0xf9: //RAM1 - io.ram00f9 = data; + case 0xf9: //AUXIO5 + io.aux5 = data; break; case 0xfa: //T0TARGET @@ -166,34 +192,41 @@ auto SMP::writeBus(uint16 addr, uint8 data) -> void { case 0xfd: //T0OUT case 0xfe: //T1OUT - case 0xff: //T2OUT -- read-only registers + case 0xff: //T2OUT (read-only registers) break; } - writeRAM(addr, data); //all writes, even to MMIO registers, appear on bus + ramWrite(addr, data); //all writes, even to I/O registers, appear on bus } -auto SMP::idle() -> void { - step(24); +auto SMP::speed(uint16 addr) const -> uint { + static const uint waitStates[4] = {1, 2, 5, 10}; + if((addr & 0xfff0) == 0x00f0) return waitStates[io.romIOSpeed]; + if(addr >= 0xffc0 && io.iplromEnable) return waitStates[io.romIOSpeed]; + return waitStates[io.ramSpeed]; +} + +auto SMP::idle(uint16 addr, bool read) -> void { + step(24 * speed(addr)); + if(read) busRead(addr); cycleEdge(); } auto SMP::read(uint16 addr) -> uint8 { - step(12); - uint8 data = readBus(addr); - step(12); + step(24 * speed(addr)); + uint8 data = busRead(addr); cycleEdge(); return data; } auto SMP::write(uint16 addr, uint8 data) -> void { - step(24); - writeBus(addr, data); + step(24 * speed(addr)); + busWrite(addr, data); cycleEdge(); } auto SMP::readDisassembler(uint16 addr) -> uint8 { if((addr & 0xfff0) == 0x00f0) return 0x00; - if((addr & 0xffc0) == 0xffc0 && io.iplromEnable) return iplrom[addr & 0x3f]; - return apuram[addr]; + if(addr >= 0xffc0 && io.iplromEnable) return iplrom[addr & 0x3f]; + return dsp.apuram[addr]; } diff --git a/higan/sfc/smp/serialization.cpp b/higan/sfc/smp/serialization.cpp index b12811b3..f68c2ec4 100644 --- a/higan/sfc/smp/serialization.cpp +++ b/higan/sfc/smp/serialization.cpp @@ -2,27 +2,33 @@ auto SMP::serialize(serializer& s) -> void { SPC700::serialize(s); Thread::serialize(s); - s.array(apuram); - s.integer(io.clockCounter); s.integer(io.dspCounter); s.integer(io.timerStep); - s.integer(io.clockSpeed); - s.integer(io.timerSpeed); - s.integer(io.timersEnable); - s.integer(io.ramDisable); - s.integer(io.ramWritable); + s.integer(io.apu0); + s.integer(io.apu1); + s.integer(io.apu2); + s.integer(io.apu3); + s.integer(io.timersDisable); + s.integer(io.ramWritable); + s.integer(io.ramDisable); + s.integer(io.timersEnable); + s.integer(io.ramSpeed); + s.integer(io.romIOSpeed); s.integer(io.iplromEnable); s.integer(io.dspAddr); - s.array(io.port); + s.integer(io.cpu0); + s.integer(io.cpu1); + s.integer(io.cpu2); + s.integer(io.cpu3); - s.integer(io.ram00f8); - s.integer(io.ram00f9); + s.integer(io.aux4); + s.integer(io.aux5); s.integer(timer0.stage0); s.integer(timer0.stage1); diff --git a/higan/sfc/smp/smp.cpp b/higan/sfc/smp/smp.cpp index 3b57f97f..a73de9e9 100644 --- a/higan/sfc/smp/smp.cpp +++ b/higan/sfc/smp/smp.cpp @@ -39,19 +39,24 @@ auto SMP::power() -> void { r.pc.byte.l = iplrom[62]; r.pc.byte.h = iplrom[63]; - for(auto& byte : apuram) byte = random(0x00); - + //timing io.clockCounter = 0; io.dspCounter = 0; - io.timerStep = 3; + io.timerStep = (1 << 0) + (2 << 0); + + //external + io.apu0 = 0x00; + io.apu1 = 0x00; + io.apu2 = 0x00; + io.apu3 = 0x00; //$00f0 - io.clockSpeed = 0; - io.timerSpeed = 0; - io.timersEnable = true; - io.ramDisable = false; - io.ramWritable = true; io.timersDisable = false; + io.ramWritable = true; + io.ramDisable = false; + io.timersEnable = true; + io.ramSpeed = 0; + io.romIOSpeed = 0; //$00f1 io.iplromEnable = true; @@ -60,14 +65,14 @@ auto SMP::power() -> void { io.dspAddr = 0x00; //$00f4-00f7 - io.port[0] = 0x00; - io.port[1] = 0x00; - io.port[2] = 0x00; - io.port[3] = 0x00; + io.cpu0 = 0x00; + io.cpu1 = 0x00; + io.cpu2 = 0x00; + io.cpu3 = 0x00; - //$00f8,$00f9 - io.ram00f8 = 0x00; - io.ram00f9 = 0x00; + //$00f8-$00f9 + io.aux4 = 0x00; + io.aux5 = 0x00; timer0.stage0 = 0; timer1.stage0 = 0; diff --git a/higan/sfc/smp/smp.hpp b/higan/sfc/smp/smp.hpp index d03f1825..a1a35391 100644 --- a/higan/sfc/smp/smp.hpp +++ b/higan/sfc/smp/smp.hpp @@ -1,11 +1,13 @@ //Sony CXP1100Q-1 struct SMP : Processor::SPC700, Thread { + uint8 iplrom[64]; + //smp.cpp auto synchronizing() const -> bool override; - auto readPort(uint2 port) const -> uint8; - auto writePort(uint2 port, uint8 data) -> void; + auto portRead(uint2 port) const -> uint8; + auto portWrite(uint2 port, uint8 data) -> void; auto main() -> void; auto load(Markup::Node) -> bool; @@ -14,9 +16,6 @@ struct SMP : Processor::SPC700, Thread { //serialization.cpp auto serialize(serializer&) -> void; - uint8 iplrom[64]; - uint8 apuram[64 * 1024]; - private: struct IO { //timing @@ -24,13 +23,19 @@ private: uint dspCounter; uint timerStep; + //external + uint8 apu0; + uint8 apu1; + uint8 apu2; + uint8 apu3; + //$00f0 - uint8 clockSpeed; - uint8 timerSpeed; - bool timersEnable; - bool ramDisable; - bool ramWritable; - bool timersDisable; + uint1 timersDisable; + uint1 ramWritable; + uint1 ramDisable; + uint1 timersEnable; + uint2 ramSpeed; + uint2 romIOSpeed; //$00f1 bool iplromEnable; @@ -39,23 +44,27 @@ private: uint8 dspAddr; //$00f4-00f7 - uint8 port[4]; + uint8 cpu0; + uint8 cpu1; + uint8 cpu2; + uint8 cpu3; - //$00f8,$00f9 - uint8 ram00f8; - uint8 ram00f9; + //$00f8-00f9 + uint8 aux4; + uint8 aux5; } io; static auto Enter() -> void; //memory.cpp - auto readRAM(uint16 addr) -> uint8; - auto writeRAM(uint16 addr, uint8 data) -> void; + auto ramRead(uint16 addr) -> uint8; + auto ramWrite(uint16 addr, uint8 data) -> void; - auto readBus(uint16 addr) -> uint8; - auto writeBus(uint16 addr, uint8 data) -> void; + auto busRead(uint16 addr) -> uint8; + auto busWrite(uint16 addr, uint8 data) -> void; - auto idle() -> void override; + auto speed(uint16 addr) const -> uint; + auto idle(uint16 addr, bool read = true) -> void override; auto read(uint16 addr) -> uint8 override; auto write(uint16 addr, uint8 data) -> void override; diff --git a/higan/sfc/smp/timing.cpp b/higan/sfc/smp/timing.cpp index 42edb8d4..27fa9769 100644 --- a/higan/sfc/smp/timing.cpp +++ b/higan/sfc/smp/timing.cpp @@ -15,15 +15,6 @@ auto SMP::cycleEdge() -> void { timer0.tick(); timer1.tick(); timer2.tick(); - - //TEST register S-SMP speed control - //24 clocks have already been added for this cycle at this point - switch(io.clockSpeed) { - case 0: break; //100% speed - case 1: step(24); break; // 50% speed - case 2: while(true) step(24); // 0% speed -- locks S-SMP - case 3: step(24 * 9); break; // 10% speed - } } template auto SMP::Timer::tick() -> void {