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:
Tim Allen 2012-05-14 23:32:55 +10:00
parent 73ebe093b8
commit a1e4c67a05
26 changed files with 873 additions and 774 deletions

View File

@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "bsnes";
static const char Version[] = "089";
static const char Version[] = "089.02";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}

View File

@ -98,7 +98,10 @@ struct Interface {
virtual void cheatSet(const lstring& = lstring{}) {}
//utility functions
virtual void updatePalette() {}
virtual void paletteUpdate() {}
//debugger functions
virtual bool tracerEnable(bool) { return false; }
Interface() : bind(nullptr) {}
};

View File

@ -76,7 +76,7 @@ void Interface::cheatSet(const lstring &list) {
cheat.synchronize();
}
void Interface::updatePalette() {
void Interface::paletteUpdate() {
video.generate_palette();
}

View File

@ -33,7 +33,7 @@ struct Interface : Emulator::Interface {
void cheatSet(const lstring&);
void updatePalette();
void paletteUpdate();
Interface();

View File

@ -99,7 +99,7 @@ void Interface::cheatSet(const lstring &list) {
cheat.synchronize();
}
void Interface::updatePalette() {
void Interface::paletteUpdate() {
video.generate_palette();
}

View File

@ -45,7 +45,7 @@ struct Interface : Emulator::Interface {
void cheatSet(const lstring&);
void updatePalette();
void paletteUpdate();
Interface();

View File

@ -79,7 +79,7 @@ bool Interface::unserialize(serializer &s) {
return system.unserialize(s);
}
void Interface::updatePalette() {
void Interface::paletteUpdate() {
video.generate_palette();
}

View File

@ -32,7 +32,7 @@ struct Interface : Emulator::Interface {
serializer serialize();
bool unserialize(serializer&);
void updatePalette();
void paletteUpdate();
Interface();

View File

@ -158,26 +158,11 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
else if(has_spc7110) {
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"
" <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"
" <map address='00-3f:4800-483f'/>\n"
" <map address='80-bf:4800-483f'/>\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(
" <rtc>\n"
@ -186,6 +171,22 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
" </rtc>\n"
);
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"
);
}

View File

@ -424,9 +424,5 @@ void R65816::disassemble_opcode(char *output, uint32 addr) {
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);
}

View File

@ -400,19 +400,19 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
has_spc7110 = true;
has_spc7110rtc = root["rtc"].exists();
auto &ram = root["ram"];
auto &mmio = root["mmio"];
auto &mcu = root["mcu"];
auto &dcu = root["dcu"];
auto &rtc = root["rtc"];
auto &dcu = root["dcu"];
auto &mcurom = root["mcu"]["rom"];
auto &mcuram = root["mcu"]["ram"];
ram_size = numeral(ram["size"].data);
for(auto &node : ram) {
if(node.name != "map") continue;
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
parse_markup_map(m, node);
mapping.append(m);
}
spc7110.prom_base = numeral(mcurom["program"]["offset"].data);
spc7110.prom_size = numeral(mcurom["program"]["size"].data);
spc7110.drom_base = numeral(mcurom["data"]["offset"].data);
spc7110.drom_size = numeral(mcurom["data"]["size"].data);
ram_size = numeral(mcuram["size"].data);
for(auto &node : mmio) {
if(node.name != "map") continue;
@ -421,11 +421,9 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
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) {
for(auto &node : rtc) {
if(node.name != "map") continue;
Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 });
Mapping m({&SPC7110::mmio_read, &spc7110}, {&SPC7110::mmio_write, &spc7110});
parse_markup_map(m, node);
mapping.append(m);
}
@ -437,9 +435,16 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
mapping.append(m);
}
for(auto &node : rtc) {
for(auto &node : mcurom) {
if(node.name != "map") continue;
Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 });
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);
mapping.append(m);
}

View File

