/* Copyright (c) 2013-2015 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MemoryView.h" #include "GameController.h" extern "C" { #include "gba/memory.h" } using namespace QGBA; MemoryView::MemoryView(GameController* controller, QWidget* parent) : QWidget(parent) , m_controller(controller) { m_ui.setupUi(this); m_ui.hexfield->setController(controller); connect(m_ui.regions, SIGNAL(currentIndexChanged(int)), this, SLOT(setIndex(int))); 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.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); }); connect(m_ui.setAddress, SIGNAL(valueChanged(const QString&)), m_ui.hexfield, SLOT(jumpToAddress(const QString&))); connect(m_ui.hexfield, SIGNAL(selectionChanged(uint32_t, uint32_t)), this, SLOT(updateStatus(uint32_t, uint32_t))); connect(controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(close())); } 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]; m_ui.hexfield->setRegion(info.base, info.size, info.name); } void MemoryView::updateStatus(uint32_t start, uint32_t end) { int align = m_ui.hexfield->alignment(); if (start & (align - 1) || end - start != align) { m_ui.sintVal->clear(); m_ui.uintVal->clear(); return; } ARMCore* cpu = m_controller->thread()->cpu; union { uint32_t u32; int32_t i32; uint16_t u16; int16_t i16; uint8_t u8; int8_t i8; } value; switch (align) { case 1: value.u8 = cpu->memory.load8(cpu, start, nullptr); m_ui.sintVal->setText(QString::number(value.i8)); m_ui.uintVal->setText(QString::number(value.u8)); break; case 2: value.u16 = cpu->memory.load16(cpu, start, nullptr); m_ui.sintVal->setText(QString::number(value.i16)); m_ui.uintVal->setText(QString::number(value.u16)); break; case 4: value.u32 = cpu->memory.load32(cpu, start, nullptr); m_ui.sintVal->setText(QString::number(value.i32)); m_ui.uintVal->setText(QString::number(value.u32)); break; } }