mirror of https://github.com/bsnes-emu/bsnes.git
Update to v089r02 release.
(r01 was not posted to the WIP thread) byuu says: r01 changelog: - major improvements to SPC7110 MCU (memory controller unit) - revised SPC7110 memory map to reflect aforementioned improvements - added "Toggle Tracer" hotkey to target-ethos (only works for SFC so far, I plan to use this as a lightweight laevateinn for FEoEZ) r02 changelog: - quick fix: SRAM is mapped to 00-3f|80-bf:6000-7fff - quick fix: $4830.d7 is SRAM chip enable, not SRAM write enable. Reads return 0x00 when this bit is clear
This commit is contained in:
parent
73ebe093b8
commit
a1e4c67a05
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "089";
|
static const char Version[] = "089.02";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,10 @@ struct Interface {
|
||||||
virtual void cheatSet(const lstring& = lstring{}) {}
|
virtual void cheatSet(const lstring& = lstring{}) {}
|
||||||
|
|
||||||
//utility functions
|
//utility functions
|
||||||
virtual void updatePalette() {}
|
virtual void paletteUpdate() {}
|
||||||
|
|
||||||
|
//debugger functions
|
||||||
|
virtual bool tracerEnable(bool) { return false; }
|
||||||
|
|
||||||
Interface() : bind(nullptr) {}
|
Interface() : bind(nullptr) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,7 +76,7 @@ void Interface::cheatSet(const lstring &list) {
|
||||||
cheat.synchronize();
|
cheat.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::updatePalette() {
|
void Interface::paletteUpdate() {
|
||||||
video.generate_palette();
|
video.generate_palette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct Interface : Emulator::Interface {
|
||||||
|
|
||||||
void cheatSet(const lstring&);
|
void cheatSet(const lstring&);
|
||||||
|
|
||||||
void updatePalette();
|
void paletteUpdate();
|
||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ void Interface::cheatSet(const lstring &list) {
|
||||||
cheat.synchronize();
|
cheat.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::updatePalette() {
|
void Interface::paletteUpdate() {
|
||||||
video.generate_palette();
|
video.generate_palette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct Interface : Emulator::Interface {
|
||||||
|
|
||||||
void cheatSet(const lstring&);
|
void cheatSet(const lstring&);
|
||||||
|
|
||||||
void updatePalette();
|
void paletteUpdate();
|
||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ bool Interface::unserialize(serializer &s) {
|
||||||
return system.unserialize(s);
|
return system.unserialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::updatePalette() {
|
void Interface::paletteUpdate() {
|
||||||
video.generate_palette();
|
video.generate_palette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct Interface : Emulator::Interface {
|
||||||
serializer serialize();
|
serializer serialize();
|
||||||
bool unserialize(serializer&);
|
bool unserialize(serializer&);
|
||||||
|
|
||||||
void updatePalette();
|
void paletteUpdate();
|
||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
|
|
|
@ -158,26 +158,11 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
|
|
||||||
else if(has_spc7110) {
|
else if(has_spc7110) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
|
||||||
" <map mode='shadow' address='00-0f:8000-ffff'/>\n"
|
|
||||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
|
||||||
" <map mode='linear' address='c0-cf:0000-ffff'/>\n"
|
|
||||||
" </rom>\n"
|
|
||||||
" <spc7110>\n"
|
" <spc7110>\n"
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
|
||||||
" <map mode='linear' address='00:6000-7fff'/>\n"
|
|
||||||
" <map mode='linear' address='30:6000-7fff'/>\n"
|
|
||||||
" </ram>\n"
|
|
||||||
" <mmio>\n"
|
" <mmio>\n"
|
||||||
" <map address='00-3f:4800-483f'/>\n"
|
" <map address='00-3f:4800-483f'/>\n"
|
||||||
" <map address='80-bf:4800-483f'/>\n"
|
" <map address='80-bf:4800-483f'/>\n"
|
||||||
" </mmio>\n"
|
" </mmio>\n"
|
||||||
" <mcu>\n"
|
|
||||||
" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n"
|
|
||||||
" </mcu>\n"
|
|
||||||
" <dcu>\n"
|
|
||||||
" <map address='50:0000-ffff'/>\n"
|
|
||||||
" </dcu>\n"
|
|
||||||
);
|
);
|
||||||
if(has_spc7110rtc) markup.append(
|
if(has_spc7110rtc) markup.append(
|
||||||
" <rtc>\n"
|
" <rtc>\n"
|
||||||
|
@ -186,6 +171,22 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" </rtc>\n"
|
" </rtc>\n"
|
||||||
);
|
);
|
||||||
markup.append(
|
markup.append(
|
||||||
|
" <dcu>\n"
|
||||||
|
" <map address='50:0000-ffff'/>\n"
|
||||||
|
" </dcu>\n"
|
||||||
|
" <mcu>\n"
|
||||||
|
" <rom>\n"
|
||||||
|
" <program offset='0x000000' size='0x100000'/>\n"
|
||||||
|
" <data offset='0x100000' size='", hex(rom_size - 0x100000), "'/>\n"
|
||||||
|
" <map address='00-0f:8000-ffff'/>\n"
|
||||||
|
" <map address='80-bf:8000-ffff'/>\n"
|
||||||
|
" <map address='c0-cf:0000-ffff'/>\n"
|
||||||
|
" </rom>\n"
|
||||||
|
" <ram size='0x", hex(ram_size), "'>\n"
|
||||||
|
" <map address='00-3f:6000-7fff'/>\n"
|
||||||
|
" <map address='80-bf:6000-7fff'/>\n"
|
||||||
|
" </ram>\n"
|
||||||
|
" </mcu>\n"
|
||||||
" </spc7110>\n"
|
" </spc7110>\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,9 +424,5 @@ void R65816::disassemble_opcode(char *output, uint32 addr) {
|
||||||
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
|
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(s, t);
|
|
||||||
//strcat(s, " ");
|
|
||||||
|
|
||||||
//sprintf(t, "V:%3d H:%4d", cpu.vcounter(), cpu.hcounter());
|
|
||||||
strcat(s, t);
|
strcat(s, t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,46 +400,51 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
|
||||||
has_spc7110 = true;
|
has_spc7110 = true;
|
||||||
has_spc7110rtc = root["rtc"].exists();
|
has_spc7110rtc = root["rtc"].exists();
|
||||||
|
|
||||||
auto &ram = root["ram"];
|
|
||||||
auto &mmio = root["mmio"];
|
auto &mmio = root["mmio"];
|
||||||
auto &mcu = root["mcu"];
|
|
||||||
auto &dcu = root["dcu"];
|
|
||||||
auto &rtc = root["rtc"];
|
auto &rtc = root["rtc"];
|
||||||
|
auto &dcu = root["dcu"];
|
||||||
|
auto &mcurom = root["mcu"]["rom"];
|
||||||
|
auto &mcuram = root["mcu"]["ram"];
|
||||||
|
|
||||||
ram_size = numeral(ram["size"].data);
|
spc7110.prom_base = numeral(mcurom["program"]["offset"].data);
|
||||||
for(auto &node : ram) {
|
spc7110.prom_size = numeral(mcurom["program"]["size"].data);
|
||||||
if(node.name != "map") continue;
|
|
||||||
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
|
spc7110.drom_base = numeral(mcurom["data"]["offset"].data);
|
||||||
parse_markup_map(m, node);
|
spc7110.drom_size = numeral(mcurom["data"]["size"].data);
|
||||||
mapping.append(m);
|
|
||||||
}
|
ram_size = numeral(mcuram["size"].data);
|
||||||
|
|
||||||
for(auto &node : mmio) {
|
for(auto &node : mmio) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 });
|
Mapping m({&SPC7110::mmio_read, &spc7110}, {&SPC7110::mmio_write, &spc7110});
|
||||||
parse_markup_map(m, node);
|
|
||||||
mapping.append(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
spc7110.data_rom_offset = numeral(mcu["offset"].data);
|
|
||||||
if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000;
|
|
||||||
for(auto &node : mcu) {
|
|
||||||
if(node.name != "map") continue;
|
|
||||||
Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 });
|
|
||||||
parse_markup_map(m, node);
|
|
||||||
mapping.append(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto &node : dcu) {
|
|
||||||
if(node.name != "map") continue;
|
|
||||||
Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 });
|
|
||||||
parse_markup_map(m, node);
|
parse_markup_map(m, node);
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto &node : rtc) {
|
for(auto &node : rtc) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 });
|
Mapping m({&SPC7110::mmio_read, &spc7110}, {&SPC7110::mmio_write, &spc7110});
|
||||||
|
parse_markup_map(m, node);
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &node : dcu) {
|
||||||
|
if(node.name != "map") continue;
|
||||||
|
Mapping m({&SPC7110::dcu_read, &spc7110}, {&SPC7110::dcu_write, &spc7110});
|
||||||
|
parse_markup_map(m, node);
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &node : mcurom) {
|
||||||
|
if(node.name != "map") continue;
|
||||||
|
Mapping m({&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110});
|
||||||
|
parse_markup_map(m, node);
|
||||||
|
mapping.append(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &node : mcuram) {
|
||||||
|
if(node.name != "map") continue;
|
||||||
|
Mapping m({&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110});
|
||||||
parse_markup_map(m, node);
|
parse_markup_map(m, node);
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,8 @@ void SPC7110::Decomp::write(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SPC7110::Decomp::dataread() {
|
uint8 SPC7110::Decomp::dataread() {
|
||||||
unsigned size = cartridge.rom.size() - spc7110.data_rom_offset;
|
unsigned addr = Bus::mirror(decomp_offset++, spc7110.drom_size);
|
||||||
while(decomp_offset >= size) decomp_offset -= size;
|
return cartridge.rom.read(spc7110.drom_base + addr);
|
||||||
return cartridge.rom.read(spc7110.data_rom_offset + decomp_offset++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
void SPC7110::Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
||||||
|
|
|
@ -65,10 +65,6 @@ void SPC7110::serialize(serializer &s) {
|
||||||
s.integer(r4833);
|
s.integer(r4833);
|
||||||
s.integer(r4834);
|
s.integer(r4834);
|
||||||
|
|
||||||
s.integer(dx_offset);
|
|
||||||
s.integer(ex_offset);
|
|
||||||
s.integer(fx_offset);
|
|
||||||
|
|
||||||
s.integer(r4840);
|
s.integer(r4840);
|
||||||
s.integer(r4841);
|
s.integer(r4841);
|
||||||
s.integer(r4842);
|
s.integer(r4842);
|
||||||
|
|
|
@ -71,9 +71,9 @@ void SPC7110::reset() {
|
||||||
r482f = 0x00;
|
r482f = 0x00;
|
||||||
|
|
||||||
r4830 = 0x00;
|
r4830 = 0x00;
|
||||||
mmio_write(0x4831, 0);
|
r4831 = 0x00;
|
||||||
mmio_write(0x4832, 1);
|
r4832 = 0x01;
|
||||||
mmio_write(0x4833, 2);
|
r4833 = 0x02;
|
||||||
r4834 = 0x00;
|
r4834 = 0x00;
|
||||||
|
|
||||||
r4840 = 0x00;
|
r4840 = 0x00;
|
||||||
|
@ -88,9 +88,8 @@ void SPC7110::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned SPC7110::datarom_addr(unsigned addr) {
|
unsigned SPC7110::datarom_addr(unsigned addr) {
|
||||||
unsigned size = cartridge.rom.size() - data_rom_offset;
|
addr = Bus::mirror(addr, drom_size);
|
||||||
while(addr >= size) addr -= size;
|
return drom_base + addr;
|
||||||
return data_rom_offset + addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
||||||
|
@ -194,6 +193,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
|
||||||
//==================
|
//==================
|
||||||
//decompression unit
|
//decompression unit
|
||||||
//==================
|
//==================
|
||||||
|
@ -333,6 +333,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
|
||||||
r4842 &= 0x7f;
|
r4842 &= 0x7f;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
|
@ -342,6 +343,7 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
|
||||||
//==================
|
//==================
|
||||||
//decompression unit
|
//decompression unit
|
||||||
//==================
|
//==================
|
||||||
|
@ -530,24 +532,11 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
//memory mapping unit
|
//memory mapping unit
|
||||||
//===================
|
//===================
|
||||||
|
|
||||||
case 0x4830: r4830 = data; break;
|
case 0x4830: r4830 = data & 0x87; break;
|
||||||
|
case 0x4831: r4831 = data & 0x07; break;
|
||||||
case 0x4831: {
|
case 0x4832: r4832 = data & 0x07; break;
|
||||||
r4831 = data;
|
case 0x4833: r4833 = data & 0x07; break;
|
||||||
dx_offset = datarom_addr(data * 0x100000);
|
case 0x4834: r4834 = data & 0x07; break;
|
||||||
} break;
|
|
||||||
|
|
||||||
case 0x4832: {
|
|
||||||
r4832 = data;
|
|
||||||
ex_offset = datarom_addr(data * 0x100000);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case 0x4833: {
|
|
||||||
r4833 = data;
|
|
||||||
fx_offset = datarom_addr(data * 0x100000);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case 0x4834: r4834 = data; break;
|
|
||||||
|
|
||||||
//====================
|
//====================
|
||||||
//real-time clock unit
|
//real-time clock unit
|
||||||
|
@ -628,26 +617,13 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
} break;
|
} break;
|
||||||
} //switch(rtc_state)
|
} //switch(rtc_state)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPC7110::SPC7110() {
|
SPC7110::SPC7110() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//============
|
|
||||||
//SPC7110::MCU
|
|
||||||
//============
|
|
||||||
|
|
||||||
uint8 SPC7110::mcu_read(unsigned addr) {
|
|
||||||
if(addr <= 0xdfffff) return cartridge.rom.read(dx_offset + (addr & 0x0fffff));
|
|
||||||
if(addr <= 0xefffff) return cartridge.rom.read(ex_offset + (addr & 0x0fffff));
|
|
||||||
if(addr <= 0xffffff) return cartridge.rom.read(fx_offset + (addr & 0x0fffff));
|
|
||||||
return cpu.regs.mdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPC7110::mcu_write(unsigned addr, uint8 data) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//============
|
//============
|
||||||
//SPC7110::DCU
|
//SPC7110::DCU
|
||||||
//============
|
//============
|
||||||
|
@ -659,16 +635,86 @@ uint8 SPC7110::dcu_read(unsigned) {
|
||||||
void SPC7110::dcu_write(unsigned, uint8) {
|
void SPC7110::dcu_write(unsigned, uint8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//============
|
//===============
|
||||||
//SPC7110::RAM
|
//SPC7110::MCUROM
|
||||||
//============
|
//===============
|
||||||
|
|
||||||
uint8 SPC7110::ram_read(unsigned addr) {
|
uint8 SPC7110::mcurom_read(unsigned addr) {
|
||||||
return cartridge.ram.read(addr & 0x1fff);
|
unsigned bank = 0;
|
||||||
|
|
||||||
|
if((addr & 0x708000) == 0x008000 //$00-0f|80-8f:8000-ffff
|
||||||
|
|| (addr & 0xf00000) == 0xc00000 // $c0-cf:0000-ffff
|
||||||
|
) {
|
||||||
|
addr &= 0x0fffff;
|
||||||
|
if(true) { //8mbit PROM
|
||||||
|
return cartridge.rom.read(prom_base + bus.mirror(0x000000 + addr, prom_size));
|
||||||
|
}
|
||||||
|
return mcurom_read_data(r4830 & 7, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0x708000) == 0x108000 //$10-1f|90-9f:8000-ffff
|
||||||
|
|| (addr & 0xf00000) == 0xd00000 // $d0-df:0000-ffff
|
||||||
|
) {
|
||||||
|
addr &= 0x0fffff;
|
||||||
|
if(r4834 & 4) { //16mbit PROM
|
||||||
|
return cartridge.rom.read(prom_base + bus.mirror(0x100000 + addr, prom_size));
|
||||||
|
}
|
||||||
|
return mcurom_read_data(r4831 & 7, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0x708000) == 0x208000 //$20-2f|a0-af:8000-ffff
|
||||||
|
|| (addr & 0xf00000) == 0xe00000 // $e0-ef:0000-ffff
|
||||||
|
) {
|
||||||
|
addr &= 0x0fffff;
|
||||||
|
return mcurom_read_data(r4832 & 7, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0x708000) == 0x308000 //$30-3f|b0-bf:8000-ffff
|
||||||
|
|| (addr & 0xf00000) == 0xf00000 // $f0-ff:0000-ffff
|
||||||
|
) {
|
||||||
|
addr &= 0x0fffff;
|
||||||
|
return mcurom_read_data(r4833 & 7, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::ram_write(unsigned addr, uint8 data) {
|
uint8 SPC7110::mcurom_read_data(unsigned bank, unsigned addr) {
|
||||||
if(r4830 & 0x80) cartridge.ram.write(addr & 0x1fff, data);
|
unsigned mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM
|
||||||
|
unsigned range = 0x100000 * (1 + mask);
|
||||||
|
unsigned offset = 0x100000 * (bank & mask);
|
||||||
|
|
||||||
|
//mirroring behavior is non-sensical. assuming a 32mbit data ROM:
|
||||||
|
//banks 4-7 with mask 0-2 returns 0x00; banks 4-7 with mask 3 mirrors banks 0-3
|
||||||
|
if(range <= drom_size && offset >= drom_size) return 0x00;
|
||||||
|
|
||||||
|
return cartridge.rom.read(drom_base + bus.mirror(offset + addr, drom_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::mcurom_write(unsigned addr, uint8 data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//===============
|
||||||
|
//SPC7110::MCURAM
|
||||||
|
//===============
|
||||||
|
|
||||||
|
uint8 SPC7110::mcuram_read(unsigned addr) {
|
||||||
|
//$00-3f|80-bf:6000-7fff
|
||||||
|
if(r4830 & 0x80) {
|
||||||
|
unsigned bank = (addr >> 16) & 0x3f;
|
||||||
|
addr = bus.mirror(bank * 0x2000 + (addr & 0x1fff), cartridge.ram.size());
|
||||||
|
return cartridge.ram.read(addr);
|
||||||
|
}
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::mcuram_write(unsigned addr, uint8 data) {
|
||||||
|
//$00-3f|80-bf:6000-7fff
|
||||||
|
if(r4830 & 0x80) {
|
||||||
|
unsigned bank = (addr >> 16) & 0x3f;
|
||||||
|
addr = bus.mirror(bank * 0x2000 + (addr & 0x1fff), cartridge.ram.size());
|
||||||
|
cartridge.ram.write(addr, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
struct SPC7110 {
|
struct SPC7110 {
|
||||||
uint8 rtc[20];
|
uint8 rtc[20];
|
||||||
unsigned data_rom_offset;
|
unsigned prom_base, prom_size; //program ROM
|
||||||
|
unsigned drom_base, drom_size; //data ROM
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void load();
|
void load();
|
||||||
|
@ -25,14 +26,15 @@ struct SPC7110 {
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
uint8 mcu_read(unsigned addr);
|
|
||||||
void mcu_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 dcu_read(unsigned);
|
uint8 dcu_read(unsigned);
|
||||||
void dcu_write(unsigned, uint8);
|
void dcu_write(unsigned, uint8);
|
||||||
|
|
||||||
uint8 ram_read(unsigned addr);
|
uint8 mcurom_read(unsigned addr);
|
||||||
void ram_write(unsigned addr, uint8 data);
|
uint8 mcurom_read_data(unsigned bank, unsigned addr);
|
||||||
|
void mcurom_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 mcuram_read(unsigned addr);
|
||||||
|
void mcuram_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
//spc7110decomp
|
//spc7110decomp
|
||||||
void decomp_init();
|
void decomp_init();
|
||||||
|
@ -101,15 +103,11 @@ private:
|
||||||
//===================
|
//===================
|
||||||
//memory mapping unit
|
//memory mapping unit
|
||||||
//===================
|
//===================
|
||||||
uint8 r4830; //SRAM write enable
|
uint8 r4830; //bank 0 mapping + SRAM write enable
|
||||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
uint8 r4831; //bank 1 mapping
|
||||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
uint8 r4832; //bank 2 mapping
|
||||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
uint8 r4833; //bank 3 mapping
|
||||||
uint8 r4834; //???
|
uint8 r4834; //bank mapping control
|
||||||
|
|
||||||
unsigned dx_offset;
|
|
||||||
unsigned ex_offset;
|
|
||||||
unsigned fx_offset;
|
|
||||||
|
|
||||||
//====================
|
//====================
|
||||||
//real-time clock unit
|
//real-time clock unit
|
||||||
|
|
|
@ -86,6 +86,11 @@ void CPU::enter() {
|
||||||
|
|
||||||
void CPU::op_step() {
|
void CPU::op_step() {
|
||||||
debugger.op_exec(regs.pc.d);
|
debugger.op_exec(regs.pc.d);
|
||||||
|
if(interface->tracer.open()) {
|
||||||
|
char text[4096];
|
||||||
|
disassemble_opcode(text, regs.pc.d);
|
||||||
|
interface->tracer.print(text, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
(this->*opcode_table[op_readpc()])();
|
(this->*opcode_table[op_readpc()])();
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,7 @@ void Interface::save(unsigned id, const stream &stream) {
|
||||||
|
|
||||||
void Interface::unload() {
|
void Interface::unload() {
|
||||||
cartridge.unload();
|
cartridge.unload();
|
||||||
|
tracerEnable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::connect(unsigned port, unsigned device) {
|
void Interface::connect(unsigned port, unsigned device) {
|
||||||
|
@ -230,10 +231,30 @@ void Interface::cheatSet(const lstring &list) {
|
||||||
cheat.synchronize();
|
cheat.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::updatePalette() {
|
void Interface::paletteUpdate() {
|
||||||
video.generate_palette();
|
video.generate_palette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Interface::tracerEnable(bool trace) {
|
||||||
|
string pathname = path(group(ID::ROM));
|
||||||
|
|
||||||
|
if(trace == true && !tracer.open()) {
|
||||||
|
for(unsigned n = 0; n <= 999; n++) {
|
||||||
|
string filename = {pathname, "trace-", decimal<3, '0'>(n), ".log"};
|
||||||
|
if(file::exists(filename)) continue;
|
||||||
|
tracer.open(filename, file::mode::write);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trace == false && tracer.open()) {
|
||||||
|
tracer.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Interface::Interface() {
|
Interface::Interface() {
|
||||||
interface = this;
|
interface = this;
|
||||||
system.init();
|
system.init();
|
||||||
|
|
|
@ -53,11 +53,13 @@ struct Interface : Emulator::Interface {
|
||||||
|
|
||||||
void cheatSet(const lstring&);
|
void cheatSet(const lstring&);
|
||||||
|
|
||||||
void updatePalette();
|
void paletteUpdate();
|
||||||
|
|
||||||
|
bool tracerEnable(bool);
|
||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
private:
|
file tracer;
|
||||||
vector<Device> device;
|
vector<Device> device;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,24 @@ MappedRAM::MappedRAM() : data_(nullptr), size_(0), write_protect_(false) {}
|
||||||
|
|
||||||
//Bus
|
//Bus
|
||||||
|
|
||||||
|
unsigned Bus::mirror(unsigned addr, unsigned size) {
|
||||||
|
unsigned base = 0;
|
||||||
|
if(size) {
|
||||||
|
unsigned mask = 1 << 23;
|
||||||
|
while(addr >= size) {
|
||||||
|
while(!(addr & mask)) mask >>= 1;
|
||||||
|
addr -= mask;
|
||||||
|
if(size > mask) {
|
||||||
|
size -= mask;
|
||||||
|
base += mask;
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
base += addr;
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
uint8 Bus::read(unsigned addr) {
|
uint8 Bus::read(unsigned addr) {
|
||||||
if(cheat.override[addr]) return cheat.read(addr);
|
if(cheat.override[addr]) return cheat.read(addr);
|
||||||
return reader[lookup[addr]](target[addr]);
|
return reader[lookup[addr]](target[addr]);
|
||||||
|
|
|
@ -5,24 +5,6 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
Bus bus;
|
Bus bus;
|
||||||
|
|
||||||
unsigned Bus::mirror(unsigned addr, unsigned size) {
|
|
||||||
unsigned base = 0;
|
|
||||||
if(size) {
|
|
||||||
unsigned mask = 1 << 23;
|
|
||||||
while(addr >= size) {
|
|
||||||
while(!(addr & mask)) mask >>= 1;
|
|
||||||
addr -= mask;
|
|
||||||
if(size > mask) {
|
|
||||||
size -= mask;
|
|
||||||
base += mask;
|
|
||||||
}
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
base += addr;
|
|
||||||
}
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bus::map(
|
void Bus::map(
|
||||||
MapMode mode,
|
MapMode mode,
|
||||||
unsigned bank_lo, unsigned bank_hi,
|
unsigned bank_lo, unsigned bank_hi,
|
||||||
|
|
|
@ -42,7 +42,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Bus {
|
struct Bus {
|
||||||
unsigned mirror(unsigned addr, unsigned size);
|
alwaysinline static unsigned mirror(unsigned addr, unsigned size);
|
||||||
|
|
||||||
alwaysinline uint8 read(unsigned addr);
|
alwaysinline uint8 read(unsigned addr);
|
||||||
alwaysinline void write(unsigned addr, uint8 data);
|
alwaysinline void write(unsigned addr, uint8 data);
|
||||||
|
|
|
@ -74,6 +74,8 @@ ifeq ($(USER),root)
|
||||||
@echo The installer needs to know your home directory to install important files.
|
@echo The installer needs to know your home directory to install important files.
|
||||||
else ifeq ($(platform),x)
|
else ifeq ($(platform),x)
|
||||||
sudo install -D -m 755 out/$(name) $(DESTDIR)$(prefix)/bin/$(name)
|
sudo install -D -m 755 out/$(name) $(DESTDIR)$(prefix)/bin/$(name)
|
||||||
|
sudo install -D -m 644 data/$(name).png $(DESTDIR)$(prefix)/share/pixmaps/$(name).png
|
||||||
|
sudo install -D -m 644 data/$(name).desktop $(DESTDIR)$(prefix)/share/applications/$(name).desktop
|
||||||
|
|
||||||
mkdir -p ~/.config/$(name)
|
mkdir -p ~/.config/$(name)
|
||||||
cp -R profile/* ~/.config/$(name)
|
cp -R profile/* ~/.config/$(name)
|
||||||
|
|
|
@ -119,6 +119,16 @@ void InputManager::appendHotkeys() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto hotkey = new HotkeyInput;
|
||||||
|
hotkey->name = "Toggle Tracer";
|
||||||
|
hotkey->mapping = "None";
|
||||||
|
|
||||||
|
hotkey->press = [&] {
|
||||||
|
utility->tracerToggle();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
for(auto &hotkey : hotkeyMap) {
|
for(auto &hotkey : hotkeyMap) {
|
||||||
string name = {"Hotkey::", hotkey->name};
|
string name = {"Hotkey::", hotkey->name};
|
||||||
name.replace(" ", "");
|
name.replace(" ", "");
|
||||||
|
|
|
@ -59,5 +59,5 @@ void VideoSettings::synchronize() {
|
||||||
overscanHorizontal.value.setText({config->video.maskOverscanHorizontal, "px"});
|
overscanHorizontal.value.setText({config->video.maskOverscanHorizontal, "px"});
|
||||||
overscanVertical.value.setText({config->video.maskOverscanVertical, "px"});
|
overscanVertical.value.setText({config->video.maskOverscanVertical, "px"});
|
||||||
|
|
||||||
if(application->active) system().updatePalette();
|
if(application->active) system().paletteUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ void Utility::load() {
|
||||||
|
|
||||||
loadMemory();
|
loadMemory();
|
||||||
|
|
||||||
system().updatePalette();
|
system().paletteUpdate();
|
||||||
synchronizeDSP();
|
synchronizeDSP();
|
||||||
|
|
||||||
resize();
|
resize();
|
||||||
|
@ -109,6 +109,7 @@ void Utility::load() {
|
||||||
|
|
||||||
void Utility::unload() {
|
void Utility::unload() {
|
||||||
if(application->active == nullptr) return;
|
if(application->active == nullptr) return;
|
||||||
|
if(tracerEnable) tracerToggle();
|
||||||
|
|
||||||
saveMemory();
|
saveMemory();
|
||||||
system().unload();
|
system().unload();
|
||||||
|
@ -143,6 +144,16 @@ void Utility::loadState(unsigned slot) {
|
||||||
showMessage({"Loaded from slot ", slot});
|
showMessage({"Loaded from slot ", slot});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utility::tracerToggle() {
|
||||||
|
if(application->active == nullptr) return;
|
||||||
|
tracerEnable = !tracerEnable;
|
||||||
|
bool result = system().tracerEnable(tracerEnable);
|
||||||
|
if( tracerEnable && result) return utility->showMessage("Tracer activated");
|
||||||
|
if( tracerEnable && !result) return tracerEnable = false, utility->showMessage("Unable to activate tracer");
|
||||||
|
if(!tracerEnable && result) return utility->showMessage("Tracer deactivated");
|
||||||
|
if(!tracerEnable && !result) return utility->showMessage("Unable to deactivate tracer");
|
||||||
|
}
|
||||||
|
|
||||||
void Utility::synchronizeDSP() {
|
void Utility::synchronizeDSP() {
|
||||||
if(application->active == nullptr) return;
|
if(application->active == nullptr) return;
|
||||||
|
|
||||||
|
@ -280,5 +291,6 @@ void Utility::showMessage(const string &message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Utility::Utility() {
|
Utility::Utility() {
|
||||||
|
tracerEnable = false;
|
||||||
statusTime = 0;
|
statusTime = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ struct Utility {
|
||||||
void saveState(unsigned slot);
|
void saveState(unsigned slot);
|
||||||
void loadState(unsigned slot);
|
void loadState(unsigned slot);
|
||||||
|
|
||||||
|
void tracerToggle();
|
||||||
|
|
||||||
void synchronizeDSP();
|
void synchronizeDSP();
|
||||||
void synchronizeRuby();
|
void synchronizeRuby();
|
||||||
void updateShader();
|
void updateShader();
|
||||||
|
@ -32,6 +34,7 @@ struct Utility {
|
||||||
lstring pathname;
|
lstring pathname;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool tracerEnable;
|
||||||
string statusText;
|
string statusText;
|
||||||
string statusMessage;
|
string statusMessage;
|
||||||
time_t statusTime;
|
time_t statusTime;
|
||||||
|
|
Loading…
Reference in New Issue