diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 2c3006f2..901aee50 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -7,7 +7,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "098.02"; + static const string Version = "098.03"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/sfc/GNUmakefile b/higan/sfc/GNUmakefile index 288e2e7b..92b02600 100644 --- a/higan/sfc/GNUmakefile +++ b/higan/sfc/GNUmakefile @@ -3,7 +3,7 @@ processors += r65816 spc700 arm gsu hg51b upd96050 objects += sfc-interface sfc-system sfc-scheduler sfc-controller objects += sfc-cartridge sfc-cheat objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu -objects += sfc-satellaview sfc-superdisc +objects += sfc-expansion sfc-satellaview sfc-superdisc objects += sfc-21fx objects += sfc-icd2 sfc-mcc sfc-nss sfc-event objects += sfc-sa1 sfc-superfx @@ -26,6 +26,7 @@ obj/sfc-smp.o: sfc/smp/smp.cpp $(call rwildcard,sfc/smp/) obj/sfc-dsp.o: sfc/dsp/dsp.cpp $(call rwildcard,sfc/dsp/) obj/sfc-ppu.o: sfc/ppu/ppu.cpp $(call rwildcard,sfc/ppu/) +obj/sfc-expansion.o: sfc/expansion/expansion.cpp $(call rwildcard,sfc/expansion/) obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/) obj/sfc-superdisc.o: sfc/expansion/superdisc/superdisc.cpp $(call rwildcard,sfc/expansion/superdisc/) obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansion/21fx/) diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 5813269a..e465e708 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -35,20 +35,6 @@ struct Cartridge : property { MappedRAM rom; MappedRAM ram; - struct Mapping { - function uint8> reader; - function void> writer; - string addr; - uint size = 0; - uint base = 0; - uint mask = 0; - - Mapping() = default; - Mapping(const function&, const function&); - Mapping(SuperFamicom::Memory&); - }; - vector mapping; - struct Memory { unsigned id; string name; diff --git a/higan/sfc/cartridge/markup.cpp b/higan/sfc/cartridge/markup.cpp index 7cc43faf..7e28690b 100644 --- a/higan/sfc/cartridge/markup.cpp +++ b/higan/sfc/cartridge/markup.cpp @@ -1,13 +1,3 @@ -Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) { - this->reader = {&SuperFamicom::Memory::read, &memory}; - this->writer = {&SuperFamicom::Memory::write, &memory}; -} - -Cartridge::Mapping::Mapping(const function& reader, const function& writer) { - this->reader = reader; - this->writer = writer; -} - auto Cartridge::parseMarkup(const string& markup) -> void { auto document = BML::unserialize(markup); auto information = document["information"]; @@ -16,7 +6,6 @@ auto Cartridge::parseMarkup(const string& markup) -> void { this->information.title.cartridge = information["title"].text(); _region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; - mapping.reset(); if(auto node = board["rom"]) parseMarkupROM(node); if(auto node = board["ram"]) parseMarkupRAM(node); if(auto node = board["icd2"]) parseMarkupICD2(node); @@ -40,13 +29,13 @@ auto Cartridge::parseMarkup(const string& markup) -> void { } auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -> void { - Mapping m{memory}; - m.addr = map["address"].text(); - m.size = map["size"].natural(); - m.base = map["base"].natural(); - m.mask = map["mask"].natural(); - if(m.size == 0) m.size = memory.size(); - if(m.size != 0) mapping.append(m); + auto addr = map["address"].text(); + auto size = map["size"].natural(); + auto base = map["base"].natural(); + auto mask = map["mask"].natural(); + if(size == 0) size = memory.size(); + if(size == 0) return; + bus.map({&SuperFamicom::Memory::read, &memory}, {&SuperFamicom::Memory::write, &memory}, addr, size, base, mask); } auto Cartridge::parseMarkupMap( @@ -54,12 +43,11 @@ auto Cartridge::parseMarkupMap( const function& reader, const function& writer ) -> void { - Mapping m{reader, writer}; - m.addr = map["address"].text(); - m.size = map["size"].natural(); - m.base = map["base"].natural(); - m.mask = map["mask"].natural(); - mapping.append(m); + auto addr = map["address"].text(); + auto size = map["size"].natural(); + auto base = map["base"].natural(); + auto mask = map["mask"].natural(); + bus.map(reader, writer, addr, size, base, mask); } auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, uint id, bool writable) -> void { diff --git a/higan/sfc/controller/controller.cpp b/higan/sfc/controller/controller.cpp index 153238f9..4a88e14a 100644 --- a/higan/sfc/controller/controller.cpp +++ b/higan/sfc/controller/controller.cpp @@ -15,8 +15,9 @@ Controller::Controller(bool port) : port(port) { auto Controller::Enter() -> void { while(true) { - if(co_active() == device.controllerPort1->thread) device.controllerPort1->main(); - if(co_active() == device.controllerPort2->thread) device.controllerPort2->main(); + scheduler.synchronize(); + if(co_active() == peripherals.controllerPort1->thread) peripherals.controllerPort1->main(); + if(co_active() == peripherals.controllerPort2->thread) peripherals.controllerPort2->main(); } } diff --git a/higan/sfc/controller/gamepad/gamepad.cpp b/higan/sfc/controller/gamepad/gamepad.cpp index e2c38f6e..7d34331d 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, (uint)Device::ID::Gamepad, B); + if(latched == 1) return interface->inputPoll(port, 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 = (uint)Device::ID::Gamepad; + auto 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 df499da7..973925c5 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 ? (unsigned)Device::ID::Justifier : (unsigned)Device::ID::Justifiers) +device(chained == false ? Device::Justifier : Device::Justifiers) { create(Controller::Enter, 21477272); latched = 0; diff --git a/higan/sfc/controller/mouse/mouse.cpp b/higan/sfc/controller/mouse/mouse.cpp index ddf977f5..30660068 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, (unsigned)Device::ID::Mouse, X); //-n = left, 0 = center, +n = right - y = interface->inputPoll(port, (unsigned)Device::ID::Mouse, Y); //-n = up, 0 = center, +n = down - l = interface->inputPoll(port, (unsigned)Device::ID::Mouse, Left); - r = interface->inputPoll(port, (unsigned)Device::ID::Mouse, Right); + 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); 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 b17ae23b..7d21bc53 100644 --- a/higan/sfc/controller/multitap/multitap.cpp +++ b/higan/sfc/controller/multitap/multitap.cpp @@ -24,8 +24,8 @@ auto Multitap::data() -> uint2 { port2 = 3; //controller 4 } - bool data1 = interface->inputPoll(port, (unsigned)Device::ID::Multitap, port1 * 12 + index); - bool data2 = interface->inputPoll(port, (unsigned)Device::ID::Multitap, port2 * 12 + index); + 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); } diff --git a/higan/sfc/controller/superscope/superscope.cpp b/higan/sfc/controller/superscope/superscope.cpp index 575c3884..d67839c2 100644 --- a/higan/sfc/controller/superscope/superscope.cpp +++ b/higan/sfc/controller/superscope/superscope.cpp @@ -46,8 +46,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, (unsigned)Device::ID::SuperScope, X); - int ny = interface->inputPoll(port, (unsigned)Device::ID::SuperScope, Y); + int nx = interface->inputPoll(port, Device::SuperScope, X); + int ny = interface->inputPoll(port, Device::SuperScope, Y); nx += x; ny += y; x = max(-16, min(256 + 16, nx)); @@ -64,7 +64,7 @@ auto SuperScope::data() -> uint2 { if(counter == 0) { //turbo is a switch; toggle is edge sensitive - bool newturbo = interface->inputPoll(port, (unsigned)Device::ID::SuperScope, Turbo); + bool newturbo = interface->inputPoll(port, Device::SuperScope, Turbo); if(newturbo && !turbo) { turbo = !turbo; //toggle state turbolock = true; @@ -75,7 +75,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, (unsigned)Device::ID::SuperScope, Trigger); + bool newtrigger = interface->inputPoll(port, Device::SuperScope, Trigger); if(newtrigger && (turbo || !triggerlock)) { trigger = true; triggerlock = true; @@ -84,11 +84,11 @@ auto SuperScope::data() -> uint2 { } //cursor is a button; it is always level sensitive - cursor = interface->inputPoll(port, (unsigned)Device::ID::SuperScope, Cursor); + cursor = interface->inputPoll(port, Device::SuperScope, Cursor); //pause is a button; it is always edge sensitive pause = false; - bool newpause = interface->inputPoll(port, (unsigned)Device::ID::SuperScope, Pause); + bool newpause = interface->inputPoll(port, Device::SuperScope, Pause); if(newpause && !pauselock) { pause = true; pauselock = true; diff --git a/higan/sfc/controller/usart/usart.cpp b/higan/sfc/controller/usart/usart.cpp index 450ac195..ca9751a9 100644 --- a/higan/sfc/controller/usart/usart.cpp +++ b/higan/sfc/controller/usart/usart.cpp @@ -80,7 +80,7 @@ auto USART::data() -> uint2 { if(iobit()) { if(counter >= 16) return 1; uint2 result = 0; - if(counter < 12) result = interface->inputPoll(port, (uint)Device::ID::Gamepad, counter); + if(counter < 12) result = interface->inputPoll(port, Device::Gamepad, counter); if(latched == 0) counter++; return result; } diff --git a/higan/sfc/coprocessor/sdd1/sdd1.cpp b/higan/sfc/coprocessor/sdd1/sdd1.cpp index 1bfbbfe1..de01bd4f 100644 --- a/higan/sfc/coprocessor/sdd1/sdd1.cpp +++ b/higan/sfc/coprocessor/sdd1/sdd1.cpp @@ -11,10 +11,6 @@ auto SDD1::init() -> void { } void SDD1::load() { - //hook S-CPU DMA MMIO registers to gather information for struct dma[]; - //buffer address and transfer size information for use in SDD1::mcu_read() - bus.map({&SDD1::dma_read, &sdd1}, {&SDD1::dma_write, &sdd1}, 0x00, 0x3f, 0x4300, 0x437f); - bus.map({&SDD1::dma_read, &sdd1}, {&SDD1::dma_write, &sdd1}, 0x80, 0xbf, 0x4300, 0x437f); } auto SDD1::unload() -> void { @@ -26,6 +22,10 @@ auto SDD1::power() -> void { } auto SDD1::reset() -> void { + //hook S-CPU DMA MMIO registers to gather information for struct dma[]; + //buffer address and transfer size information for use in SDD1::mcu_read() + bus.map({&SDD1::dma_read, &sdd1}, {&SDD1::dma_write, &sdd1}, "00-3f,80-bf:4300-437f"); + sdd1_enable = 0x00; xfer_enable = 0x00; dma_ready = false; diff --git a/higan/sfc/cpu/cpu.cpp b/higan/sfc/cpu/cpu.cpp index c751e245..9094fdd3 100644 --- a/higan/sfc/cpu/cpu.cpp +++ b/higan/sfc/cpu/cpu.cpp @@ -85,38 +85,6 @@ auto CPU::main() -> void { instruction(); } -auto CPU::enable() -> void { - function uint8> reader; - function void> writer; - - reader = {&CPU::apuPortRead, this}; - writer = {&CPU::apuPortWrite, this}; - bus.map(reader, writer, 0x00, 0x3f, 0x2140, 0x217f); - bus.map(reader, writer, 0x80, 0xbf, 0x2140, 0x217f); - - reader = {&CPU::cpuPortRead, this}; - writer = {&CPU::cpuPortWrite, this}; - bus.map(reader, writer, 0x00, 0x3f, 0x2180, 0x2183); - bus.map(reader, writer, 0x80, 0xbf, 0x2180, 0x2183); - - bus.map(reader, writer, 0x00, 0x3f, 0x4016, 0x4017); - bus.map(reader, writer, 0x80, 0xbf, 0x4016, 0x4017); - - bus.map(reader, writer, 0x00, 0x3f, 0x4200, 0x421f); - bus.map(reader, writer, 0x80, 0xbf, 0x4200, 0x421f); - - reader = {&CPU::dmaPortRead, this}; - writer = {&CPU::dmaPortWrite, this}; - bus.map(reader, writer, 0x00, 0x3f, 0x4300, 0x437f); - bus.map(reader, writer, 0x80, 0xbf, 0x4300, 0x437f); - - reader = [](uint24 addr, uint8) -> uint8 { return cpu.wram[addr]; }; - writer = [](uint24 addr, uint8 data) -> void { cpu.wram[addr] = data; }; - bus.map(reader, writer, 0x00, 0x3f, 0x0000, 0x1fff, 0x002000); - bus.map(reader, writer, 0x80, 0xbf, 0x0000, 0x1fff, 0x002000); - bus.map(reader, writer, 0x7e, 0x7f, 0x0000, 0xffff, 0x020000); -} - auto CPU::power() -> void { for(auto& byte : wram) byte = random(0x55); @@ -155,6 +123,26 @@ auto CPU::reset() -> void { coprocessors.reset(); PPUcounter::reset(); + function uint8> reader; + function void> writer; + + reader = {&CPU::apuPortRead, this}; + writer = {&CPU::apuPortWrite, this}; + bus.map(reader, writer, "00-3f,80-bf:2140-217f"); + + reader = {&CPU::cpuPortRead, this}; + writer = {&CPU::cpuPortWrite, this}; + bus.map(reader, writer, "00-3f,80-bf:2180-2183,4016-4017,4200-421f"); + + reader = {&CPU::dmaPortRead, this}; + writer = {&CPU::dmaPortWrite, this}; + bus.map(reader, writer, "00-3f,80-bf:4300-437f"); + + reader = [](uint24 addr, uint8) -> uint8 { return cpu.wram[addr]; }; + writer = [](uint24 addr, uint8 data) -> void { cpu.wram[addr] = data; }; + bus.map(reader, writer, "00-3f,80-bf:0000-1fff", 0x2000); + bus.map(reader, writer, "7e-7f:0000-ffff", 0x20000); + //CPU regs.pc = 0x000000; regs.x.h = 0x00; diff --git a/higan/sfc/cpu/cpu.hpp b/higan/sfc/cpu/cpu.hpp index 236750b5..c31e5de0 100644 --- a/higan/sfc/cpu/cpu.hpp +++ b/higan/sfc/cpu/cpu.hpp @@ -16,7 +16,6 @@ struct CPU : Processor::R65816, Thread, PPUcounter { static auto Enter() -> void; auto main() -> void; - auto enable() -> void; auto power() -> void; auto reset() -> void; diff --git a/higan/sfc/cpu/joypad.cpp b/higan/sfc/cpu/joypad.cpp index e60402d3..aaa81406 100644 --- a/higan/sfc/cpu/joypad.cpp +++ b/higan/sfc/cpu/joypad.cpp @@ -7,14 +7,14 @@ auto CPU::stepAutoJoypadPoll() -> void { if(status.auto_joypad_active && status.auto_joypad_latch) { if(status.auto_joypad_counter == 0) { - device.controllerPort1->latch(1); - device.controllerPort2->latch(1); - device.controllerPort1->latch(0); - device.controllerPort2->latch(0); + SuperFamicom::peripherals.controllerPort1->latch(1); + SuperFamicom::peripherals.controllerPort2->latch(1); + SuperFamicom::peripherals.controllerPort1->latch(0); + SuperFamicom::peripherals.controllerPort2->latch(0); } - uint2 port0 = device.controllerPort1->data(); - uint2 port1 = device.controllerPort2->data(); + uint2 port0 = SuperFamicom::peripherals.controllerPort1->data(); + uint2 port1 = SuperFamicom::peripherals.controllerPort2->data(); status.joy1 = status.joy1 << 1 | port0.bit(0); status.joy2 = status.joy2 << 1 | port1.bit(0); diff --git a/higan/sfc/cpu/mmio.cpp b/higan/sfc/cpu/mmio.cpp index 08228b4d..433657e8 100644 --- a/higan/sfc/cpu/mmio.cpp +++ b/higan/sfc/cpu/mmio.cpp @@ -16,7 +16,7 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 { //1-0 = Joypad serial data if(addr == 0x4016) { uint8 r = regs.mdr & 0xfc; - r |= device.controllerPort1->data(); + r |= SuperFamicom::peripherals.controllerPort1->data(); return r; } @@ -26,7 +26,7 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 { //4-2 = Always 1 (pins are connected to GND) //1-0 = Joypad serial data uint8 r = (regs.mdr & 0xe0) | 0x1c; - r |= device.controllerPort2->data(); + r |= SuperFamicom::peripherals.controllerPort2->data(); return r; } @@ -183,8 +183,8 @@ auto CPU::cpuPortWrite(uint24 addr, uint8 data) -> void { //bit 0 is shared between JOYSER0 and JOYSER1, therefore //strobing $4016.d0 affects both controller port latches. //$4017 bit 0 writes are ignored. - device.controllerPort1->latch(data.bit(0)); - device.controllerPort2->latch(data.bit(0)); + SuperFamicom::peripherals.controllerPort1->latch(data.bit(0)); + SuperFamicom::peripherals.controllerPort2->latch(data.bit(0)); } //NMITIMEN diff --git a/higan/sfc/expansion/21fx/21fx.cpp b/higan/sfc/expansion/21fx/21fx.cpp index 636990d2..0a213556 100644 --- a/higan/sfc/expansion/21fx/21fx.cpp +++ b/higan/sfc/expansion/21fx/21fx.cpp @@ -2,10 +2,56 @@ namespace SuperFamicom { -S21FX s21fx; +S21FX::S21FX() { + create(S21FX::Enter, 10'000'000); + + resetVector.byte(0) = bus.read(0xfffc, 0x00); + resetVector.byte(1) = bus.read(0xfffd, 0x00); + + bus.map({&S21FX::read, this}, {&S21FX::write, this}, "00-3f,80-bf:2184-21ff"); + bus.map({&S21FX::read, this}, {&S21FX::write, this}, "00:fffc-fffd"); + + booted = false; + + for(auto& byte : ram) byte = 0xdb; //stp + ram[0] = 0x6c; //jmp ($fffc) + ram[1] = 0xfc; + ram[2] = 0xff; + + if(auto buffer = file::read({interface->path(ID::System), "21fx.rom"})) { + memory::copy(ram, sizeof(ram), buffer.data(), buffer.size()); + } + + string filename{interface->path(ID::SuperFamicom), "21fx.so"}; + if(link.openAbsolute(filename)) { + linkInit = link.sym("fx_init"); + linkMain = link.sym("fx_main"); + } +} + +S21FX::~S21FX() { + bus.unmap("00-3f,80-bf:2184-21ff"); + bus.unmap("00:fffc-fffd"); + + //note: this is an awful hack ... + //since the bus maps are lambdas, we can't safely restore the original reset vector handler + //as such, we install a basic read-only lambda that simply returns the known reset vector + //the downside is that if 00:fffc-fffd were anything but ROM; it will now only act as ROM + //given that this is the only device that hooks the reset vector like this, + //it's not worth the added complexity to support some form of reversible bus mapping hooks + uint vector = resetVector; + bus.map([vector](uint24 addr, uint8) -> uint8 { + return vector >> addr * 8; + }, [](uint24, uint8) -> void { + }, "00:fffc-fffd", 2); + + if(link.open()) link.close(); + linkInit.reset(); + linkMain.reset(); +} auto S21FX::Enter() -> void { - while(true) scheduler.synchronize(), s21fx.main(); + while(true) scheduler.synchronize(), peripherals.expansionPort->main(); } auto S21FX::main() -> void { @@ -21,47 +67,6 @@ auto S21FX::main() -> void { while(true) step(10'000'000); } -auto S21FX::init() -> void { -} - -auto S21FX::load() -> void { - resetVector.byte(0) = bus.read(0xfffc, 0x00); - resetVector.byte(1) = bus.read(0xfffd, 0x00); - - for(auto& byte : ram) byte = 0xdb; //stp - ram[0] = 0x6c; //jmp ($fffc) - ram[1] = 0xfc; - ram[2] = 0xff; - - bus.map({&S21FX::read, &s21fx}, {&S21FX::write, &s21fx}, 0x00, 0x00, 0xfffc, 0xfffd); - bus.map({&S21FX::read, &s21fx}, {&S21FX::write, &s21fx}, 0x00, 0x3f, 0x2184, 0x21ff); - bus.map({&S21FX::read, &s21fx}, {&S21FX::write, &s21fx}, 0x80, 0xbf, 0x2184, 0x21ff); - - if(auto buffer = file::read({interface->path(ID::System), "21fx.rom"})) { - memory::copy(ram, sizeof(ram), buffer.data(), buffer.size()); - } - - string filename{interface->path(ID::SuperFamicom), "21fx.so"}; - if(link.openAbsolute(filename)) { - linkInit = link.sym("fx_init"); - linkMain = link.sym("fx_main"); - } -} - -auto S21FX::unload() -> void { - if(link.open()) link.close(); - linkInit.reset(); - linkMain.reset(); -} - -auto S21FX::power() -> void { -} - -auto S21FX::reset() -> void { - create(S21FX::Enter, 10'000'000); - booted = false; -} - auto S21FX::read(uint24 addr, uint8 data) -> uint8 { addr &= 0x40ffff; diff --git a/higan/sfc/expansion/21fx/21fx.hpp b/higan/sfc/expansion/21fx/21fx.hpp index 9ddffd2d..e76d9ecb 100644 --- a/higan/sfc/expansion/21fx/21fx.hpp +++ b/higan/sfc/expansion/21fx/21fx.hpp @@ -1,11 +1,9 @@ -struct S21FX : Cothread, Memory { +struct S21FX : Expansion { + S21FX(); + ~S21FX(); + static auto Enter() -> void; auto main() -> void; - auto init() -> void; - auto load() -> void; - auto unload() -> void; - auto power() -> void; - auto reset() -> void; auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; @@ -36,5 +34,3 @@ private: vector snesBuffer; //SNES -> Link vector linkBuffer; //Link -> SNES }; - -extern S21FX s21fx; diff --git a/higan/sfc/expansion/expansion.cpp b/higan/sfc/expansion/expansion.cpp new file mode 100644 index 00000000..235561b3 --- /dev/null +++ b/higan/sfc/expansion/expansion.cpp @@ -0,0 +1,17 @@ +#include + +namespace SuperFamicom { + +Expansion::Expansion() { + if(!thread) create(Expansion::Enter, 1); +} + +auto Expansion::Enter() -> void { + while(true) scheduler.synchronize(), peripherals.expansionPort->main(); +} + +auto Expansion::main() -> void { + step(1); +} + +} diff --git a/higan/sfc/expansion/expansion.hpp b/higan/sfc/expansion/expansion.hpp index 9f42ca4e..c5cd820d 100644 --- a/higan/sfc/expansion/expansion.hpp +++ b/higan/sfc/expansion/expansion.hpp @@ -1,3 +1,9 @@ +struct Expansion : Cothread { + Expansion(); + static auto Enter() -> void; + virtual auto main() -> void; +}; + #include #include #include diff --git a/higan/sfc/expansion/satellaview/satellaview.cpp b/higan/sfc/expansion/satellaview/satellaview.cpp index 90b64c78..77981128 100644 --- a/higan/sfc/expansion/satellaview/satellaview.cpp +++ b/higan/sfc/expansion/satellaview/satellaview.cpp @@ -2,30 +2,17 @@ namespace SuperFamicom { -Satellaview satellaview; - -auto Satellaview::init() -> void { -} - -auto Satellaview::load() -> void { - bus.map({&Satellaview::read, &satellaview}, {&Satellaview::write, &satellaview}, 0x00, 0x3f, 0x2188, 0x219f); - bus.map({&Satellaview::read, &satellaview}, {&Satellaview::write, &satellaview}, 0x80, 0xbf, 0x2188, 0x219f); -} - -auto Satellaview::unload() -> void { -} - -auto Satellaview::power() -> void { -} - -auto Satellaview::reset() -> void { +Satellaview::Satellaview() { + bus.map({&Satellaview::read, this}, {&Satellaview::write, this}, "00-3f,80-bf:2188-219f"); memory::fill(®s, sizeof regs); } -auto Satellaview::read(uint24 addr, uint8 data) -> uint8 { - addr &= 0xffff; +Satellaview::~Satellaview() { + bus.unmap("00-3f,80-bf:2188-219f"); +} - switch(addr) { +auto Satellaview::read(uint24 addr, uint8 data) -> uint8 { + switch(addr &= 0xffff) { case 0x2188: return regs.r2188; case 0x2189: return regs.r2189; case 0x218a: return regs.r218a; @@ -81,9 +68,7 @@ auto Satellaview::read(uint24 addr, uint8 data) -> uint8 { } auto Satellaview::write(uint24 addr, uint8 data) -> void { - addr &= 0xffff; - - switch(addr) { + switch(addr &= 0xffff) { case 0x2188: { regs.r2188 = data; } break; diff --git a/higan/sfc/expansion/satellaview/satellaview.hpp b/higan/sfc/expansion/satellaview/satellaview.hpp index 7d520535..9c64c12d 100644 --- a/higan/sfc/expansion/satellaview/satellaview.hpp +++ b/higan/sfc/expansion/satellaview/satellaview.hpp @@ -1,9 +1,6 @@ -struct Satellaview : Memory { - auto init() -> void; - auto load() -> void; - auto unload() -> void; - auto power() -> void; - auto reset() -> void; +struct Satellaview : Expansion { + Satellaview(); + ~Satellaview(); auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; @@ -21,5 +18,3 @@ private: uint8 r2192_hour, r2192_minute, r2192_second; } regs; }; - -extern Satellaview satellaview; diff --git a/higan/sfc/expansion/superdisc/superdisc.cpp b/higan/sfc/expansion/superdisc/superdisc.cpp index 2d8a71f7..367e6775 100644 --- a/higan/sfc/expansion/superdisc/superdisc.cpp +++ b/higan/sfc/expansion/superdisc/superdisc.cpp @@ -2,12 +2,29 @@ namespace SuperFamicom { -SuperDisc superdisc; #include "nec.cpp" #include "sony.cpp" +SuperDisc::SuperDisc() { + create(&SuperDisc::Enter, 75); + + bus.map({&SuperDisc::read, this}, {&SuperDisc::write, this}, "00-3f,80-bf:21e0-21e5"); + + r.irqEnable = 0x00; + + nec.command.reset(); + nec.data = 0x00; + + sony.command = 0x00; + sony.data = 0x00; +} + +SuperDisc::~SuperDisc() { + bus.unmap("00-3f,80-bf:21e0-21e5"); +} + auto SuperDisc::Enter() -> void { - while(true) scheduler.synchronize(), superdisc.main(); + while(true) scheduler.synchronize(), peripherals.expansionPort->main(); } auto SuperDisc::main() -> void { @@ -27,31 +44,6 @@ auto SuperDisc::main() -> void { synchronizeCPU(); } -auto SuperDisc::init() -> void { -} - -auto SuperDisc::load() -> void { - bus.map({&SuperDisc::read, &superdisc}, {&SuperDisc::write, &superdisc}, 0x00, 0x3f, 0x21e0, 0x21e5); - bus.map({&SuperDisc::read, &superdisc}, {&SuperDisc::write, &superdisc}, 0x80, 0xbf, 0x21e0, 0x21e5); -} - -auto SuperDisc::unload() -> void { -} - -auto SuperDisc::power() -> void { - create(&SuperDisc::Enter, 75); -} - -auto SuperDisc::reset() -> void { - r.irqEnable = 0x00; - - nec.command.reset(); - nec.data = 0x00; - - sony.command = 0x00; - sony.data = 0x00; -} - auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 { addr = 0x21e0 | (addr & 7); diff --git a/higan/sfc/expansion/superdisc/superdisc.hpp b/higan/sfc/expansion/superdisc/superdisc.hpp index da305a6a..6dd98042 100644 --- a/higan/sfc/expansion/superdisc/superdisc.hpp +++ b/higan/sfc/expansion/superdisc/superdisc.hpp @@ -1,13 +1,10 @@ -struct SuperDisc : Cothread, Memory { +struct SuperDisc : Expansion { + SuperDisc(); + ~SuperDisc(); + static auto Enter() -> void; auto main() -> void; - auto init() -> void; - auto load() -> void; - auto unload() -> void; - auto power() -> void; - auto reset() -> void; - auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; @@ -39,5 +36,3 @@ private: uint8 data; } sony; }; - -extern SuperDisc superdisc; diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 60d6039f..cd6fd848 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -425,7 +425,7 @@ auto Interface::unload() -> void { } auto Interface::connect(uint port, uint device) -> void { - SuperFamicom::device.connect(port, (SuperFamicom::Device::ID)device); + SuperFamicom::peripherals.connect(port, device); } auto Interface::power() -> void { diff --git a/higan/sfc/memory/memory.cpp b/higan/sfc/memory/memory.cpp index 878693e6..28b7e4e3 100644 --- a/higan/sfc/memory/memory.cpp +++ b/higan/sfc/memory/memory.cpp @@ -4,63 +4,98 @@ namespace SuperFamicom { Bus bus; -Bus::Bus() { - lookup = new uint8 [16 * 1024 * 1024]; - target = new uint32[16 * 1024 * 1024]; -} - Bus::~Bus() { - delete[] lookup; - delete[] target; + if(lookup) delete[] lookup; + if(target) delete[] target; } auto Bus::reset() -> void { - function uint8> reader = [](uint24, uint8 data) { return data; }; - function void> writer = [](uint24, uint8) {}; + for(auto id : range(256)) { + reader[id].reset(); + writer[id].reset(); + counter[id] = 0; + } - idcount = 0; - map(reader, writer, 0x00, 0xff, 0x0000, 0xffff); + if(lookup) delete[] lookup; + if(target) delete[] target; + + lookup = new uint8 [16 * 1024 * 1024](); + target = new uint32[16 * 1024 * 1024](); + + reader[0] = [](uint24, uint8 data) -> uint8 { return data; }; + writer[0] = [](uint24, uint8) -> void {}; } -auto Bus::map() -> void { - for(auto& m : cartridge.mapping) { - lstring part = m.addr.split(":", 1L); - lstring banks = part(0).split(","); - lstring addrs = part(1).split(","); - for(auto& bank : banks) { - for(auto& addr : addrs) { - lstring bankpart = bank.split("-", 1L); - lstring addrpart = addr.split("-", 1L); - uint banklo = hex(bankpart(0)); - uint bankhi = hex(bankpart(1, bankpart(0))); - uint addrlo = hex(addrpart(0)); - uint addrhi = hex(addrpart(1, addrpart(0))); - map(m.reader, m.writer, banklo, bankhi, addrlo, addrhi, m.size, m.base, m.mask); +auto Bus::map( + const function& read, + const function& write, + const string& addr, uint size, uint base, uint mask +) -> void { + uint id = 1; + while(counter[id]) { + if(++id >= 256) return print("SFC error: bus map exhausted\n"); + } +//print("map[", hex(id, 2), "] => ", addr, "\n"); + + reader[id] = read; + writer[id] = write; + + auto p = addr.split(":", 1L); + auto banks = p(0).split(","); + auto addrs = p(1).split(","); + for(auto& bank : banks) { + for(auto& addr : addrs) { + auto bankRange = bank.split("-", 1L); + auto addrRange = addr.split("-", 1L); + uint bankLo = hex(bankRange(0)); + uint bankHi = hex(bankRange(1, bankRange(0))); + uint addrLo = hex(addrRange(0)); + uint addrHi = hex(addrRange(1, addrRange(0))); + + for(uint bank = bankLo; bank <= bankHi; bank++) { + for(uint addr = addrLo; addr <= addrHi; addr++) { + uint pid = lookup[bank << 16 | addr]; + if(pid && --counter[pid] == 0) { + reader[pid].reset(); + writer[pid].reset(); + } + + uint offset = reduce(bank << 16 | addr, mask); + if(size) offset = base + mirror(offset, size - base); + lookup[bank << 16 | addr] = id; + target[bank << 16 | addr] = offset; + counter[id]++; + } } } } } -auto Bus::map( - const function& reader, - const function& writer, - uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi, - uint size, uint base, uint mask -) -> void { - assert(banklo <= bankhi); - assert(addrlo <= addrhi); - assert(idcount < 255); +auto Bus::unmap(const string& addr) -> void { + auto p = addr.split(":", 1L); + auto banks = p(0).split(","); + auto addrs = p(1).split(","); + for(auto& bank : banks) { + for(auto& addr : addrs) { + auto bankRange = bank.split("-", 1L); + auto addrRange = addr.split("-", 1L); + uint bankLo = hex(bankRange(0)); + uint bankHi = hex(bankRange(1, bankRange(0))); + uint addrLo = hex(addrRange(0)); + uint addrHi = hex(addrRange(1, addrRange(1))); - uint id = idcount++; - this->reader[id] = reader; - this->writer[id] = writer; + for(uint bank = bankLo; bank <= bankHi; bank++) { + for(uint addr = addrLo; addr <= addrHi; addr++) { + uint pid = lookup[bank << 16 | addr]; + if(pid && --counter[pid] == 0) { + reader[pid].reset(); + writer[pid].reset(); + } - for(uint bank = banklo; bank <= bankhi; bank++) { - for(uint addr = addrlo; addr <= addrhi; addr++) { - uint offset = reduce(bank << 16 | addr, mask); - if(size) offset = base + mirror(offset, size - base); - lookup[bank << 16 | addr] = id; - target[bank << 16 | addr] = offset; + lookup[bank << 16 | addr] = 0; + target[bank << 16 | addr] = 0; + } + } } } } diff --git a/higan/sfc/memory/memory.hpp b/higan/sfc/memory/memory.hpp index 31a537a2..5b6f5323 100644 --- a/higan/sfc/memory/memory.hpp +++ b/higan/sfc/memory/memory.hpp @@ -45,27 +45,26 @@ struct Bus { alwaysinline static auto mirror(uint addr, uint size) -> uint; alwaysinline static auto reduce(uint addr, uint mask) -> uint; - Bus(); ~Bus(); alwaysinline auto read(uint24 addr, uint8 data) -> uint8; alwaysinline auto write(uint24 addr, uint8 data) -> void; auto reset() -> void; - auto map() -> void; auto map( - const function& reader, - const function& writer, - uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi, - uint size = 0, uint base = 0, uint mask = 0 + const function& read, + const function& write, + const string& addr, uint size = 0, uint base = 0, uint mask = 0 ) -> void; + auto unmap(const string& addr) -> void; +private: uint8* lookup = nullptr; uint32* target = nullptr; - uint idcount = 0; function uint8> reader[256]; function void> writer[256]; + uint24 counter[256]; }; extern Bus bus; diff --git a/higan/sfc/ppu/ppu.cpp b/higan/sfc/ppu/ppu.cpp index 2ad1cd5f..bdf11374 100644 --- a/higan/sfc/ppu/ppu.cpp +++ b/higan/sfc/ppu/ppu.cpp @@ -86,14 +86,6 @@ auto PPU::addClocks(uint clocks) -> void { } } -auto PPU::enable() -> void { - function uint8> reader{&PPU::read, this}; - function void> writer{&PPU::write, this}; - - bus.map(reader, writer, 0x00, 0x3f, 0x2100, 0x213f); - bus.map(reader, writer, 0x80, 0xbf, 0x2100, 0x213f); -} - auto PPU::power() -> void { for(auto& n : vram) n = random(0x00); for(auto& n : oam) n = random(0x00); @@ -105,6 +97,10 @@ auto PPU::reset() -> void { PPUcounter::reset(); memory::fill(output, 512 * 480 * sizeof(uint32)); + function uint8> reader{&PPU::read, this}; + function void> writer{&PPU::write, this}; + bus.map(reader, writer, "00-3f,80-bf:2100-213f"); + regs.ppu1_mdr = random(0xff); regs.ppu2_mdr = random(0xff); diff --git a/higan/sfc/ppu/ppu.hpp b/higan/sfc/ppu/ppu.hpp index 7d9ae9d2..c10f5c4a 100644 --- a/higan/sfc/ppu/ppu.hpp +++ b/higan/sfc/ppu/ppu.hpp @@ -13,7 +13,6 @@ struct PPU : Thread, PPUcounter { static auto Enter() -> void; auto main() -> void; - auto enable() -> void; auto power() -> void; auto reset() -> void; diff --git a/higan/sfc/ppu/video.cpp b/higan/sfc/ppu/video.cpp index 01f080e1..ae43e6b9 100644 --- a/higan/sfc/ppu/video.cpp +++ b/higan/sfc/ppu/video.cpp @@ -144,17 +144,17 @@ auto Video::drawCursor(uint32 color, int x, int y) -> void { } auto Video::drawCursors() -> void { - switch((Device::ID)settings.controllerPort2) { - case Device::ID::SuperScope: - if(dynamic_cast(device.controllerPort2)) { - auto& controller = (SuperScope&)*device.controllerPort2; + switch(settings.controllerPort2) { + case Device::SuperScope: + if(dynamic_cast(peripherals.controllerPort2)) { + auto& controller = (SuperScope&)*peripherals.controllerPort2; drawCursor(0xff0000ff, controller.x, controller.y); } break; - case Device::ID::Justifier: - case Device::ID::Justifiers: - if(dynamic_cast(device.controllerPort2)) { - auto& controller = (Justifier&)*device.controllerPort2; + case Device::Justifier: + case Device::Justifiers: + if(dynamic_cast(peripherals.controllerPort2)) { + auto& controller = (Justifier&)*peripherals.controllerPort2; drawCursor(0xffff0000, controller.player1.x, controller.player1.y); if(!controller.chained) break; drawCursor(0xff00bf00, controller.player2.x, controller.player2.y); diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index de0ea562..05fc0ceb 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -25,7 +25,7 @@ namespace SuperFamicom { namespace SuperFamicom { struct Thread { - ~Thread() { + virtual ~Thread() { if(thread) co_delete(thread); } @@ -61,10 +61,10 @@ namespace SuperFamicom { #include #include + #include #include #include #include - #include #include #include #include diff --git a/higan/sfc/system/device.cpp b/higan/sfc/system/device.cpp deleted file mode 100644 index d448d54e..00000000 --- a/higan/sfc/system/device.cpp +++ /dev/null @@ -1,47 +0,0 @@ -Device device; - -Device::Device() { - connect(0, ID::None); - connect(1, ID::None); - connect(2, ID::None); -} - -Device::~Device() { - if(controllerPort1) delete controllerPort1; - if(controllerPort2) delete controllerPort2; -} - -auto Device::connect(uint port, Device::ID id) -> void { - if(port == 0 || port == 1) { - Controller*& controller = (port == 0 ? controllerPort1 : controllerPort2); - - if(controller) { - delete controller; - controller = nullptr; - } - - switch(id) { default: - case ID::None: controller = new Controller(port); break; - case ID::Gamepad: controller = new Gamepad(port); break; - case ID::Multitap: controller = new Multitap(port); break; - case ID::Mouse: controller = new Mouse(port); break; - case ID::SuperScope: controller = new SuperScope(port); break; - case ID::Justifier: controller = new Justifier(port, false); break; - case ID::Justifiers: controller = new Justifier(port, true); break; - case ID::USART: controller = new USART(port); break; - } - - switch(port) { - case 0: settings.controllerPort1 = (uint)id; break; - case 1: settings.controllerPort2 = (uint)id; break; - } - } - - if(port == 2) { - settings.expansionPort = (uint)id; - } - - cpu.peripherals.reset(); - cpu.peripherals.append(controllerPort1); - cpu.peripherals.append(controllerPort2); -} diff --git a/higan/sfc/system/device.hpp b/higan/sfc/system/device.hpp deleted file mode 100644 index b8289e3d..00000000 --- a/higan/sfc/system/device.hpp +++ /dev/null @@ -1,35 +0,0 @@ -struct Device { - enum class Port : uint { - Controller1, - Controller2, - Expansion, - }; - - enum class ID : uint { - None, - - //controller port devices - Gamepad, - Multitap, - Mouse, - SuperScope, - Justifier, - Justifiers, - USART, - - //expansion port devices - Satellaview, - SuperDisc, - S21FX, - }; - - Device(); - ~Device(); - - auto connect(uint port, Device::ID id) -> void; - - Controller* controllerPort1 = nullptr; - Controller* controllerPort2 = nullptr; -}; - -extern Device device; diff --git a/higan/sfc/system/peripherals.cpp b/higan/sfc/system/peripherals.cpp new file mode 100644 index 00000000..9a6a1457 --- /dev/null +++ b/higan/sfc/system/peripherals.cpp @@ -0,0 +1,66 @@ +Peripherals peripherals; + +auto Peripherals::unload() -> void { + delete controllerPort1; + delete controllerPort2; + delete expansionPort; + controllerPort1 = nullptr; + controllerPort2 = nullptr; + expansionPort = nullptr; +} + +auto Peripherals::reset() -> void { + connect(0, settings.controllerPort1); + connect(1, settings.controllerPort2); + connect(2, settings.expansionPort); +} + +auto Peripherals::connect(uint port, uint id) -> void { + if(port == Port::Controller1) { + settings.controllerPort1 = id; + 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; + case Device::USART: controllerPort1 = new USART(0); break; + } + } + + if(port == Port::Controller2) { + settings.controllerPort2 = id; + 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; + } + } + + if(port == Port::Expansion) { + settings.expansionPort = id; + 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; + } + } + + cpu.peripherals.reset(); + cpu.peripherals.append(controllerPort1); + cpu.peripherals.append(controllerPort2); + cpu.peripherals.append(expansionPort); +} diff --git a/higan/sfc/system/peripherals.hpp b/higan/sfc/system/peripherals.hpp new file mode 100644 index 00000000..e0396955 --- /dev/null +++ b/higan/sfc/system/peripherals.hpp @@ -0,0 +1,35 @@ +struct Port { enum : uint { + Controller1, + Controller2, + Expansion, +};}; + +struct Device { enum : uint { + None, + + //controller port peripherals + Gamepad, + Multitap, + Mouse, + SuperScope, + Justifier, + Justifiers, + USART, + + //expansion port peripherals + Satellaview, + SuperDisc, + S21FX, +};}; + +struct Peripherals { + auto unload() -> void; + auto reset() -> void; + auto connect(uint port, uint id) -> void; + + Controller* controllerPort1 = nullptr; + Controller* controllerPort2 = nullptr; + Expansion* expansionPort = nullptr; +}; + +extern Peripherals peripherals; diff --git a/higan/sfc/system/serialization.cpp b/higan/sfc/system/serialization.cpp index d73b9bda..d0e34a85 100644 --- a/higan/sfc/system/serialization.cpp +++ b/higan/sfc/system/serialization.cpp @@ -39,7 +39,6 @@ auto System::unserialize(serializer& s) -> bool { auto System::serialize(serializer& s) -> void { s.integer((uint&)_region); - s.integer((uint&)_expansionPort); } auto System::serializeAll(serializer& s) -> void { diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index ebcda475..5c8bdce6 100644 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -4,13 +4,12 @@ namespace SuperFamicom { System system; -#include "device.cpp" +#include "peripherals.cpp" #include "random.cpp" #include "serialization.cpp" auto System::loaded() const -> bool { return _loaded; } auto System::region() const -> Region { return _region; } -auto System::expansionPort() const -> Device::ID { return _expansionPort; } auto System::cpuFrequency() const -> uint { return _cpuFrequency; } auto System::apuFrequency() const -> uint { return _apuFrequency; } @@ -34,10 +33,6 @@ auto System::runToSave() -> void { auto System::init() -> void { assert(interface != nullptr); - satellaview.init(); - superdisc.init(); - s21fx.init(); - icd2.init(); mcc.init(); nss.init(); @@ -55,16 +50,14 @@ auto System::init() -> void { msu1.init(); bsmemory.init(); - - device.connect(0, (Device::ID)settings.controllerPort1); - device.connect(1, (Device::ID)settings.controllerPort2); - device.connect(2, (Device::ID)settings.expansionPort); } auto System::term() -> void { } auto System::load() -> void { + bus.reset(); + interface->loadRequest(ID::SystemManifest, "manifest.bml", true); auto document = BML::unserialize(information.manifest); @@ -74,20 +67,9 @@ auto System::load() -> void { cartridge.load(); _region = cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL; - _expansionPort = (Device::ID)settings.expansionPort; _cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370; _apuFrequency = 24'606'720; - bus.reset(); - bus.map(); - - cpu.enable(); - ppu.enable(); - - if(expansionPort() == Device::ID::Satellaview) satellaview.load(); - if(expansionPort() == Device::ID::SuperDisc) superdisc.load(); - if(expansionPort() == Device::ID::S21FX) s21fx.load(); - if(cartridge.hasICD2()) icd2.load(); if(cartridge.hasMCC()) mcc.load(); if(cartridge.hasNSSDIP()) nss.load(); @@ -113,9 +95,7 @@ auto System::load() -> void { auto System::unload() -> void { if(!loaded()) return; - if(expansionPort() == Device::ID::Satellaview) satellaview.unload(); - if(expansionPort() == Device::ID::SuperDisc) superdisc.unload(); - if(expansionPort() == Device::ID::S21FX) s21fx.unload(); + peripherals.unload(); if(cartridge.hasICD2()) icd2.unload(); if(cartridge.hasMCC()) mcc.unload(); @@ -148,10 +128,6 @@ auto System::power() -> void { dsp.power(); ppu.power(); - if(expansionPort() == Device::ID::Satellaview) satellaview.power(); - if(expansionPort() == Device::ID::SuperDisc) superdisc.power(); - if(expansionPort() == Device::ID::S21FX) s21fx.power(); - if(cartridge.hasICD2()) icd2.power(); if(cartridge.hasMCC()) mcc.power(); if(cartridge.hasNSSDIP()) nss.power(); @@ -179,10 +155,6 @@ auto System::reset() -> void { dsp.reset(); ppu.reset(); - if(expansionPort() == Device::ID::Satellaview) satellaview.reset(); - if(expansionPort() == Device::ID::SuperDisc) superdisc.reset(); - if(expansionPort() == Device::ID::S21FX) s21fx.reset(); - if(cartridge.hasICD2()) icd2.reset(); if(cartridge.hasMCC()) mcc.reset(); if(cartridge.hasNSSDIP()) nss.reset(); @@ -212,13 +184,9 @@ auto System::reset() -> void { if(cartridge.hasSharpRTC()) cpu.coprocessors.append(&sharprtc); if(cartridge.hasSPC7110()) cpu.coprocessors.append(&spc7110); if(cartridge.hasMSU1()) cpu.coprocessors.append(&msu1); - if(expansionPort() == Device::ID::SuperDisc) cpu.coprocessors.append(&superdisc); - if(expansionPort() == Device::ID::S21FX) cpu.coprocessors.append(&s21fx); scheduler.reset(); - device.connect(0, (Device::ID)settings.controllerPort1); - device.connect(1, (Device::ID)settings.controllerPort2); - device.connect(2, (Device::ID)settings.expansionPort); + peripherals.reset(); } } diff --git a/higan/sfc/system/system.hpp b/higan/sfc/system/system.hpp index 1d2ce323..2de5837f 100644 --- a/higan/sfc/system/system.hpp +++ b/higan/sfc/system/system.hpp @@ -1,13 +1,12 @@ struct Interface; -#include "device.hpp" +#include "peripherals.hpp" struct System { enum class Region : bool { NTSC = 0, PAL = 1 }; auto loaded() const -> bool; auto region() const -> Region; - auto expansionPort() const -> Device::ID; auto cpuFrequency() const -> uint; auto apuFrequency() const -> uint; @@ -35,7 +34,6 @@ private: bool _loaded = false; Region _region = Region::NTSC; - Device::ID _expansionPort = Device::ID::None; uint _cpuFrequency = 0; uint _apuFrequency = 0; uint _serializeSize = 0; diff --git a/higan/target-tomoko/program/media.cpp b/higan/target-tomoko/program/media.cpp index 578070e3..870ad26c 100644 --- a/higan/target-tomoko/program/media.cpp +++ b/higan/target-tomoko/program/media.cpp @@ -20,10 +20,11 @@ auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Med mediaPaths(media.id) = location; folderPaths.append(location); + //note: the order of operations in this block of code is critical emulator = &interface; - connectDevices(); //(expansion port) devices must be connected prior to load + connectDevices(); emulator->load(media.id); - updateAudio(); //audio must be updated after load (audio frequency varies by region) + updateAudio(); emulator->power(); presentation->resizeViewport(); diff --git a/nall/run.hpp b/nall/run.hpp index eb4955e8..b12fd1fb 100644 --- a/nall/run.hpp +++ b/nall/run.hpp @@ -36,7 +36,9 @@ template inline auto execute(const string& name, P&&... p) -> str close(fd[0]); close(fd[1]); execvp(name, (char* const*)argv); - exit(0); + //this is called only if execvp fails: + //use _exit instead of exit, to avoid destroying key shared file descriptors + _exit(0); } else { close(fd[1]);