1 #include "memory.moc"
2 MemoryEditor *memoryEditor;
3
MemoryEditor()4 MemoryEditor::MemoryEditor() : QbWindow(config().geometry.memoryEditor) {
5 setObjectName("memory-editor");
6 setWindowTitle("Memory Editor");
7
8 layout = new QHBoxLayout;
9 layout->setMargin(Style::WindowMargin);
10 layout->setSpacing(Style::WidgetSpacing);
11 setLayout(layout);
12
13 editor = new HexEditor;
14 editor->reader = bind(&MemoryEditor::reader, this);
15 editor->writer = bind(&MemoryEditor::writer, this);
16 editor->setSize(16 * 1024 * 1024);
17 memorySource = SNES::Debugger::CPUBus;
18 layout->addWidget(editor);
19
20 controlLayout = new QVBoxLayout;
21 controlLayout->setSpacing(0);
22 layout->addLayout(controlLayout);
23
24 source = new QComboBox;
25 source->addItem("S-CPU bus");
26 source->addItem("S-APU bus");
27 source->addItem("S-PPU VRAM");
28 source->addItem("S-PPU OAM");
29 source->addItem("S-PPU CGRAM");
30 controlLayout->addWidget(source);
31 controlLayout->addSpacing(2);
32
33 addr = new QLineEdit;
34 controlLayout->addWidget(addr);
35
36 autoUpdateBox = new QCheckBox("Auto update");
37 controlLayout->addWidget(autoUpdateBox);
38
39 refreshButton = new QPushButton("Refresh");
40 controlLayout->addWidget(refreshButton);
41
42 spacer = new QWidget;
43 spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
44 controlLayout->addWidget(spacer);
45
46 exportButton = new QPushButton("Export");
47 controlLayout->addWidget(exportButton);
48
49 importButton = new QPushButton("Import");
50 controlLayout->addWidget(importButton);
51
52 connect(source, SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChanged(int)));
53 connect(addr, SIGNAL(textEdited(const QString&)), this, SLOT(updateOffset()));
54 connect(addr, SIGNAL(returnPressed()), this, SLOT(updateOffset()));
55 connect(refreshButton, SIGNAL(released()), this, SLOT(refresh()));
56 connect(exportButton, SIGNAL(released()), this, SLOT(exportMemory()));
57 connect(importButton, SIGNAL(released()), this, SLOT(importMemory()));
58 }
59
autoUpdate()60 void MemoryEditor::autoUpdate() {
61 if(SNES::cartridge.loaded() && autoUpdateBox->isChecked()) editor->update();
62 }
63
synchronize()64 void MemoryEditor::synchronize() {
65 if(SNES::cartridge.loaded() == false) {
66 editor->setHtml("");
67 editor->scrollbar->setEnabled(false);
68 source->setEnabled(false);
69 addr->setEnabled(false);
70 autoUpdateBox->setEnabled(false);
71 refreshButton->setEnabled(false);
72 exportButton->setEnabled(false);
73 importButton->setEnabled(false);
74 } else {
75 editor->scrollbar->setEnabled(true);
76 source->setEnabled(true);
77 addr->setEnabled(true);
78 autoUpdateBox->setEnabled(true);
79 refreshButton->setEnabled(true);
80 exportButton->setEnabled(true);
81 importButton->setEnabled(true);
82 }
83 }
84
show()85 void MemoryEditor::show() {
86 QbWindow::show();
87 refresh();
88 }
89
sourceChanged(int index)90 void MemoryEditor::sourceChanged(int index) {
91 switch(index) { default:
92 case 0: memorySource = SNES::Debugger::CPUBus; editor->setSize(16 * 1024 * 1024); break;
93 case 1: memorySource = SNES::Debugger::APURAM; editor->setSize(64 * 1024); break;
94 case 2: memorySource = SNES::Debugger::VRAM; editor->setSize(64 * 1024); break;
95 case 3: memorySource = SNES::Debugger::OAM; editor->setSize(544); break;
96 case 4: memorySource = SNES::Debugger::CGRAM; editor->setSize(512); break;
97 }
98
99 editor->setOffset(strhex(addr->text().toUtf8().data()));
100 editor->update();
101 }
102
refresh()103 void MemoryEditor::refresh() {
104 if(SNES::cartridge.loaded() == false) {
105 editor->setHtml("");
106 } else {
107 editor->update();
108 }
109 }
110
updateOffset()111 void MemoryEditor::updateOffset() {
112 editor->setOffset(strhex(addr->text().toUtf8().data()));
113 refresh();
114 }
115
exportMemory()116 void MemoryEditor::exportMemory() {
117 string basename = filepath(nall::basename(cartridge.fileName), config().path.data);
118
119 exportMemory(SNES::memory::cartram, string() << basename << "-sram.bin");
120 exportMemory(SNES::memory::wram, string() << basename << "-wram.bin");
121 exportMemory(SNES::memory::apuram, string() << basename << "-apuram.bin");
122 exportMemory(SNES::memory::vram, string() << basename << "-vram.bin");
123 exportMemory(SNES::memory::oam, string() << basename << "-oam.bin");
124 exportMemory(SNES::memory::cgram, string() << basename << "-cgram.bin");
125 }
126
importMemory()127 void MemoryEditor::importMemory() {
128 string basename = filepath(nall::basename(cartridge.fileName), config().path.data);
129
130 importMemory(SNES::memory::cartram, string() << basename << "-sram.bin");
131 importMemory(SNES::memory::wram, string() << basename << "-wram.bin");
132 importMemory(SNES::memory::apuram, string() << basename << "-apuram.bin");
133 importMemory(SNES::memory::vram, string() << basename << "-vram.bin");
134 importMemory(SNES::memory::oam, string() << basename << "-oam.bin");
135 importMemory(SNES::memory::cgram, string() << basename << "-cgram.bin");
136 refresh(); //in case import changed values that are currently being displayed ...
137 }
138
exportMemory(SNES::Memory & memory,const string & filename) const139 void MemoryEditor::exportMemory(SNES::Memory &memory, const string &filename) const {
140 file fp;
141 if(fp.open(filename, file::mode_write)) {
142 for(unsigned i = 0; i < memory.size(); i++) fp.write(memory.read(i));
143 fp.close();
144 }
145 }
146
importMemory(SNES::Memory & memory,const string & filename) const147 void MemoryEditor::importMemory(SNES::Memory &memory, const string &filename) const {
148 file fp;
149 if(fp.open(filename, file::mode_read)) {
150 unsigned filesize = fp.size();
151 for(unsigned i = 0; i < memory.size() && i < filesize; i++) memory.write(i, fp.read());
152 fp.close();
153 }
154 }
155
reader(unsigned addr)156 uint8 MemoryEditor::reader(unsigned addr) {
157 return SNES::debugger.read(memorySource, addr);
158 }
159
writer(unsigned addr,uint8 data)160 void MemoryEditor::writer(unsigned addr, uint8 data) {
161 SNES::debugger.write(memorySource, addr, data);
162 }
163