GB Core: Add rawRead* and enable memory viewer for Game Boy
@@ -295,6 +295,22 @@ cpu->memory.store8(cpu, address + 2, value >> 16);
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 @@ core->busRead32 = _GBCoreBusRead32;
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;
@@ -467,8 +467,6 @@ }
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) {
@@ -171,10 +171,6 @@
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
@@ -210,12 +210,18 @@ }
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 @@ break;
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 @@ case 1:
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());
@@ -10,11 +10,53 @@ #include "GameController.h"
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 @@ m_ui.setupUi(this);
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 @@ connect(controller, SIGNAL(rewound(mCoreThread*)), this, SLOT(update()));
} 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 @@ }
if (!m_controller->isLoaded()) { return; } - ARMCore* cpu = static_cast<ARMCore*>(m_controller->thread()->core->cpu); + mCore* core = m_controller->thread()->core; union { uint32_t u32; int32_t i32;@@ -95,17 +156,17 @@ int8_t i8;
} 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;
@@ -17,73 +17,18 @@ <layout class="QVBoxLayout" name="verticalLayout">
<item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QComboBox" name="regions"> - <item> - <property name="text"> - <string>All</string> - </property> - </item> - <item> - <property name="text"> - <string>BIOS (16kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Working RAM (256kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Internal Working RAM (32kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Memory-Mapped I/O</string> - </property> - </item> - <item> - <property name="text"> - <string>Palette RAM (1kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Video RAM (96kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>OBJ Attribute Memory (1kiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Game Pak (32MiB)</string> - </property> - </item> - <item> - <property name="text"> - <string>Game Pak (Waitstate 1)</string> - </property> - </item> - <item> - <property name="text"> - <string>Game Pak (Waitstate 2)</string> - </property> - </item> - <item> - <property name="text"> - <string>Static RAM (64kiB)</string> - </property> - </item> - </widget> + <widget class="QComboBox" name="regions"/> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> </property> </spacer> </item>@@ -126,6 +71,12 @@ <spacer name="horizontalSpacer_2">
<property name="orientation"> <enum>Qt::Horizontal</enum> </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> </spacer> </item> <item>@@ -143,6 +94,12 @@ <spacer name="horizontalSpacer_4">
<property name="orientation"> <enum>Qt::Horizontal</enum> </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> </spacer> </item> <item>@@ -157,6 +114,12 @@ <spacer name="horizontalSpacer_5">
<property name="orientation"> <enum>Qt::Horizontal</enum> </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> </spacer> </item> <item>@@ -170,6 +133,12 @@ <item>
<spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> </property> </spacer> </item>
@@ -1260,7 +1260,6 @@
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);