all repos — mgba @ 7d79db7d7d31f5a956123e751f455eee9d4b043e

mGBA Game Boy Advance Emulator

src/platform/qt/MemoryView.cpp (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6
  7#include "MemoryView.h"
  8
  9#include "CoreController.h"
 10
 11#include <mgba/core/core.h>
 12
 13using namespace QGBA;
 14
 15MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent)
 16	: QWidget(parent)
 17	, m_controller(controller)
 18{
 19	m_ui.setupUi(this);
 20
 21	m_ui.hexfield->setController(controller);
 22
 23	mCore* core = m_controller->thread()->core;
 24	const mCoreMemoryBlock* info;
 25	size_t nBlocks = core->listMemoryBlocks(core, &info);
 26
 27	connect(m_ui.regions, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
 28	        this, &MemoryView::setIndex);
 29	connect(m_ui.segments, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
 30	        this, &MemoryView::setSegment);
 31
 32	if (info) {
 33		for (size_t i = 0; i < nBlocks; ++i) {
 34			if (!(info[i].flags & (mCORE_MEMORY_MAPPED | mCORE_MEMORY_VIRTUAL))) {
 35				continue;
 36			}
 37			m_ui.regions->addItem(tr(info[i].longName));
 38		}
 39	}
 40
 41	connect(m_ui.width8, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(1); });
 42	connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); });
 43	connect(m_ui.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); });
 44	connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
 45	        m_ui.hexfield, static_cast<void (MemoryModel::*)(uint32_t)>(&MemoryModel::jumpToAddress));
 46	connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
 47
 48	connect(controller.get(), &CoreController::stopping, this, &QWidget::close);
 49
 50	connect(controller.get(), &CoreController::frameAvailable, this, &MemoryView::update);
 51	connect(controller.get(), &CoreController::paused, this, &MemoryView::update);
 52	connect(controller.get(), &CoreController::stateLoaded, this, &MemoryView::update);
 53	connect(controller.get(), &CoreController::rewound, this, &MemoryView::update);
 54
 55	connect(m_ui.copy, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::copy);
 56	connect(m_ui.save, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::save);
 57	connect(m_ui.paste, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::paste);
 58	connect(m_ui.load, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::load);
 59
 60	connect(m_ui.loadTBL, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::loadTBL);
 61}
 62
 63void MemoryView::setIndex(int index) {
 64	mCore* core = m_controller->thread()->core;
 65	const mCoreMemoryBlock* blocks;
 66	size_t nBlocks = core->listMemoryBlocks(core, &blocks);
 67	const mCoreMemoryBlock& info = blocks[index];
 68
 69	m_ui.segments->setValue(-1);
 70	m_ui.segments->setVisible(info.maxSegment > 0);
 71	m_ui.segments->setMaximum(info.maxSegment);
 72	m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
 73}
 74
 75void MemoryView::setSegment(int segment) {
 76	mCore* core = m_controller->thread()->core;
 77	const mCoreMemoryBlock* blocks;
 78	size_t nBlocks = core->listMemoryBlocks(core, &blocks);
 79	const mCoreMemoryBlock& info = blocks[m_ui.regions->currentIndex()];
 80
 81	m_ui.hexfield->setSegment(info.maxSegment < segment ? info.maxSegment : segment);
 82}
 83
 84void MemoryView::update() {
 85	m_ui.hexfield->viewport()->update();
 86	updateStatus();
 87}
 88
 89void MemoryView::updateSelection(uint32_t start, uint32_t end) {
 90	m_selection.first = start;
 91	m_selection.second = end;
 92	updateStatus();
 93}
 94
 95void MemoryView::updateStatus() {
 96	int align = m_ui.hexfield->alignment();
 97	mCore* core = m_controller->thread()->core;
 98	QByteArray selection(m_ui.hexfield->serialize());
 99	QString text(m_ui.hexfield->decodeText(selection));
100	m_ui.stringVal->setText(text);
101
102	if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) {
103		m_ui.sintVal->clear();
104		m_ui.uintVal->clear();
105		return;
106	}
107	union {
108		uint32_t u32;
109		int32_t i32;
110		uint16_t u16;
111		int16_t i16;
112		uint8_t u8;
113		int8_t i8;
114	} value;
115	switch (align) {
116	case 1:
117		value.u8 = core->rawRead8(core, m_selection.first, m_ui.segments->value());
118		m_ui.sintVal->setText(QString::number(value.i8));
119		m_ui.uintVal->setText(QString::number(value.u8));
120		break;
121	case 2:
122		value.u16 = core->rawRead16(core, m_selection.first, m_ui.segments->value());
123		m_ui.sintVal->setText(QString::number(value.i16));
124		m_ui.uintVal->setText(QString::number(value.u16));
125		break;
126	case 4:
127		value.u32 = core->rawRead32(core, m_selection.first, m_ui.segments->value());
128		m_ui.sintVal->setText(QString::number(value.i32));
129		m_ui.uintVal->setText(QString::number(value.u32));
130		break;
131	}
132}