@ -24,9 +24,8 @@ void SPC7110::Decomp::write(uint8 data) {
}
uint8 SPC7110::Decomp::dataread() {
unsigned size = cartridge.rom.size() - spc7110.data_rom_offset;
while(decomp_offset >= size) decomp_offset -= size;
return cartridge.rom.read(spc7110.data_rom_offset + decomp_offset++);
unsigned addr = Bus::mirror(decomp_offset++, spc7110.drom_size);
return cartridge.rom.read(spc7110.drom_base + addr);
}
void SPC7110::Decomp::init(unsigned mode, unsigned offset, unsigned index) {

View File

@ -65,10 +65,6 @@ void SPC7110::serialize(serializer &s) {
s.integer(r4833);
s.integer(r4834);
s.integer(dx_offset);
s.integer(ex_offset);
s.integer(fx_offset);
s.integer(r4840);
s.integer(r4841);
s.integer(r4842);

View File

@ -71,9 +71,9 @@ void SPC7110::reset() {
r482f = 0x00;
r4830 = 0x00;
mmio_write(0x4831, 0);
mmio_write(0x4832, 1);
mmio_write(0x4833, 2);
r4831 = 0x00;
r4832 = 0x01;
r4833 = 0x02;
r4834 = 0x00;
r4840 = 0x00;
@ -88,9 +88,8 @@ void SPC7110::reset() {
}
unsigned SPC7110::datarom_addr(unsigned addr) {
unsigned size = cartridge.rom.size() - data_rom_offset;
while(addr >= size) addr -= size;
return data_rom_offset + addr;
addr = Bus::mirror(addr, drom_size);
return drom_base + addr;
}
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
@ -194,6 +193,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
addr &= 0xffff;
switch(addr) {
//==================
//decompression unit
//==================
@ -333,6 +333,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
r4842 &= 0x7f;
return status;
}
}
return cpu.regs.mdr;
@ -342,6 +343,7 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;
switch(addr) {
//==================
//decompression unit
//==================
@ -530,24 +532,11 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
//memory mapping unit
//===================
case 0x4830: r4830 = data; break;
case 0x4831: {
r4831 = data;
dx_offset = datarom_addr(data * 0x100000);
} 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;
case 0x4830: r4830 = data & 0x87; break;
case 0x4831: r4831 = data & 0x07; break;
case 0x4832: r4832 = data & 0x07; break;
case 0x4833: r4833 = data & 0x07; break;
case 0x4834: r4834 = data & 0x07; break;
//====================
//real-time clock unit
@ -628,26 +617,13 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
} break;
} //switch(rtc_state)
} break;
}
}
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
//============
@ -659,16 +635,86 @@ uint8 SPC7110::dcu_read(unsigned) {
void SPC7110::dcu_write(unsigned, uint8) {
}
//============
//SPC7110::RAM
//============
//===============
//SPC7110::MCUROM
//===============
uint8 SPC7110::ram_read(unsigned addr) {
return cartridge.ram.read(addr & 0x1fff);
uint8 SPC7110::mcurom_read(unsigned addr) {
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);
}
void SPC7110::ram_write(unsigned addr, uint8 data) {
if(r4830 & 0x80) cartridge.ram.write(addr & 0x1fff, data);
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;
}
uint8 SPC7110::mcurom_read_data(unsigned bank, unsigned addr) {
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);
}
}
}

View File

