From 4b5885624bc647faf43b5aa83acb04146c41dacd Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 5 May 2016 23:52:28 -0700 Subject: [PATCH] GB Core: Add rawRead* and enable memory viewer for Game Boy --- src/gb/core.c | 22 ++++++- src/gb/memory.c | 2 - src/gb/memory.h | 4 -- src/platform/qt/MemoryModel.cpp | 12 ++++ src/platform/qt/MemoryView.cpp | 107 +++++++++++++++++++++++++------- src/platform/qt/MemoryView.ui | 93 +++++++++------------------ src/platform/qt/Window.cpp | 1 - 7 files changed, 146 insertions(+), 95 deletions(-) diff --git a/src/gb/core.c b/src/gb/core.c index 8b1727138..531408711 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -295,6 +295,22 @@ static void _GBCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t val cpu->memory.store8(cpu, address + 3, value >> 24); } +static uint32_t _GBCoreRawRead8(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return GBLoad8(cpu, address); +} + +static uint32_t _GBCoreRawRead16(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return GBLoad8(cpu, address) | (GBLoad8(cpu, address + 1) << 8); +} + +static uint32_t _GBCoreRawRead32(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return GBLoad8(cpu, address) | (GBLoad8(cpu, address + 1) << 8) | + (GBLoad8(cpu, address + 2) << 16) | (GBLoad8(cpu, address + 3) << 24); +} + static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { UNUSED(core); switch (type) { @@ -389,9 +405,9 @@ struct mCore* GBCoreCreate(void) { core->busWrite8 = _GBCoreBusWrite8; core->busWrite16 = _GBCoreBusWrite16; core->busWrite32 = _GBCoreBusWrite32; - core->rawRead8 = NULL; - core->rawRead16 = NULL; - core->rawRead32 = NULL; + core->rawRead8 = _GBCoreRawRead8; + core->rawRead16 = _GBCoreRawRead16; + core->rawRead32 = _GBCoreRawRead32; core->rawWrite8 = NULL; core->rawWrite16 = NULL; core->rawWrite32 = NULL; diff --git a/src/gb/memory.c b/src/gb/memory.c index 40fcc6071..2cac8c8bd 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -467,8 +467,6 @@ void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { GBStore8(cpu, address, value); } -uint8_t GBView8(struct LR35902Core* cpu, uint16_t address); - void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old); static void _switchBank(struct GBMemory* memory, int bank) { diff --git a/src/gb/memory.h b/src/gb/memory.h index ac8c09124..f2f4a4d26 100644 --- a/src/gb/memory.h +++ b/src/gb/memory.h @@ -171,10 +171,6 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value); uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address); void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value); -uint16_t GBView16(struct LR35902Core* cpu, uint16_t address); -uint8_t GBView8(struct LR35902Core* cpu, uint16_t address); - -void GBPatch16(struct LR35902Core* cpu, uint16_t address, int16_t value, int16_t* old); void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old); #endif diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index 094869df3..9ac37cc17 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -210,12 +210,18 @@ void MemoryModel::paintEvent(QPaintEvent* event) { int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight; for (int y = 0; y < height; ++y) { int yp = m_cellHeight * y + m_margins.top(); + if ((y + m_top) * 16 >= m_size) { + break; + } QString data = arg.arg((y + m_top) * 16 + m_base, 8, 16, c0).toUpper(); painter.drawText(QRectF(QPointF(0, yp), QSizeF(m_margins.left(), m_cellHeight)), Qt::AlignHCenter, data); switch (m_align) { case 2: for (int x = 0; x < 16; x += 2) { uint32_t address = (y + m_top) * 16 + x + m_base; + if (address >= m_base + m_size) { + break; + } if (isInSelection(address)) { painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), QSizeF(m_cellSize.width() * 2, m_cellSize.height())), @@ -241,6 +247,9 @@ void MemoryModel::paintEvent(QPaintEvent* event) { case 4: for (int x = 0; x < 16; x += 4) { uint32_t address = (y + m_top) * 16 + x + m_base; + if (address >= m_base + m_size) { + break; + } if (isInSelection(address)) { painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), QSizeF(m_cellSize.width() * 4, m_cellSize.height())), @@ -273,6 +282,9 @@ void MemoryModel::paintEvent(QPaintEvent* event) { default: for (int x = 0; x < 16; ++x) { uint32_t address = (y + m_top) * 16 + x + m_base; + if (address >= m_base + m_size) { + break; + } if (isInSelection(address)) { painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), m_cellSize), palette.highlight()); diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index 14d34ed27..a7216e358 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -10,11 +10,53 @@ extern "C" { #include "core/core.h" +#ifdef M_CORE_GBA #include "gba/memory.h" +#endif +#ifdef M_CORE_GB +#include "gb/memory.h" +#endif } using namespace QGBA; +struct IndexInfo { + const char* name; + const char* longName; + uint32_t base; + uint32_t size; +}; +#ifdef M_CORE_GBA +const static struct IndexInfo indexInfoGBA[] = { + { "All", "All", 0, 0x10000000 }, + { "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS }, + { "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, SIZE_WORKING_RAM }, + { "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, SIZE_WORKING_IRAM }, + { "MMIO", "Memory-Mapped I/O", BASE_IO, SIZE_IO }, + { "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, SIZE_PALETTE_RAM }, + { "VRAM", "Video RAM (96kiB)", BASE_VRAM, SIZE_VRAM }, + { "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, SIZE_OAM }, + { "ROM", "Game Pak (32MiB)", BASE_CART0, SIZE_CART0 }, + { "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, SIZE_CART1 }, + { "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, SIZE_CART2 }, + { "SRAM", "Static RAM (64kiB)", BASE_CART_SRAM, SIZE_CART_SRAM }, + { nullptr, nullptr, 0, 0 } +}; +#endif +#ifdef M_CORE_GB +const static struct IndexInfo indexInfoGB[] = { + { "All", "All", 0, 0x10000 }, + { "ROM", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_SIZE_CART_BANK0 * 2 }, + { "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_SIZE_VRAM }, + { "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM }, + { "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_SIZE_WORKING_RAM_BANK0 * 2 }, + { "OAM", "OBJ Attribute Memory", GB_BASE_OAM, GB_SIZE_OAM }, + { "IO", "Memory-Mapped I/O", GB_BASE_IO, GB_SIZE_IO }, + { "HRAM", "High RAM", GB_BASE_HRAM, GB_SIZE_HRAM }, + { nullptr, nullptr, 0, 0 } +}; +#endif + MemoryView::MemoryView(GameController* controller, QWidget* parent) : QWidget(parent) , m_controller(controller) @@ -23,7 +65,29 @@ MemoryView::MemoryView(GameController* controller, QWidget* parent) m_ui.hexfield->setController(controller); + mCore* core = m_controller->thread()->core; + const IndexInfo* info = nullptr; + switch (core->platform(core)) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + info = indexInfoGBA; + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + info = indexInfoGB; + break; +#endif + default: + break; + } + connect(m_ui.regions, SIGNAL(currentIndexChanged(int)), this, SLOT(setIndex(int))); + if (info) { + for (size_t i = 0; info[i].name; ++i) { + m_ui.regions->addItem(tr(info[i].longName)); + } + } connect(m_ui.width8, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(1); }); connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); }); @@ -41,25 +105,22 @@ MemoryView::MemoryView(GameController* controller, QWidget* parent) } void MemoryView::setIndex(int index) { - static struct { - const char* name; - uint32_t base; - uint32_t size; - } indexInfo[] = { - { "All", 0, 0x10000000 }, - { "BIOS", BASE_BIOS, SIZE_BIOS }, - { "EWRAM", BASE_WORKING_RAM, SIZE_WORKING_RAM }, - { "IWRAM", BASE_WORKING_IRAM, SIZE_WORKING_IRAM }, - { "MMIO", BASE_IO, SIZE_IO }, - { "Palette", BASE_PALETTE_RAM, SIZE_PALETTE_RAM }, - { "VRAM", BASE_VRAM, SIZE_VRAM }, - { "OAM", BASE_OAM, SIZE_OAM }, - { "ROM", BASE_CART0, SIZE_CART0 }, - { "ROM WS1", BASE_CART1, SIZE_CART1 }, - { "ROM WS2", BASE_CART2, SIZE_CART2 }, - { "SRAM", BASE_CART_SRAM, SIZE_CART_SRAM }, - }; - const auto& info = indexInfo[index]; + mCore* core = m_controller->thread()->core; + IndexInfo info; + switch (core->platform(core)) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + info = indexInfoGBA[index]; + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + info = indexInfoGB[index]; + break; +#endif + default: + return; + } m_ui.hexfield->setRegion(info.base, info.size, info.name); } @@ -84,7 +145,7 @@ void MemoryView::updateStatus() { if (!m_controller->isLoaded()) { return; } - ARMCore* cpu = static_cast(m_controller->thread()->core->cpu); + mCore* core = m_controller->thread()->core; union { uint32_t u32; int32_t i32; @@ -95,17 +156,17 @@ void MemoryView::updateStatus() { } value; switch (align) { case 1: - value.u8 = GBAView8(cpu, m_selection.first); + value.u8 = core->rawRead8(core, m_selection.first); m_ui.sintVal->setText(QString::number(value.i8)); m_ui.uintVal->setText(QString::number(value.u8)); break; case 2: - value.u16 = GBAView16(cpu, m_selection.first); + value.u16 = core->rawRead16(core, m_selection.first); m_ui.sintVal->setText(QString::number(value.i16)); m_ui.uintVal->setText(QString::number(value.u16)); break; case 4: - value.u32 = GBAView32(cpu, m_selection.first); + value.u32 = core->rawRead32(core, m_selection.first); m_ui.sintVal->setText(QString::number(value.i32)); m_ui.uintVal->setText(QString::number(value.u32)); break; diff --git a/src/platform/qt/MemoryView.ui b/src/platform/qt/MemoryView.ui index 59ff2ef7c..a840f0e7f 100644 --- a/src/platform/qt/MemoryView.ui +++ b/src/platform/qt/MemoryView.ui @@ -17,74 +17,19 @@ - - - - All - - - - - BIOS (16kiB) - - - - - Working RAM (256kiB) - - - - - Internal Working RAM (32kiB) - - - - - Memory-Mapped I/O - - - - - Palette RAM (1kiB) - - - - - Video RAM (96kiB) - - - - - OBJ Attribute Memory (1kiB) - - - - - Game Pak (32MiB) - - - - - Game Pak (Waitstate 1) - - - - - Game Pak (Waitstate 2) - - - - - Static RAM (64kiB) - - - + Qt::Horizontal + + + 0 + 0 + + @@ -126,6 +71,12 @@ Qt::Horizontal + + + 0 + 0 + + @@ -143,6 +94,12 @@ Qt::Horizontal + + + 0 + 0 + + @@ -157,6 +114,12 @@ Qt::Horizontal + + + 0 + 0 + + @@ -171,6 +134,12 @@ Qt::Horizontal + + + 0 + 0 + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index e38241da6..a07399e10 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1260,7 +1260,6 @@ void Window::setupMenu(QMenuBar* menubar) { QAction* memoryView = new QAction(tr("View memory..."), toolsMenu); connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow())); m_gameActions.append(memoryView); - m_gbaActions.append(memoryView); addControlledAction(toolsMenu, memoryView, "memoryView"); QAction* ioViewer = new QAction(tr("View &I/O registers..."), toolsMenu);