bsnes/higan/target-laevateinn/memory/memory.cpp

117 lines
3.7 KiB
C++
Executable File

#include "../base.hpp"
MemoryEditor *memoryEditor = nullptr;
MemoryEditor::MemoryEditor() {
setTitle("Memory Editor");
setGeometry({128, 128, 485, 255});
gotoLabel.setText("Goto:");
gotoAddress.setFont(application->monospaceFont);
source.append("CPU-Bus", "APU-Bus", "VRAM", "OAM", "CGRAM");
exportMemory.setText("Export");
autoUpdate.setText("Auto");
update.setText("Update");
editor.setFont(application->monospaceFont);
editor.setColumns(16);
editor.setRows(16);
layout.setMargin(5);
layout.append(controlLayout, {~0, 0}, 5);
controlLayout.append(gotoLabel, {0, 0}, 5);
controlLayout.append(gotoAddress, {50, 0}, 5);
controlLayout.append(source, {0, 0}, 5);
controlLayout.append(exportMemory, {80, 0}, 5);
controlLayout.append(spacer, {~0, 0});
controlLayout.append(autoUpdate, {0, 0}, 5);
controlLayout.append(update, {80, 0});
layout.append(editor, {~0, ~0});
append(layout);
gotoAddress.onChange = gotoAddress.onActivate = [&] {
editor.setOffset(hex(gotoAddress.text()));
editor.update();
};
update.onActivate = { &MemoryEditor::updateView, this };
source.onChange = { &MemoryEditor::selectSource, this };
exportMemory.onActivate = { &MemoryEditor::exportMemoryToDisk, this };
editor.onRead = { &MemoryEditor::read, this };
editor.onWrite = { &MemoryEditor::write, this };
windowManager->append(this, "MemoryEditor");
}
uint8_t MemoryEditor::read(unsigned addr) {
if(SFC::cartridge.loaded() == false) return 0x00;
switch(source.selection()) {
case 0: return cpuDebugger->read(addr);
case 1: return smpDebugger->read(addr);
case 2: return SFC::ppu.vram[addr & 0xffff];
case 3: return SFC::ppu.oam[addr % 544];
case 4: return SFC::ppu.cgram[addr & 0x01ff];
}
return ~0;
}
void MemoryEditor::write(unsigned addr, uint8_t data) {
if(SFC::cartridge.loaded() == false) return;
switch(source.selection()) {
case 0:
SFC::cartridge.rom.write_protect(false);
cpuDebugger->write(addr, data);
SFC::cartridge.rom.write_protect(true);
break;
case 1:
smpDebugger->write(addr, data);
break;
case 2:
SFC::ppu.vram[addr & 0xffff] = data;
break;
case 3:
SFC::ppu.oam[addr % 544] = data;
SFC::ppu.sprite.synchronize(); //cache OAM changes internally
break;
case 4:
SFC::ppu.cgram[addr & 0x01ff] = data;
break;
}
}
void MemoryEditor::selectSource() {
editor.setOffset(0);
switch(source.selection()) {
case 0: editor.setLength(16 * 1024 * 1024); break;
case 1: editor.setLength(64 * 1024); break;
case 2: editor.setLength(64 * 1024); break;
case 3: editor.setLength(544); break;
case 4: editor.setLength(512); break;
}
updateView();
}
void MemoryEditor::exportMemoryToDisk() {
string filename = { interface->pathName, "debug/memory-" };
switch(source.selection()) {
case 0: filename.append("cpu.bin"); break;
case 1: filename.append("apu.bin"); break;
case 2: filename.append("vram.bin"); break;
case 3: filename.append("oam.bin"); break;
case 4: filename.append("cgram.bin"); break;
}
file fp;
if(fp.open(filename, file::mode::write) == false) return;
switch(source.selection()) {
case 0: for(unsigned addr = 0; addr <= 0xffffff; addr++) fp.write(cpuDebugger->read(addr)); break;
case 1: for(unsigned addr = 0; addr <= 0xffff; addr++) fp.write(smpDebugger->read(addr)); break;
case 2: for(unsigned addr = 0; addr <= 0xffff; addr++) fp.write(SFC::ppu.vram[addr]); break;
case 3: for(unsigned addr = 0; addr <= 0x021f; addr++) fp.write(SFC::ppu.oam[addr]); break;
case 4: for(unsigned addr = 0; addr <= 0x01ff; addr++) fp.write(SFC::ppu.cgram[addr]); break;
}
debugger->print("Exported memory to ", filename, "\n");
}
void MemoryEditor::updateView() {
editor.update();
}