GB Core: Add rawRead* and enable memory viewer for Game Boy

This commit is contained in:
Jeffrey Pfau 2016-05-05 23:52:28 -07:00
parent 1326626777
commit 4b5885624b
7 changed files with 146 additions and 95 deletions

View File

@ -295,6 +295,22 @@ static void _GBCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t val
cpu->memory.store8(cpu, address + 3, value >> 24); 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) { static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
UNUSED(core); UNUSED(core);
switch (type) { switch (type) {
@ -389,9 +405,9 @@ struct mCore* GBCoreCreate(void) {
core->busWrite8 = _GBCoreBusWrite8; core->busWrite8 = _GBCoreBusWrite8;
core->busWrite16 = _GBCoreBusWrite16; core->busWrite16 = _GBCoreBusWrite16;
core->busWrite32 = _GBCoreBusWrite32; core->busWrite32 = _GBCoreBusWrite32;
core->rawRead8 = NULL; core->rawRead8 = _GBCoreRawRead8;
core->rawRead16 = NULL; core->rawRead16 = _GBCoreRawRead16;
core->rawRead32 = NULL; core->rawRead32 = _GBCoreRawRead32;
core->rawWrite8 = NULL; core->rawWrite8 = NULL;
core->rawWrite16 = NULL; core->rawWrite16 = NULL;
core->rawWrite32 = NULL; core->rawWrite32 = NULL;

View File

@ -467,8 +467,6 @@ void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
GBStore8(cpu, address, 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); void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old);
static void _switchBank(struct GBMemory* memory, int bank) { static void _switchBank(struct GBMemory* memory, int bank) {

View File

@ -171,10 +171,6 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value);
uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address); uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address);
void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value); 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); void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old);
#endif #endif

View File

