Qt: Memory viewer can now edit select regions of memory

This commit is contained in:
Jeffrey Pfau 2015-05-01 23:06:33 -07:00
parent 63071d9bc2
commit 298b7e7a8b
5 changed files with 128 additions and 0 deletions

View File

@ -13,6 +13,7 @@ Features:
- Menu items for specific solar sensor brightness levels - Menu items for specific solar sensor brightness levels
- Remappable controls for tilt and gyroscope sensors - Remappable controls for tilt and gyroscope sensors
- Status messages for actions taken while a game is running (e.g. save/load state) - Status messages for actions taken while a game is running (e.g. save/load state)
- Memory inspector
Bugfixes: Bugfixes:
- GBA: Fix timers not updating timing when writing to only the reload register - GBA: Fix timers not updating timing when writing to only the reload register
- All: Fix sanitize-deb script not cleaning up after itself - All: Fix sanitize-deb script not cleaning up after itself

View File

@ -941,6 +941,63 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o
} }
} }
void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory;
int8_t oldValue = -1;
switch (address >> BASE_OFFSET) {
case REGION_WORKING_RAM:
oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
break;
case REGION_WORKING_IRAM:
oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
break;
case REGION_IO:
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch8: 0x%08X", address);
break;
case REGION_PALETTE_RAM:
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch8: 0x%08X", address);
break;
case REGION_VRAM:
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch8: 0x%08X", address);
break;
case REGION_OAM:
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch8: 0x%08X", address);
break;
case REGION_CART0:
case REGION_CART0_EX:
case REGION_CART1:
case REGION_CART1_EX:
case REGION_CART2:
case REGION_CART2_EX:
_pristineCow(gba);
if ((address & (SIZE_CART0 - 1)) < gba->memory.romSize) {
gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
}
oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
break;
case REGION_CART_SRAM:
case REGION_CART_SRAM_MIRROR:
if (memory->savedata.type == SAVEDATA_SRAM) {
oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
} else {
GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
}
break;
default:
GBALog(gba, GBA_LOG_WARN, "Bad memory Patch8: 0x%08X", address);
break;
}
if (old) {
*old = oldValue;
}
}
#define LDM_LOOP(LDM) \ #define LDM_LOOP(LDM) \
for (i = 0; i < 16; i += 4) { \ for (i = 0; i < 16; i += 4) { \
if (UNLIKELY(mask & (1 << i))) { \ if (UNLIKELY(mask & (1 << i))) { \

View File

@ -154,6 +154,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old); void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old);
void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old); void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old);
void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old);
uint32_t GBALoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter); uint32_t GBALoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
uint32_t GBAStoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter); uint32_t GBAStoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);

View File

