diff --git a/higan/GNUmakefile b/higan/GNUmakefile index 0d94ff51..fdef8008 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -2,7 +2,7 @@ build := performance include ../nall/GNUmakefile binary := application -target := tomoko +target := higan objects := libco emulator audio video resource flags += -I. -I.. diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 225de157..ada93f36 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 = "106.20"; + static const string Version = "106.21"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp index 447c43c2..bf05da6a 100644 --- a/higan/sfc/cartridge/load.cpp +++ b/higan/sfc/cartridge/load.cpp @@ -53,7 +53,7 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void { if(auto node = board["slot(type=SufamiTurbo)[0]"]) loadSufamiTurboA(node); if(auto node = board["slot(type=SufamiTurbo)[1]"]) loadSufamiTurboB(node); if(auto node = board["dip"]) loadDIP(node); - if(auto node = board["event"]) loadEvent(node); + if(auto node = board["processor(architecture=uPD78214)"]) loadEvent(node); if(auto node = board["processor(architecture=W65C816S)"]) loadSA1(node); if(auto node = board["processor(architecture=GSU)"]) loadSuperFX(node); if(auto node = board["processor(architecture=ARM6)"]) loadARMDSP(node); @@ -193,17 +193,13 @@ auto Cartridge::loadMCC(Markup::Node node) -> void { if(auto memory = mcu["memory(type=ROM,content=Program)"]) { loadMemory(mcc.rom, memory, File::Required); } + if(auto memory = mcu["memory(type=RAM,content=Download)"]) { + loadMemory(mcc.psram, memory, File::Optional); + } if(auto slot = mcu["slot(type=BSMemory)"]) { loadBSMemory(slot); } } - - if(auto memory = node["memory(type=RAM,content=Download)"]) { - loadMemory(mcc.ram, memory, File::Optional); - for(auto map : memory.find("map")) { - loadMap(map, mcc.ram); - } - } } //slot(type=BSMemory) @@ -256,6 +252,7 @@ auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { } } +//dip auto Cartridge::loadDIP(Markup::Node node) -> void { has.DIP = true; dip.value = platform->dipSettings(node); @@ -265,22 +262,34 @@ auto Cartridge::loadDIP(Markup::Node node) -> void { } } +//processor(architecture=uPD78214) auto Cartridge::loadEvent(Markup::Node node) -> void { - auto roms = node.find("rom"); - if(roms.size() != 4) return; - has.Event = true; + event.board = Event::Board::Unknown; + if(node["identifier"].text() == "Campus Challenge '92") event.board = Event::Board::CampusChallenge92; + if(node["identifier"].text() == "PowerFest '94") event.board = Event::Board::PowerFest94; - for(uint n : range(4)) loadMemory(event.rom[n], roms[n], File::Required); + for(auto map : node.find("map")) { + loadMap(map, {&Event::read, &event}, {&Event::write, &event}); + } - event.board = Event::Board::CampusChallenge92; - if(node.text() == "CC92") event.board = Event::Board::CampusChallenge92; - if(node.text() == "PF94") event.board = Event::Board::Powerfest94; - event.timer = node["timer"].natural(); - - for(auto leaf : node.find("map")) leaf.text() == "mcu" - ? loadMap(leaf, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}) - : loadMap(leaf, {&Event::read, &event}, {&Event::write, &event}); + if(auto mcu = node["mcu"]) { + for(auto map : mcu.find("map")) { + loadMap(map, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}); + } + if(auto memory = mcu["memory(type=ROM,content=Program)"]) { + loadMemory(event.rom[0], memory, File::Required); + } + if(auto memory = mcu["memory(type=ROM,content=Level-1)"]) { + loadMemory(event.rom[1], memory, File::Required); + } + if(auto memory = mcu["memory(type=ROM,content=Level-2)"]) { + loadMemory(event.rom[2], memory, File::Required); + } + if(auto memory = mcu["memory(type=ROM,content=Level-3)"]) { + loadMemory(event.rom[3], memory, File::Required); + } + } } //processor(architecture=W65C816S) diff --git a/higan/sfc/cartridge/save.cpp b/higan/sfc/cartridge/save.cpp index cadc7929..7c35173d 100644 --- a/higan/sfc/cartridge/save.cpp +++ b/higan/sfc/cartridge/save.cpp @@ -63,8 +63,10 @@ auto Cartridge::saveRAM(Markup::Node node) -> void { //processor(identifier=MCC) auto Cartridge::saveMCC(Markup::Node node) -> void { - if(auto memory = node["memory(type=RAM,content=Download)"]) { - saveMemory(mcc.ram, memory); + if(auto mcu = node["mcu"]) { + if(auto memory = mcu["memory(type=RAM,content=Download)"]) { + saveMemory(mcc.psram, memory); + } } } diff --git a/higan/sfc/coprocessor/event/event.cpp b/higan/sfc/coprocessor/event/event.cpp index 3de01a65..077dbe20 100644 --- a/higan/sfc/coprocessor/event/event.cpp +++ b/higan/sfc/coprocessor/event/event.cpp @@ -44,6 +44,11 @@ auto Event::power() -> void { rom[2].writeProtect(true); rom[3].writeProtect(true); + //DIP switches 0-3 control the time: 3 minutes + 0-15 extra minutes + timer = (3 + dip.value.bits(0,3)) * 60; //in seconds + //DIP switches 4-5 serve an unknown purpose + //DIP switches 6-7 are not connected + status = 0x00; select = 0x00; timerActive = false; @@ -66,7 +71,7 @@ auto Event::mcuRead(uint24 addr, uint8 data) -> uint8 { } } - if(board == Board::Powerfest94) { + if(board == Board::PowerFest94) { uint id = 0; if(select == 0x09) id = 1; if(select == 0x0c) id = 2; diff --git a/higan/sfc/coprocessor/event/event.hpp b/higan/sfc/coprocessor/event/event.hpp index 776f5c42..53c3f56c 100644 --- a/higan/sfc/coprocessor/event/event.hpp +++ b/higan/sfc/coprocessor/event/event.hpp @@ -1,6 +1,63 @@ -//SNES-EVENT board emulation: +//HLE of the NEC uPD78P214GC processor found on SNES-EVENT PCBs, used by: //* Campus Challenge '92 -//* Powerfest '94 +//* PowerFest '94 + +//The NEC uPD78214 family are 8-bit microprocessors containing: +//* UART/CSI serial interface +//* ALU (MUL, DIV, BCD) +//* interrupts (12 internal; 7 external; 2 priority levels) +//* 16384 x 8-bit ROM +//* 512 x 8-bit RAM +//* 4 x timer/counters + +//None of the SNES-EVENT games have had their uPD78214 firmware dumped. +//As such, our only option is very basic high-level emulation, provided here. + +/* Unverified memory maps: + +game + label: Campus Challenge '92 + board + memory type=RAM content=Save size=0x2000 volatile + map address=70-7d,f0-ff:0000-7fff mask=0x8000 + processor manufacturer=NEC architecture=uPD78214 + map address=c0,e0:0000 + mcu + map address=00-1f,80-9f:8000-ffff + memory type=ROM content=Program size=0x40000 label: Menu + memory type=ROM content=Level-1 size=0x80000 label: Super Mario World + memory type=ROM content=Level-2 size=0x80000 label: F-Zero + memory type=ROM content=Level-3 size=0x80000 label: Pilotwings + dip switches=8 + processor manufacturer=NEC architecture=uPD7725 identifier=DSP1 + map address=20-3f,a0-bf:8000-ffff mask=0x7fff + memory type=ROM content=Program size=0x1800 architecture=uPD7725 + memory type=ROM content=Data size=0x800 architecture=uPD7725 + memory type=RAM content=Data size=0x200 architecture=uPD7725 volatile + oscillator frequency=7600000 + +game + label: PowerFest '94 + board + memory type=RAM content=Save size=0x2000 volatile + map address=30-3f,b0-bf:6000-7fff mask=0xe000 + processor manufacturer=NEC architecture=uPD78214 + map address=10,20:6000 + mcu + map address=00-3f,80-bf:8000-ffff + map address=c0-ff:0000-ffff + memory type=ROM content=Program size=0x40000 label: Menu + memory type=ROM content=Level-1 size=0x80000 label: Super Mario Bros.: The Lost Levels + memory type=ROM content=Level-2 size=0x80000 label: Super Mario Kart + memory type=ROM content=Level-3 size=0x100000 label: Ken Griffey Jr. Presents: Major League Baseball + dip switches=8 + processor manufacturer=NEC architecture=uPD7725 identifier=DSP1 + map address=00-0f,80-8f:6000-7fff mask=0xfff + memory type=ROM content=Program size=0x1800 architecture=uPD7725 + memory type=ROM content=Data size=0x800 architecture=uPD7725 + memory type=RAM content=Data size=0x200 architecture=uPD7725 volatile + oscillator frequency=7600000 +*/ struct Event : Thread { //event.cpp @@ -18,9 +75,10 @@ struct Event : Thread { //serialization.cpp auto serialize(serializer&) -> void; +public: MappedRAM rom[4]; - enum class Board : uint { CampusChallenge92, Powerfest94 } board; + enum class Board : uint { Unknown, CampusChallenge92, PowerFest94 } board; uint timer; private: diff --git a/higan/sfc/coprocessor/mcc/mcc.cpp b/higan/sfc/coprocessor/mcc/mcc.cpp index 26ed783a..5d89a84d 100644 --- a/higan/sfc/coprocessor/mcc/mcc.cpp +++ b/higan/sfc/coprocessor/mcc/mcc.cpp @@ -7,124 +7,254 @@ MCC mcc; auto MCC::unload() -> void { rom.reset(); - ram.reset(); + psram.reset(); } auto MCC::power() -> void { rom.writeProtect(true); - ram.writeProtect(false); + psram.writeProtect(false); - for(auto n : range(16)) r[n] = 0x00; - r[0x07] = 0x80; - r[0x08] = 0x80; - commit(); + irq.flag = 0; + irq.enable = 0; + w.mapping = 1; + w.psramEnableLo = 1; + w.psramEnableHi = 0; + w.psramMapping = 3; + w.romEnableLo = 1; + w.romEnableHi = 1; + w.exEnableLo = 1; + w.exEnableHi = 0; + w.exMapping = 1; + w.bsWritable = 0; + w.unknown = 0; + x.enable = 0; + x.value = 0b0011'1111; + memory::copy(&r, &w, sizeof(Registers)); } -auto MCC::memoryAccess(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8 { - addr = bus.mirror(addr, memory.size()); - if(!write) { - return memory.read(addr, data); - } else { - memory.write(addr, data); - } -} - -//map address=00-3f,80-bf:8000-ffff mask=0x408000 -//map address=40-7d,c0-ff:0000-ffff -auto MCC::mcuAccess(bool write, uint24 addr, uint8 data) -> uint8 { - if(addr < 0x400000) { - //note: manifest maps 00-3f,80-bf:8000-ffff mask=0x408000 => 00-3f:0000-ffff - //the intention is consistency in pre-decoding as much as possible - //however, the MCC code is intended to be rewritten; and is too convoluted - //so for right now, I'm simply transforming it back to its original state - //this is very wasteful; but will be addressed once things are rewritten - addr = ((addr & 0x200000) << 2) | ((addr & 0x1f8000) << 1) | 0x8000 | (addr & 0x7fff); - } - - if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff - if(r07 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memoryAccess(write, rom, addr, data); +auto MCC::read(uint24 address, uint8 data) -> uint8 { + if((address & 0xf0f000) == 0x005000) { //$00-0f:5000-5fff + uint4 index = address.bits(16,19); + if(x.enable) return x.value.bit(index & 7); + switch(index) { + case 0: return irq.flag << 7; + case 1: return irq.enable << 7; + case 2: return r.mapping << 7; + case 3: return r.psramEnableLo << 7; + case 4: return r.psramEnableHi << 7; + case 5: return r.psramMapping.bit(0) << 7; + case 6: return r.psramMapping.bit(1) << 7; + case 7: return r.romEnableLo << 7; + case 8: return r.romEnableHi << 7; + case 9: return r.exEnableLo << 7; + case 10: return r.exEnableHi << 7; + case 11: return r.exMapping << 7; + case 12: return r.bsWritable << 7; + case 13: return r.unknown << 7; + case 14: return 0; //commit (always zero) + case 15: return 0; //x.enable (always zero) } } - if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff - if(r08 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memoryAccess(write, rom, addr, data); - } - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - if(r05 == 0) return memoryAccess(write, ram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x500000) { //$50-5f:0000-ffff - if(r06 == 0) return memoryAccess(write, ram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff - if(r03 == 1) return memoryAccess(write, ram, addr & 0x0fffff, data); - } - - if((addr & 0xf80000) == 0x700000) { //$70-77:0000-ffff - return memoryAccess(write, ram, addr & 0x07ffff, data); - } - - if(((addr & 0x408000) == 0x008000) //$00-3f,80-bf:8000-ffff - || ((addr & 0x400000) == 0x400000) //$40-7f,c0-ff:0000-ffff - ) { - if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); - Memory& memory = (r01 == 0 ? (Memory&)bsmemory : (Memory&)ram); - return memoryAccess(write, memory, addr & 0x7fffff, data); - } - - return 0x00; -} - -auto MCC::mcuRead(uint24 addr, uint8 data) -> uint8 { - return mcuAccess(false, addr, data); -} - -auto MCC::mcuWrite(uint24 addr, uint8 data) -> void { - mcuAccess(true, addr, data); -} - -auto MCC::read(uint24 addr, uint8 data) -> uint8 { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - return r[n]; - } - return data; } -auto MCC::write(uint24 addr, uint8 data) -> void { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - r[n] = data; - if(n == 0x0e && data & 0x80) commit(); - return; +auto MCC::write(uint24 address, uint8 data) -> void { + if((address & 0xf0f000) == 0x005000) { //$00-0f:5000-5fff + uint4 index = address.bits(16,19); + if(x.enable) return x.value.bit(index & 7) = data.bit(7), void(); + switch(index) { + case 1: irq.enable = data.bit(7); break; + case 2: w.mapping = data.bit(7); break; + case 3: w.psramEnableLo = data.bit(7); break; + case 4: w.psramEnableHi = data.bit(7); break; + case 5: w.psramMapping.bit(0) = data.bit(7); break; + case 6: w.psramMapping.bit(1) = data.bit(7); break; + case 7: w.romEnableLo = data.bit(7); break; + case 8: w.romEnableHi = data.bit(7); break; + case 9: w.exEnableLo = data.bit(7); break; + case 10: w.exEnableHi = data.bit(7); break; + case 11: w.exMapping = data.bit(7); break; + case 12: w.bsWritable = data.bit(7); break; + case 13: w.unknown = data.bit(7); break; + case 14: if(data.bit(7)) memory::copy(&r, &w, sizeof(Registers)); break; + case 15: x.enable = data.bit(7); break; + } } } -auto MCC::commit() -> void { - r00 = r[0x00] & 0x80; - r01 = r[0x01] & 0x80; - r02 = r[0x02] & 0x80; - r03 = r[0x03] & 0x80; - r04 = r[0x04] & 0x80; - r05 = r[0x05] & 0x80; - r06 = r[0x06] & 0x80; - r07 = r[0x07] & 0x80; - r08 = r[0x08] & 0x80; - r09 = r[0x09] & 0x80; - r0a = r[0x0a] & 0x80; - r0b = r[0x0b] & 0x80; - r0c = r[0x0c] & 0x80; - r0d = r[0x0d] & 0x80; - r0e = r[0x0e] & 0x80; - r0f = r[0x0f] & 0x80; +auto MCC::mcuRead(uint24 address, uint8 data) -> uint8 { + return mcuAccess(0, address, data); +} + +auto MCC::mcuWrite(uint24 address, uint8 data) -> void { + return mcuAccess(1, address, data), void(); +} + +auto MCC::mcuAccess(bool mode, uint24 address, uint8 data) -> uint8 { + //[[ROM]] + + if(r.romEnableLo) { + if((address & 0xc08000) == 0x008000) { //00-3f:8000-ffff + return romAccess(mode, (address & 0x3f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(r.romEnableHi) { + if((address & 0xc08000) == 0x808000) { //80-bf:8000-ffff + return romAccess(mode, (address & 0x3f0000) >> 1 | (address & 0x7fff), data); + } + } + + //[[PSRAM]] + + if(r.psramEnableLo && r.mapping == 0) { + if(((address & 0xf08000) == 0x008000 && r.psramMapping == 0) //00-0f:8000-ffff + || ((address & 0xf08000) == 0x208000 && r.psramMapping == 1) //20-2f:8000-ffff + || ((address & 0xf00000) == 0x400000 && r.psramMapping == 2) //40-4f:0000-ffff + || ((address & 0xf00000) == 0x600000 && r.psramMapping == 3) //60-6f:0000-ffff + ) { + return psramAccess(mode, (address & 0x0f0000) >> 1 | (address & 0x7fff), data); + } + + if((address & 0xf08000) == 0x700000) { //70-7d:0000-7fff + return psramAccess(mode, (address & 0x0f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(r.psramEnableHi && r.mapping == 0) { + if(((address & 0xf08000) == 0x808000 && r.psramMapping == 0) //80-8f:8000-ffff + || ((address & 0xf08000) == 0xa08000 && r.psramMapping == 1) //a0-af:8000-ffff + || ((address & 0xf00000) == 0xc00000 && r.psramMapping == 2) //c0-cf:0000-ffff + || ((address & 0xf00000) == 0xe00000 && r.psramMapping == 3) //e0-ef:0000-ffff + ) { + return psramAccess(mode, (address & 0x0f0000) >> 1 | (address & 0x7fff), data); + } + + if((address & 0xf08000) == 0xf00000) { //f0-ff:0000-7fff + return psramAccess(mode, (address & 0x0f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(r.psramEnableLo && r.mapping == 1) { + if(((address & 0xf88000) == 0x008000 && r.psramMapping == 0) //00-07:8000-ffff + || ((address & 0xf88000) == 0x108000 && r.psramMapping == 1) //10-17:8000-ffff + || ((address & 0xf88000) == 0x208000 && r.psramMapping == 2) //20-27:8000-ffff + || ((address & 0xf88000) == 0x308000 && r.psramMapping == 3) //30-37:8000-ffff + || ((address & 0xf80000) == 0x400000 && r.psramMapping == 0) //40-47:0000-ffff + || ((address & 0xf80000) == 0x500000 && r.psramMapping == 1) //50-57:0000-ffff + || ((address & 0xf80000) == 0x600000 && r.psramMapping == 2) //60-67:0000-ffff + || ((address & 0xf80000) == 0x700000 && r.psramMapping == 3) //70-77:0000-ffff + ) { + return psramAccess(mode, address & 0x07ffff, data); + } + + if((address & 0xe0e000) == 0x206000) { //20-3f:6000-7fff + return psramAccess(mode, (address & 0x3f0000) >> 3 | (address & 0x1fff), data); + } + } + + if(r.psramEnableHi && r.mapping == 1) { + if(((address & 0xf88000) == 0x808000 && r.psramMapping == 0) //80-87:8000-ffff + || ((address & 0xf88000) == 0x908000 && r.psramMapping == 1) //90-97:8000-ffff + || ((address & 0xf88000) == 0xa08000 && r.psramMapping == 2) //a0-a7:8000-ffff + || ((address & 0xf88000) == 0xb08000 && r.psramMapping == 3) //b0-b7:8000-ffff + || ((address & 0xf80000) == 0xc00000 && r.psramMapping == 0) //c0-c7:0000-ffff + || ((address & 0xf80000) == 0xd00000 && r.psramMapping == 1) //d0-d7:0000-ffff + || ((address & 0xf80000) == 0xe00000 && r.psramMapping == 2) //e0-e7:0000-ffff + || ((address & 0xf80000) == 0xf00000 && r.psramMapping == 3) //f0-f7:0000-ffff + ) { + return psramAccess(mode, address & 0x07ffff, data); + } + + if((address & 0xe0e000) == 0xa06000) { //a0-bf:6000-7fff + return psramAccess(mode, (address & 0x3f0000) >> 3 | (address & 0x1fff), data); + } + } + + //[[EXMEMORY]] + + if(r.exEnableLo && r.mapping == 0) { + if(((address & 0xe08000) == 0x008000 && r.exMapping == 0) //00-1f:8000-ffff + || ((address & 0xe00000) == 0x400000 && r.exMapping == 1) //40-5f:0000-ffff + ) { + return exAccess(mode, (address & 0x1f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(r.exEnableLo && r.mapping == 1) { + if(((address & 0xf08000) == 0x008000 && r.exMapping == 0) //00-0f:8000-ffff + || ((address & 0xf08000) == 0x208000 && r.exMapping == 1) //20-2f:8000-ffff + || ((address & 0xf00000) == 0x400000 && r.exMapping == 0) //40-4f:0000-ffff + || ((address & 0xf00000) == 0x600000 && r.exMapping == 1) //60-6f:0000-ffff + ) { + return exAccess(mode, address & 0x0fffff, data); + } + } + + if(r.exEnableHi && r.mapping == 0) { + if(((address & 0xe08000) == 0x808000 && r.exMapping == 0) //80-9f:8000-ffff + || ((address & 0xe00000) == 0xc00000 && r.exMapping == 1) //c0-df:0000-ffff + ) { + return exAccess(mode, (address & 0x1f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(r.exEnableHi && r.mapping == 1) { + if(((address & 0xf08000) == 0x808000 && r.exMapping == 0) //80-8f:8000-ffff + || ((address & 0xf08000) == 0xa08000 && r.exMapping == 1) //a0-af:8000-ffff + || ((address & 0xf00000) == 0xc00000 && r.exMapping == 0) //c0-cf:0000-ffff + || ((address & 0xf00000) == 0xe00000 && r.exMapping == 1) //e0-ef:0000-ffff + ) { + return exAccess(mode, address & 0x0fffff, data); + } + } + + //[[BSMEMORY]] + + if(bsmemory.memory.size() && r.mapping == 0) { + if(((address & 0x408000) == 0x008000) //00-3f,80-bf:8000-ffff + || ((address & 0xc00000) == 0x400000) //40-7d,c0-ff:0000-ffff + ) { + return bsAccess(mode, (address & 0x3f0000) >> 1 | (address & 0x7fff), data); + } + } + + if(bsmemory.memory.size() && r.mapping == 1) { + if(((address & 0x408000) == 0x008000) //00-3f,80-bf:8000-ffff + || ((address & 0xc00000) == 0x400000) //40-7d,c0-ff:0000-ffff + ) { + return bsAccess(mode, address & 0x3fffff, data); + } + } + + return data; +} + +auto MCC::romAccess(bool mode, uint24 address, uint8 data) -> uint8 { + address = bus.mirror(address, rom.size()); + if(mode == 0) return rom.read(address); + return data; +} + +//size: 0x80000 +auto MCC::psramAccess(bool mode, uint24 address, uint8 data) -> uint8 { + address = bus.mirror(address, psram.size()); + if(mode == 0) return psram.read(address); + return psram.write(address, data), data; +} + +//size: 0x100000 (?) +auto MCC::exAccess(bool mode, uint24 address, uint8 data) -> uint8 { + //not physically present on BSC-1A5B9P-01 + return data; +} + +//size: 0x100000, 0x200000, 0x400000 +auto MCC::bsAccess(bool mode, uint24 address, uint8 data) -> uint8 { + address = bus.mirror(address, bsmemory.memory.size()); + if(mode == 0) return bsmemory.memory.read(address); + return bsmemory.memory.write(address, data), data; } } diff --git a/higan/sfc/coprocessor/mcc/mcc.hpp b/higan/sfc/coprocessor/mcc/mcc.hpp index 2f9a4ca2..eba1c7b0 100644 --- a/higan/sfc/coprocessor/mcc/mcc.hpp +++ b/higan/sfc/coprocessor/mcc/mcc.hpp @@ -1,31 +1,55 @@ -//the MCC is the custom logic chip inside the BS-X Satellaview cartridge +//MCC - Memory Controller Chip +//Custom logic chip inside the BS-X Satellaview base cartridge struct MCC { MappedRAM rom; - MappedRAM ram; + MappedRAM psram; + //mcc.cpp auto unload() -> void; auto power() -> void; - auto memoryAccess(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8; - auto mcuAccess(bool write, uint24 addr, uint8 data) -> uint8; + auto read(uint24 address, uint8 data) -> uint8; + auto write(uint24 address, uint8 data) -> void; - auto mcuRead(uint24 addr, uint8 data) -> uint8; - auto mcuWrite(uint24 addr, uint8 data) -> void; + auto mcuRead(uint24 address, uint8 data) -> uint8; + auto mcuWrite(uint24 address, uint8 data) -> void; - auto read(uint24 addr, uint8 data) -> uint8; - auto write(uint24 addr, uint8 data) -> void; - - auto commit() -> void; + auto mcuAccess(bool mode, uint24 address, uint8 data) -> uint8; + auto romAccess(bool mode, uint24 address, uint8 data) -> uint8; + auto psramAccess(bool mode, uint24 address, uint8 data) -> uint8; + auto exAccess(bool mode, uint24 address, uint8 data) -> uint8; + auto bsAccess(bool mode, uint24 address, uint8 data) -> uint8; + //serialization.cpp auto serialize(serializer&) -> void; private: - uint8 r[16]; - bool r00, r01, r02, r03; - bool r04, r05, r06, r07; - bool r08, r09, r0a, r0b; - bool r0c, r0d, r0e, r0f; + struct IRQ { + uint1 flag; //bit 0 + uint1 enable; //bit 1 + } irq; + + struct Registers { + uint1 mapping; //bit 2 (0 = ignore A15; 1 = use A15) + uint1 psramEnableLo; //bit 3 + uint1 psramEnableHi; //bit 4 + uint2 psramMapping; //bits 5-6 + uint1 romEnableLo; //bit 7 + uint1 romEnableHi; //bit 8 + uint1 exEnableLo; //bit 9 + uint1 exEnableHi; //bit 10 + uint1 exMapping; //bit 11 + uint1 bsWritable; //bit 12 + uint1 unknown; //bit 13 + } r, w; + + //bit 14 (commit) + + struct ExtendedRegisters { + uint1 enable; //bit 15 + uint8 value; //bits 24-31 + } x; }; extern MCC mcc; diff --git a/higan/sfc/coprocessor/mcc/serialization.cpp b/higan/sfc/coprocessor/mcc/serialization.cpp index 4558f4d3..117738cf 100644 --- a/higan/sfc/coprocessor/mcc/serialization.cpp +++ b/higan/sfc/coprocessor/mcc/serialization.cpp @@ -1,3 +1,29 @@ auto MCC::serialize(serializer& s) -> void { - s.array(ram.data(), ram.size()); + s.array(psram.data(), psram.size()); + s.integer(irq.flag); + s.integer(irq.enable); + s.integer(r.mapping); + s.integer(r.psramEnableLo); + s.integer(r.psramEnableHi); + s.integer(r.psramMapping); + s.integer(r.romEnableLo); + s.integer(r.romEnableHi); + s.integer(r.exEnableLo); + s.integer(r.exEnableHi); + s.integer(r.exMapping); + s.integer(r.bsWritable); + s.integer(r.unknown); + s.integer(w.mapping); + s.integer(w.psramEnableLo); + s.integer(w.psramEnableHi); + s.integer(w.psramMapping); + s.integer(w.romEnableLo); + s.integer(w.romEnableHi); + s.integer(w.exEnableLo); + s.integer(w.exEnableHi); + s.integer(w.exMapping); + s.integer(w.bsWritable); + s.integer(w.unknown); + s.integer(x.enable); + s.integer(x.value); } diff --git a/higan/systems/Super Famicom.sys/boards.bml b/higan/systems/Super Famicom.sys/boards.bml index 400a5979..ce89f2f7 100644 --- a/higan/systems/Super Famicom.sys/boards.bml +++ b/higan/systems/Super Famicom.sys/boards.bml @@ -1,10 +1,10 @@ database - revision: 2018-05-12 + revision: 2018-05-16 //Boards (Production) database - revision: 2018-05-08 + revision: 2018-05-16 board: BANDAI-PT-923 memory type=ROM content=Program @@ -20,6 +20,19 @@ board: BANDAI-PT-923 ram map address=70-7d,f0-ff:0000-ffff +board: BSC-1A5B9P-01 + memory type=RAM content=Save + map address=10-17:5000-5fff mask=0xf000 + processor identifier=MCC + map address=00-0f:5000-5fff + mcu + map address=00-3f,80-bf:8000-ffff + map address=40-7d,c0-ff:0000-ffff + map address=20-3f,a0-bf:6000-7fff + memory type=ROM content=Program + memory type=RAM content=Download + slot type=BSMemory + board: BSC-1A5M-02 memory type=ROM content=Program map address=00-1f:8000-ffff mask=0x8000 base=0x000000 @@ -519,15 +532,15 @@ board: SHVC-LDH3C-01 memory type=RTC content=Time manufacturer=Epson board: SHVC-LN3B-01 + memory type=RAM content=Save + map address=00-3f,80-bf:6000-7fff mask=0xe000 + map address=70-73:0000-ffff processor identifier=SDD1 map address=00-3f,80-bf:4800-480f mcu map address=00-3f,80-bf:8000-ffff map address=c0-ff:0000-ffff memory type=ROM content=Program - memory type=RAM content=Save - map address=00-3f,80-bf:6000-7fff mask=0xe000 - map address=70-73:0000-ffff board: SHVC-SGB2-01 memory type=ROM content=Program @@ -552,7 +565,7 @@ board: SHVC-YJ0N-01 //Boards (Generic) database - revision: 2018-05-12 + revision: 2018-05-16 board: ARM-LOROM-RAM memory type=ROM content=Program @@ -590,16 +603,16 @@ board: BS-LOROM-RAM board: BS-MCC-RAM memory type=RAM content=Save - map address=10-1f:5000-5fff mask=0xf000 + map address=10-17:5000-5fff mask=0xf000 processor identifier=MCC - map address=00-0f:5000 + map address=00-0f:5000-5fff mcu - map address=00-3f,80-bf:8000-ffff mask=0x408000 + map address=00-3f,80-bf:8000-ffff map address=40-7d,c0-ff:0000-ffff + map address=20-3f,a0-bf:6000-7fff memory type=ROM content=Program + memory type=RAM content=Download slot type=BSMemory - memory type=RAM content=Download - map address=00-3f,80-bf:6000-7fff mask=0xe000 board: BS-SA1-RAM processor architecture=W65C816S diff --git a/higan/target-tomoko/GNUmakefile b/higan/target-higan/GNUmakefile similarity index 96% rename from higan/target-tomoko/GNUmakefile rename to higan/target-higan/GNUmakefile index 4f96df68..ed80b31b 100644 --- a/higan/target-tomoko/GNUmakefile +++ b/higan/target-higan/GNUmakefile @@ -11,7 +11,7 @@ include gba/GNUmakefile include ws/GNUmakefile include processor/GNUmakefile -ui_objects := ui-tomoko ui-program ui-configuration ui-input +ui_objects := ui-higan ui-program ui-configuration ui-input ui_objects += ui-settings ui-tools ui-presentation ui_objects += ruby hiro ui_objects += $(if $(call streq,$(platform),windows),ui-resource) @@ -53,7 +53,7 @@ obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/) obj/hiro.o: ../hiro/hiro.cpp $(call rwildcard,../hiro/) $(compiler) $(hiroflags) -c $< -o $@ -obj/ui-tomoko.o: $(ui)/tomoko.cpp $(call rwildcard,$(ui)/) +obj/ui-higan.o: $(ui)/higan.cpp $(call rwildcard,$(ui)/) obj/ui-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/) obj/ui-configuration.o: $(ui)/configuration/configuration.cpp $(call rwildcard,$(ui)/) obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/) diff --git a/higan/target-tomoko/configuration/configuration.cpp b/higan/target-higan/configuration/configuration.cpp similarity index 98% rename from higan/target-tomoko/configuration/configuration.cpp rename to higan/target-higan/configuration/configuration.cpp index e67efc1a..743bae2e 100644 --- a/higan/target-tomoko/configuration/configuration.cpp +++ b/higan/target-higan/configuration/configuration.cpp @@ -1,4 +1,4 @@ -#include "../tomoko.hpp" +#include "../higan.hpp" Settings settings; Settings::Settings() { diff --git a/higan/target-tomoko/configuration/configuration.hpp b/higan/target-higan/configuration/configuration.hpp similarity index 100% rename from higan/target-tomoko/configuration/configuration.hpp rename to higan/target-higan/configuration/configuration.hpp diff --git a/higan/target-tomoko/tomoko.cpp b/higan/target-higan/higan.cpp similarity index 96% rename from higan/target-tomoko/tomoko.cpp rename to higan/target-higan/higan.cpp index 8eaecdec..f0e82b51 100644 --- a/higan/target-tomoko/tomoko.cpp +++ b/higan/target-higan/higan.cpp @@ -1,4 +1,4 @@ -#include "tomoko.hpp" +#include "higan.hpp" unique_pointer