@ -210,12 +210,18 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight; int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight;
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
int yp = m_cellHeight * y + m_margins.top(); 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(); 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); painter.drawText(QRectF(QPointF(0, yp), QSizeF(m_margins.left(), m_cellHeight)), Qt::AlignHCenter, data);
switch (m_align) { switch (m_align) {
case 2: case 2:
for (int x = 0; x < 16; x += 2) { for (int x = 0; x < 16; x += 2) {
uint32_t address = (y + m_top) * 16 + x + m_base; uint32_t address = (y + m_top) * 16 + x + m_base;
if (address >= m_base + m_size) {
break;
}
if (isInSelection(address)) { if (isInSelection(address)) {
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp),
QSizeF(m_cellSize.width() * 2, m_cellSize.height())), QSizeF(m_cellSize.width() * 2, m_cellSize.height())),
@ -241,6 +247,9 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
case 4: case 4:
for (int x = 0; x < 16; x += 4) { for (int x = 0; x < 16; x += 4) {
uint32_t address = (y + m_top) * 16 + x + m_base; uint32_t address = (y + m_top) * 16 + x + m_base;
if (address >= m_base + m_size) {
break;
}
if (isInSelection(address)) { if (isInSelection(address)) {
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp),
QSizeF(m_cellSize.width() * 4, m_cellSize.height())), QSizeF(m_cellSize.width() * 4, m_cellSize.height())),
@ -273,6 +282,9 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
default: default:
for (int x = 0; x < 16; ++x) { for (int x = 0; x < 16; ++x) {
uint32_t address = (y + m_top) * 16 + x + m_base; uint32_t address = (y + m_top) * 16 + x + m_base;
if (address >= m_base + m_size) {
break;
}
if (isInSelection(address)) { if (isInSelection(address)) {
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), m_cellSize), painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), m_cellSize),
palette.highlight()); palette.highlight());

View File

@ -10,11 +10,53 @@
extern "C" { extern "C" {
#include "core/core.h" #include "core/core.h"
#ifdef M_CORE_GBA
#include "gba/memory.h" #include "gba/memory.h"
#endif
#ifdef M_CORE_GB
#include "gb/memory.h"
#endif
} }
using namespace QGBA; 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) MemoryView::MemoryView(GameController* controller, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_controller(controller) , m_controller(controller)
@ -23,7 +65,29 @@ MemoryView::MemoryView(GameController* controller, QWidget* parent)
m_ui.hexfield->setController(controller); 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))); 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.width8, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(1); });
connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); }); 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) { void MemoryView::setIndex(int index) {
static struct { mCore* core = m_controller->thread()->core;
const char* name; IndexInfo info;
uint32_t base; switch (core->platform(core)) {
uint32_t size; #ifdef M_CORE_GBA
} indexInfo[] = { case PLATFORM_GBA:
{ "All", 0, 0x10000000 }, info = indexInfoGBA[index];
{ "BIOS", BASE_BIOS, SIZE_BIOS }, break;
{ "EWRAM", BASE_WORKING_RAM, SIZE_WORKING_RAM }, #endif
{ "IWRAM", BASE_WORKING_IRAM, SIZE_WORKING_IRAM }, #ifdef M_CORE_GB
{ "MMIO", BASE_IO, SIZE_IO }, case PLATFORM_GB:
{ "Palette", BASE_PALETTE_RAM, SIZE_PALETTE_RAM }, info = indexInfoGB[index];
{ "VRAM", BASE_VRAM, SIZE_VRAM }, break;
{ "OAM", BASE_OAM, SIZE_OAM }, #endif
{ "ROM", BASE_CART0, SIZE_CART0 }, default:
{ "ROM WS1", BASE_CART1, SIZE_CART1 }, return;
{ "ROM WS2", BASE_CART2, SIZE_CART2 }, }
{ "SRAM", BASE_CART_SRAM, SIZE_CART_SRAM },
};
const auto& info = indexInfo[index];
m_ui.hexfield->setRegion(info.base, info.size, info.name); m_ui.hexfield->setRegion(info.base, info.size, info.name);
} }
@ -84,7 +145,7 @@ void MemoryView::updateStatus() {
if (!m_controller->isLoaded()) { if (!m_controller->isLoaded()) {
return; return;
} }
ARMCore* cpu = static_cast<ARMCore*>(m_controller->thread()->core->cpu); mCore* core = m_controller->thread()->core;
union { union {
uint32_t u32; uint32_t u32;
int32_t i32; int32_t i32;
@ -95,17 +156,17 @@ void MemoryView::updateStatus() {
} value; } value;
switch (align) { switch (align) {
case 1: 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.sintVal->setText(QString::number(value.i8));
m_ui.uintVal->setText(QString::number(value.u8)); m_ui.uintVal->setText(QString::number(value.u8));
break; break;
case 2: 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.sintVal->setText(QString::number(value.i16));
m_ui.uintVal->setText(QString::number(value.u16)); m_ui.uintVal->setText(QString::number(value.u16));
break; break;
case 4: 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.sintVal->setText(QString::number(value.i32));
m_ui.uintVal->setText(QString::number(value.u32)); m_ui.uintVal->setText(QString::number(value.u32));
break; break;

View File

@ -17,74 +17,19 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QComboBox" name="regions"> <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>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
<item> <item>
@ -126,6 +71,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
<item> <item>
@ -143,6 +94,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
<item> <item>
@ -157,6 +114,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
<item> <item>
@ -171,6 +134,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
</layout> </layout>

View File

@ -1260,7 +1260,6 @@ void Window::setupMenu(QMenuBar* menubar) {
QAction* memoryView = new QAction(tr("View memory..."), toolsMenu); QAction* memoryView = new QAction(tr("View memory..."), toolsMenu);
connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow())); connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow()));
m_gameActions.append(memoryView); m_gameActions.append(memoryView);
m_gbaActions.append(memoryView);
addControlledAction(toolsMenu, memoryView, "memoryView"); addControlledAction(toolsMenu, memoryView, "memoryView");
QAction* ioViewer = new QAction(tr("View &I/O registers..."), toolsMenu); QAction* ioViewer = new QAction(tr("View &I/O registers..."), toolsMenu);