@ -34,6 +34,8 @@ MemoryModel::MemoryModel(QWidget* parent)
m_cellHeight = metrics.height(); m_cellHeight = metrics.height();
m_letterWidth = metrics.averageCharWidth(); m_letterWidth = metrics.averageCharWidth();
setFocusPolicy(Qt::StrongFocus);
for (int i = 0; i < 256; ++i) { for (int i = 0; i < 256; ++i) {
QStaticText str(QString("%0").arg(i, 2, 16, QChar('0')).toUpper()); QStaticText str(QString("%0").arg(i, 2, 16, QChar('0')).toUpper());
str.prepare(QTransform(), m_font); str.prepare(QTransform(), m_font);
@ -83,6 +85,8 @@ void MemoryModel::setAlignment(int width) {
return; return;
} }
m_align = width; m_align = width;
m_buffer = 0;
m_bufferedNybbles = 0;
viewport()->update(); viewport()->update();
} }
@ -104,6 +108,8 @@ void MemoryModel::jumpToAddress(uint32_t address) {
m_top = (address - m_base) / 16; m_top = (address - m_base) / 16;
boundsCheck(); boundsCheck();
verticalScrollBar()->setValue(m_top); verticalScrollBar()->setValue(m_top);
m_buffer = 0;
m_bufferedNybbles = 0;
} }
void MemoryModel::resizeEvent(QResizeEvent*) { void MemoryModel::resizeEvent(QResizeEvent*) {
@ -204,6 +210,8 @@ void MemoryModel::mousePressEvent(QMouseEvent* event) {
uint32_t address = int(position.x() / m_cellSize.width()) + (int(position.y() / m_cellSize.height()) + m_top) * 16 + m_base; uint32_t address = int(position.x() / m_cellSize.width()) + (int(position.y() / m_cellSize.height()) + m_top) * 16 + m_base;
m_selectionAnchor = address & ~(m_align - 1); m_selectionAnchor = address & ~(m_align - 1);
m_selection = qMakePair(m_selectionAnchor, m_selectionAnchor + m_align); m_selection = qMakePair(m_selectionAnchor, m_selectionAnchor + m_align);
m_buffer = 0;
m_bufferedNybbles = 0;
emit selectionChanged(m_selection.first, m_selection.second); emit selectionChanged(m_selection.first, m_selection.second);
viewport()->update(); viewport()->update();
} }
@ -220,10 +228,68 @@ void MemoryModel::mouseMoveEvent(QMouseEvent* event) {
} else { } else {
m_selection = qMakePair(m_selectionAnchor, (address & ~(m_align - 1)) + m_align); m_selection = qMakePair(m_selectionAnchor, (address & ~(m_align - 1)) + m_align);
} }
m_buffer = 0;
m_bufferedNybbles = 0;
emit selectionChanged(m_selection.first, m_selection.second); emit selectionChanged(m_selection.first, m_selection.second);
viewport()->update(); viewport()->update();
} }
void MemoryModel::keyPressEvent(QKeyEvent* event) {
if (m_selection.first >= m_selection.second) {
return;
}
int key = event->key();
uint8_t nybble = 0;
switch (key) {
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
case Qt::Key_7:
case Qt::Key_8:
case Qt::Key_9:
nybble = key - Qt::Key_0;
break;
case Qt::Key_A:
case Qt::Key_B:
case Qt::Key_C:
case Qt::Key_D:
case Qt::Key_E:
case Qt::Key_F:
nybble = key - Qt::Key_A + 10;
break;
default:
return;
}
m_buffer <<= 4;
m_buffer |= nybble;
++m_bufferedNybbles;
if (m_bufferedNybbles == m_align * 2) {
switch (m_align) {
case 1:
GBAPatch8(m_cpu, m_selection.first, m_buffer, nullptr);
break;
case 2:
GBAPatch16(m_cpu, m_selection.first, m_buffer, nullptr);
break;
case 4:
GBAPatch32(m_cpu, m_selection.first, m_buffer, nullptr);
break;
}
m_bufferedNybbles = 0;
m_buffer = 0;
m_selection.first += m_align;
if (m_selection.second <= m_selection.first) {
m_selection.second = m_selection.first + m_align;
}
emit selectionChanged(m_selection.first, m_selection.second);
viewport()->update();
}
}
void MemoryModel::boundsCheck() { void MemoryModel::boundsCheck() {
if (m_top < 0) { if (m_top < 0) {
m_top = 0; m_top = 0;

View File

@ -44,6 +44,7 @@ protected:
void wheelEvent(QWheelEvent*) override; void wheelEvent(QWheelEvent*) override;
void mousePressEvent(QMouseEvent*) override; void mousePressEvent(QMouseEvent*) override;
void mouseMoveEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override;
void keyPressEvent(QKeyEvent*) override;
private: private:
void boundsCheck(); void boundsCheck();
@ -65,6 +66,8 @@ private:
QSizeF m_cellSize; QSizeF m_cellSize;
QPair<uint32_t, uint32_t> m_selection; QPair<uint32_t, uint32_t> m_selection;
uint32_t m_selectionAnchor; uint32_t m_selectionAnchor;
uint32_t m_buffer;
int m_bufferedNybbles;
}; };
} }