From 8bbbc5e737873da3ecd84db294b99d11db78c980 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 17 May 2018 13:37:29 +1000 Subject: [PATCH] Update to v106r21 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: Changelog: - higan: target-tomoko has been renamed to target-higan - Super Famicom: event has been renamed to processor(architecture=uPD78214) - Super Famicom: SNES-EVENT supported once more; under board IDs EVENT-CC92 and EVENT-PF94 - Super Famicom: SNES-EVENT preliminarily set up to use DIP switch settings ala the Nintendo Super System (incomplete) - Super Famicom: MCC PSRAM moved inside the MCU, as it is remappable - Super Famicom: MCC emulation rewritten from scratch; it is now vastly more accurate than before - Super Famicom: added BSC-1A5B9P-01 board definition to database; corrected BS-MCC-RAM board definition - Super Famicom: moved SHVC-LN3B-01 RAM outside of processor(identifier=SDD1) - higan: when selecting a default game to load for a new system entry, it will change the system option to match the media type - higan: the load text box on the system entry window is now editable; can be used to erase entries - icarus: fixed bug in Famicom importing - icarus: importing unappended SNES coprocessor firmware will now rename the firmware properly - hiro/GTK,Qt: WM_CLASS is now set correctly in `argv[0]`, so applications should show “higan”, “icarus” instead of “hiro” now Note: if you wish to run the BS-X town cartridge, the database currently lists the download RAM as type “PSRAM”. This needs to be changed to “RAM” in order to load properly. Otherwise, the emulator will bomb out on the load window, because BSC-1A5B9P-01 expects PSRAM to always be present, but it won't find it with the wrong memory type. I'll correct this in the database in a later release. For now, you can copy the game portion of the manifest to a new manifest.bml file and drop it into the gamepak folder until I fix the database. --- higan/GNUmakefile | 2 +- higan/emulator/emulator.hpp | 2 +- higan/sfc/cartridge/load.cpp | 49 +-- higan/sfc/cartridge/save.cpp | 6 +- higan/sfc/coprocessor/event/event.cpp | 7 +- higan/sfc/coprocessor/event/event.hpp | 64 +++- higan/sfc/coprocessor/mcc/mcc.cpp | 334 ++++++++++++------ higan/sfc/coprocessor/mcc/mcc.hpp | 54 ++- higan/sfc/coprocessor/mcc/serialization.cpp | 28 +- higan/systems/Super Famicom.sys/boards.bml | 35 +- .../GNUmakefile | 4 +- .../configuration/configuration.cpp | 2 +- .../configuration/configuration.hpp | 0 .../tomoko.cpp => target-higan/higan.cpp} | 2 +- .../tomoko.hpp => target-higan/higan.hpp} | 0 .../input/hotkeys.cpp | 0 .../input/input.cpp | 2 +- .../input/input.hpp | 0 .../presentation/about.cpp | 0 .../presentation/presentation.cpp | 2 +- .../presentation/presentation.hpp | 0 .../program/interface.cpp | 0 .../program/medium.cpp | 0 .../program/program.cpp | 2 +- .../program/program.hpp | 0 .../program/state.cpp | 0 .../program/utility.cpp | 0 .../settings/advanced.cpp | 0 .../settings/audio.cpp | 0 .../settings/hotkeys.cpp | 0 .../settings/input.cpp | 0 .../settings/settings.cpp | 2 +- .../settings/settings.hpp | 0 .../settings/system-properties.cpp | 15 +- .../settings/systems.cpp | 0 .../settings/video.cpp | 0 .../tools/cheat-database.cpp | 0 .../tools/cheat-editor.cpp | 0 .../tools/game-notes.cpp | 0 .../tools/manifest-viewer.cpp | 0 .../tools/state-manager.cpp | 0 .../tools/tools.cpp | 2 +- .../tools/tools.hpp | 0 hiro/gtk/application.cpp | 9 +- hiro/qt/application.cpp | 7 +- icarus/core/famicom.cpp | 4 +- icarus/core/super-famicom.cpp | 6 +- 47 files changed, 460 insertions(+), 180 deletions(-) rename higan/{target-tomoko => target-higan}/GNUmakefile (96%) rename higan/{target-tomoko => target-higan}/configuration/configuration.cpp (98%) rename higan/{target-tomoko => target-higan}/configuration/configuration.hpp (100%) rename higan/{target-tomoko/tomoko.cpp => target-higan/higan.cpp} (96%) rename higan/{target-tomoko/tomoko.hpp => target-higan/higan.hpp} (100%) rename higan/{target-tomoko => target-higan}/input/hotkeys.cpp (100%) rename higan/{target-tomoko => target-higan}/input/input.cpp (99%) rename higan/{target-tomoko => target-higan}/input/input.hpp (100%) rename higan/{target-tomoko => target-higan}/presentation/about.cpp (100%) rename higan/{target-tomoko => target-higan}/presentation/presentation.cpp (99%) rename higan/{target-tomoko => target-higan}/presentation/presentation.hpp (100%) rename higan/{target-tomoko => target-higan}/program/interface.cpp (100%) rename higan/{target-tomoko => target-higan}/program/medium.cpp (100%) rename higan/{target-tomoko => target-higan}/program/program.cpp (99%) rename higan/{target-tomoko => target-higan}/program/program.hpp (100%) rename higan/{target-tomoko => target-higan}/program/state.cpp (100%) rename higan/{target-tomoko => target-higan}/program/utility.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/advanced.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/audio.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/hotkeys.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/input.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/settings.cpp (97%) rename higan/{target-tomoko => target-higan}/settings/settings.hpp (100%) rename higan/{target-tomoko => target-higan}/settings/system-properties.cpp (78%) rename higan/{target-tomoko => target-higan}/settings/systems.cpp (100%) rename higan/{target-tomoko => target-higan}/settings/video.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/cheat-database.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/cheat-editor.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/game-notes.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/manifest-viewer.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/state-manager.cpp (100%) rename higan/{target-tomoko => target-higan}/tools/tools.cpp (96%) rename higan/{target-tomoko => target-higan}/tools/tools.hpp (100%) 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