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}