all repos — mgba @ 10d5588d4cc543f07b4f6bf21e8a3bac63fb02f3

mGBA Game Boy Advance Emulator

src/platform/qt/MemoryModel.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#include "MemoryModel.h"
  7
  8#include "GameController.h"
  9
 10#include <QFontMetrics>
 11#include <QPainter>
 12#include <QScrollBar>
 13#include <QSlider>
 14#include <QWheelEvent>
 15
 16extern "C" {
 17#include "gba/memory.h"
 18}
 19
 20using namespace QGBA;
 21
 22MemoryModel::MemoryModel(QWidget* parent)
 23	: QAbstractScrollArea(parent)
 24	, m_top(0)
 25{
 26	m_font.setFamily("Source Code Pro");
 27	m_font.setStyleHint(QFont::Monospace);
 28	m_font.setPointSize(12);
 29	QFontMetrics metrics(m_font);
 30	m_cellHeight = metrics.height();
 31	m_letterWidth = metrics.averageCharWidth();
 32
 33	for (int i = 0; i < 256; ++i) {
 34		QStaticText str(QString("%0").arg(i, 2, 16, QChar('0')).toUpper());
 35		str.prepare(QTransform(), m_font);
 36		m_staticNumbers.append(str);
 37	}
 38
 39	for (int i = 0; i < 128; ++i) {
 40		QChar c(0xFFFD);
 41		if (c.isPrint()) {
 42			c = i;
 43		}
 44		QStaticText str = QStaticText(QString(c));
 45		str.prepare(QTransform(), m_font);
 46		m_staticAscii.append(str);
 47	}
 48
 49	setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 50	setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
 51	m_margins = QMargins(metrics.width("FFFFFF ") + 3, m_cellHeight + 1, metrics.width(" AAAAAAAAAAAAAAAA") + 3, 0);
 52
 53	verticalScrollBar()->setRange(0, 0x01000001 - viewport()->size().height() / m_cellHeight);
 54	connect(verticalScrollBar(), &QSlider::sliderMoved, [this](int position) {
 55		m_top = position;
 56		update();
 57	});
 58	update();
 59}
 60
 61void MemoryModel::setController(GameController* controller) {
 62	m_cpu = controller->thread()->cpu;
 63}
 64
 65void MemoryModel::resizeEvent(QResizeEvent*) {
 66	verticalScrollBar()->setRange(0, 0x01000001 - viewport()->size().height() / m_cellHeight);
 67	boundsCheck();
 68}
 69
 70void MemoryModel::paintEvent(QPaintEvent* event) {
 71	QPainter painter(viewport());
 72	painter.setFont(m_font);
 73	QChar c0('0');
 74	QSizeF cellSize = QSizeF((viewport()->size().width() - (m_margins.left() + m_margins.right())) / 16.f, m_cellHeight);
 75	QSizeF letterSize = QSizeF(m_letterWidth, m_cellHeight);
 76	painter.drawText(QRect(QPoint(0, 0), QSize(m_margins.left(), m_margins.top())), Qt::AlignHCenter, tr("All"));
 77	painter.drawText(QRect(QPoint(viewport()->size().width() - m_margins.right(), 0), QSize(m_margins.right(), m_margins.top())), Qt::AlignHCenter, tr("ASCII"));
 78	for (int x = 0; x < 16; ++x) {
 79		painter.drawText(QRectF(QPointF(cellSize.width() * x + m_margins.left(), 0), cellSize), Qt::AlignHCenter, QString::number(x, 16).toUpper());
 80	}
 81	int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight;
 82	for (int y = 0; y < height; ++y) {
 83		int yp = m_cellHeight * y + m_margins.top();
 84		QString data = QString("%0").arg(y + m_top, 6, 16, c0).toUpper();
 85		painter.drawText(QRectF(QPointF(0, yp), QSizeF(m_margins.left(), m_cellHeight)), Qt::AlignHCenter, data);
 86		for (int x = 0; x < 16; ++x) {
 87			uint8_t b = m_cpu->memory.load8(m_cpu, (y + m_top) * 16 + x, nullptr);
 88			painter.drawStaticText(QPointF(cellSize.width() * (x + 0.5) - m_letterWidth + m_margins.left(), yp), m_staticNumbers[b]);
 89			painter.drawStaticText(QPointF(viewport()->size().width() - (16 - x) * m_margins.right() / 17.0 - m_letterWidth * 0.5, yp), b < 0x80 ? m_staticAscii[b] : m_staticAscii[0]);
 90		}
 91	}
 92	painter.drawLine(m_margins.left() - 2, 0, m_margins.left() - 2, viewport()->size().height());
 93	painter.drawLine(viewport()->size().width() - m_margins.right(), 0, viewport()->size().width() - m_margins.right(), viewport()->size().height());
 94	painter.drawLine(0, m_margins.top(), viewport()->size().width(), m_margins.top());
 95}
 96
 97void MemoryModel::wheelEvent(QWheelEvent* event) {
 98	m_top -= event->angleDelta().y() / 8;
 99	boundsCheck();
100	event->accept();
101	update();
102	QAbstractScrollArea::wheelEvent(event);
103}
104
105void MemoryModel::boundsCheck() {
106	if (m_top < 0) {
107		m_top = 0;
108	} else if (m_top > 0x01000001 - viewport()->size().height() / m_cellHeight) {
109		m_top = 0x01000001 - viewport()->size().height() / m_cellHeight;
110	}
111}