Update to v106r21 release.

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.
This commit is contained in:
Tim Allen 2018-05-17 13:37:29 +10:00
parent 210306e661
commit 8bbbc5e737
47 changed files with 460 additions and 180 deletions

View File

@ -2,7 +2,7 @@ build := performance
include ../nall/GNUmakefile
binary := application
target := tomoko
target := higan
objects := libco emulator audio video resource
flags += -I. -I..

View File

@ -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/";

View File

@ -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)

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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)/)

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
Settings settings;
Settings::Settings() {

View File

@ -1,4 +1,4 @@
#include "tomoko.hpp"
#include "higan.hpp"
unique_pointer<Video> video;
unique_pointer<Audio> audio;
unique_pointer<Input> input;

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
#include "hotkeys.cpp"
unique_pointer<InputManager> inputManager;

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
#include "about.cpp"
unique_pointer<AboutWindow> aboutWindow;
unique_pointer<Presentation> presentation;

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
#include <fc/interface/interface.hpp>
#include <sfc/interface/interface.hpp>
#include <ms/interface/interface.hpp>

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
#include "system-properties.cpp"
unique_pointer<SystemProperties> systemProperties;

View File

@ -7,7 +7,6 @@ SystemProperties::SystemProperties() {
systemOption.append(ComboButtonItem().setText(emulator->information.name));
}
loadLabel.setAlignment(1.0).setText("Load:");
loadEdit.setEditable(false);
loadBrowse.setText("Browse ...").onActivate([&] {
string filters = "Games|";
for(auto& emulator : program->emulators) {
@ -22,6 +21,20 @@ SystemProperties::SystemProperties() {
.setFilters(filters)
.openFolder()) {
loadEdit.setText(location);
//change system option to match the media selected
auto suffix = Location::suffix(location).trimLeft(".", 1L);
for(auto& emulator : program->emulators) {
for(auto& media : emulator->media) {
if(media.type == suffix) {
for(auto item : systemOption.items()) {
if(item.text() == emulator->information.name) {
item.setSelected();
return;
}
}
}
}
}
}
});
aliasLabel.setAlignment(1.0).setText("Alias:");

View File

@ -1,4 +1,4 @@
#include "../tomoko.hpp"
#include "../higan.hpp"
#include "cheat-database.cpp"
unique_pointer<CheatDatabase> cheatDatabase;

View File

@ -43,18 +43,17 @@ auto pApplication::initialize() -> void {
#endif
//set WM_CLASS to Application::name()
if(Application::state.name) gdk_set_program_class(Application::state.name);
auto name = Application::state.name ? Application::state.name : string{"hiro"};
gdk_set_program_class(name);
#if 1
int argc = 1;
char* argv[] = {new char[5], nullptr};
strcpy(argv[0], "hiro");
char* argv[] = {name.get(), nullptr};
#else
//--g-fatal-warnings will force a trap on Gtk-CRITICAL errors
//this allows gdb to perform a backtrace to find an error's origin point
int argc = 2;
char* argv[] = {new char[5], new char[19], nullptr};
strcpy(argv[0], "hiro");
char* argv[] = {name.get(), new char[19], nullptr};
strcpy(argv[1], "--g-fatal-warnings");
#endif
char** argvp = argv;

View File

@ -41,9 +41,10 @@ auto pApplication::syncX() -> void {
auto pApplication::initialize() -> void {
display = XOpenDisplay(0);
static int argc = 1;
static char* argv[] = {new char[8], nullptr};
strcpy(argv[0], "hiro");
auto name = Application::state.name ? Application::state.name : string{"hiro"};
int argc = 1;
char* argv[] = {name.get(), nullptr};
char** argvp = argv;
qtApplication = new QApplication(argc, argvp);

View File

@ -44,12 +44,12 @@ auto Icarus::famicomImport(vector<uint8_t>& buffer, string location) -> string {
write({target, "ines.rom"}, &buffer[offset], size);
offset += size;
}
if(auto program = document["game/memory(type=ROM,content=Program)"]) {
if(auto program = document["game/board/memory(type=ROM,content=Program)"]) {
uint size = program["size"].natural();
write({target, "program.rom"}, &buffer[offset], size);
offset += size;
}
if(auto character = document["game/memory(type=ROM,content=Character)"]) {
if(auto character = document["game/board/memory(type=ROM,content=Character)"]) {
uint size = character["size"].natural();
write({target, "character.rom"}, &buffer[offset], size);
offset += size;

View File

@ -46,12 +46,12 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, string location) -> str
auto name = string{rom["architecture"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase();
auto size = rom["size"].natural();
if(size > buffer.size() - offset) {
auto name = string{rom["identifier"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase();
auto location = locate({"firmware/", name});
auto firmware = string{rom["identifier"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase();
auto location = locate({"firmware/", firmware});
if(location && file::size(location) == size) {
write({target, name}, file::read(location));
} else {
missingFiles.append(name);
missingFiles.append(firmware);
}
continue;
}