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