@ -3,7 +3,8 @@
struct SPC7110 {
uint8 rtc[20];
unsigned data_rom_offset;
unsigned prom_base, prom_size; //program ROM
unsigned drom_base, drom_size; //data ROM
void init();
void load();
@ -25,14 +26,15 @@ struct SPC7110 {
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
uint8 mcu_read(unsigned addr);
void mcu_write(unsigned addr, uint8 data);
uint8 dcu_read(unsigned);
void dcu_write(unsigned, uint8);
uint8 ram_read(unsigned addr);
void ram_write(unsigned addr, uint8 data);
uint8 mcurom_read(unsigned addr);
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
void decomp_init();
@ -101,15 +103,11 @@ private:
//===================
//memory mapping unit
//===================
uint8 r4830; //SRAM write enable
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
uint8 r4834; //???
unsigned dx_offset;
unsigned ex_offset;
unsigned fx_offset;
uint8 r4830; //bank 0 mapping + SRAM write enable
uint8 r4831; //bank 1 mapping
uint8 r4832; //bank 2 mapping
uint8 r4833; //bank 3 mapping
uint8 r4834; //bank mapping control
//====================
//real-time clock unit

View File

@ -86,6 +86,11 @@ void CPU::enter() {
void CPU::op_step() {
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()])();
}

View File

@ -174,6 +174,7 @@ void Interface::save(unsigned id, const stream &stream) {
void Interface::unload() {
cartridge.unload();
tracerEnable(false);
}
void Interface::connect(unsigned port, unsigned device) {
@ -230,10 +231,30 @@ void Interface::cheatSet(const lstring &list) {
cheat.synchronize();
}
void Interface::updatePalette() {
void Interface::paletteUpdate() {
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 = this;
system.init();

View File

@ -53,11 +53,13 @@ struct Interface : Emulator::Interface {
void cheatSet(const lstring&);
void updatePalette();
void paletteUpdate();
bool tracerEnable(bool);
Interface();
private:
file tracer;
vector<Device> device;
};

View File

@ -51,6 +51,24 @@ MappedRAM::MappedRAM() : data_(nullptr), size_(0), write_protect_(false) {}
//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) {
if(cheat.override[addr]) return cheat.read(addr);
return reader[lookup[addr]](target[addr]);

View File

@ -5,24 +5,6 @@ namespace SuperFamicom {
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(
MapMode mode,
unsigned bank_lo, unsigned bank_hi,

View File

@ -42,7 +42,7 @@ private:
};
struct Bus {
unsigned mirror(unsigned addr, unsigned size);
alwaysinline static unsigned mirror(unsigned addr, unsigned size);
alwaysinline uint8 read(unsigned addr);
alwaysinline void write(unsigned addr, uint8 data);

View File

@ -74,6 +74,8 @@ ifeq ($(USER),root)
@echo The installer needs to know your home directory to install important files.
else ifeq ($(platform),x)
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)
cp -R profile/* ~/.config/$(name)

View File

@ -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) {
string name = {"Hotkey::", hotkey->name};
name.replace(" ", "");

View File

@ -59,5 +59,5 @@ void VideoSettings::synchronize() {
overscanHorizontal.value.setText({config->video.maskOverscanHorizontal, "px"});
overscanVertical.value.setText({config->video.maskOverscanVertical, "px"});
if(application->active) system().updatePalette();
if(application->active) system().paletteUpdate();
}

View File

@ -99,7 +99,7 @@ void Utility::load() {
loadMemory();
system().updatePalette();
system().paletteUpdate();
synchronizeDSP();
resize();
@ -109,6 +109,7 @@ void Utility::load() {
void Utility::unload() {
if(application->active == nullptr) return;
if(tracerEnable) tracerToggle();
saveMemory();
system().unload();
@ -143,6 +144,16 @@ void Utility::loadState(unsigned 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() {
if(application->active == nullptr) return;
@ -280,5 +291,6 @@ void Utility::showMessage(const string &message) {
}
Utility::Utility() {
tracerEnable = false;
statusTime = 0;
}

View File

@ -16,6 +16,8 @@ struct Utility {
void saveState(unsigned slot);
void loadState(unsigned slot);
void tracerToggle();
void synchronizeDSP();
void synchronizeRuby();
void updateShader();
@ -32,6 +34,7 @@ struct Utility {
lstring pathname;
private:
bool tracerEnable;
string statusText;
string statusMessage;
time_t statusTime;