all repos — mgba @ 298b7e7a8b0a37fca2f55b4b859652cfd7762613

mGBA Game Boy Advance Emulator

Qt: Memory viewer can now edit select regions of memory
Jeffrey Pfau jeffrey@endrift.com
Fri, 01 May 2015 23:06:33 -0700
commit

298b7e7a8b0a37fca2f55b4b859652cfd7762613

parent

63071d9bc2950f629176d0ce613b7de6a25c0f63

M CHANGESCHANGES

@@ -13,6 +13,7 @@ - Analog inputs can be used for shortcuts

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

@@ -941,6 +941,63 @@ *old = oldValue;

} } +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) \ for (i = 0; i < 16; i += 4) { \ if (UNLIKELY(mask & (1 << i))) { \
M src/gba/memory.hsrc/gba/memory.h

@@ -154,6 +154,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);

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 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 GBAStoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
M src/platform/qt/MemoryModel.cppsrc/platform/qt/MemoryModel.cpp

@@ -34,6 +34,8 @@ QFontMetrics metrics(m_font);

m_cellHeight = metrics.height(); m_letterWidth = metrics.averageCharWidth(); + setFocusPolicy(Qt::StrongFocus); + for (int i = 0; i < 256; ++i) { QStaticText str(QString("%0").arg(i, 2, 16, QChar('0')).toUpper()); str.prepare(QTransform(), m_font);

@@ -83,6 +85,8 @@ if (width != 1 && width != 2 && width != 4) {

return; } m_align = width; + m_buffer = 0; + m_bufferedNybbles = 0; viewport()->update(); }

@@ -104,6 +108,8 @@ }

m_top = (address - m_base) / 16; boundsCheck(); verticalScrollBar()->setValue(m_top); + m_buffer = 0; + m_bufferedNybbles = 0; } void MemoryModel::resizeEvent(QResizeEvent*) {

@@ -204,6 +210,8 @@ QPoint position(event->pos() - QPoint(m_margins.left(), m_margins.top()));

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_selection = qMakePair(m_selectionAnchor, m_selectionAnchor + m_align); + m_buffer = 0; + m_bufferedNybbles = 0; emit selectionChanged(m_selection.first, m_selection.second); viewport()->update(); }

@@ -220,8 +228,66 @@ m_selection = qMakePair(address & ~(m_align - 1), m_selectionAnchor + m_align);

} else { 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); 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() {
M src/platform/qt/MemoryModel.hsrc/platform/qt/MemoryModel.h

@@ -44,6 +44,7 @@ void paintEvent(QPaintEvent*) override;

void wheelEvent(QWheelEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; + void keyPressEvent(QKeyEvent*) override; private: void boundsCheck();

@@ -65,6 +66,8 @@ QStaticText m_regionName;

QSizeF m_cellSize; QPair<uint32_t, uint32_t> m_selection; uint32_t m_selectionAnchor; + uint32_t m_buffer; + int m_bufferedNybbles; }; }