Qt: Add additional info to map view
@@ -7,7 +7,7 @@ - Debugger: Add unary operators and memory dereferencing
- GB: Expose platform information to CLI debugger - Support Discord Rich Presence - Debugger: Add tracing to file - - Map viewer supports bitmapped GBA modes + - Enhanced map viewer, supporting bitmapped GBA modes and more displayed info - OpenGL renderer with high-resolution upscaling support - Experimental high level "XQ" audio for most GBA games - Interframe blending for games that use flicker effects
@@ -0,0 +1,40 @@
+/* Copyright (c) 2013-2019 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 "AssetInfo.h" + +#include <QFontDatabase> +#include <QHBoxLayout> + +using namespace QGBA; + +AssetInfo::AssetInfo(QWidget* parent) + : QGroupBox(parent) +{ +} + +void AssetInfo::addCustomProperty(const QString& id, const QString& visibleName) { + QHBoxLayout* newLayout = new QHBoxLayout; + newLayout->addWidget(new QLabel(visibleName)); + QLabel* value = new QLabel; + value->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + value->setAlignment(Qt::AlignRight); + newLayout->addWidget(value); + m_customProperties[id] = value; + int index = customLocation(); + static_cast<QBoxLayout*>(layout())->insertLayout(index, newLayout); +} + +void AssetInfo::setCustomProperty(const QString& id, const QVariant& value) { + QLabel* label = m_customProperties[id]; + if (!label) { + return; + } + label->setText(value.toString()); +} + +int AssetInfo::customLocation(const QString&) { + return layout()->count(); +}
@@ -0,0 +1,34 @@
+/* Copyright (c) 2013-2019 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/. */ +#pragma once + +#include <QGroupBox> +#include <QHash> +#include <QLabel> +#include <QVariant> + +namespace QGBA { + +class CoreController; + +class AssetInfo : public QGroupBox { +Q_OBJECT + +public: + AssetInfo(QWidget* parent = nullptr); + void addCustomProperty(const QString& id, const QString& visibleName); + +public slots: + void setCustomProperty(const QString& id, const QVariant& value); + +protected: + virtual int customLocation(const QString& id = {}); + +private: + QHash<QString, QLabel*> m_customProperties; +}; + +}
@@ -22,7 +22,7 @@
using namespace QGBA; AssetTile::AssetTile(QWidget* parent) - : QGroupBox(parent) + : AssetInfo(parent) { m_ui.setupUi(this);@@ -42,16 +42,8 @@ m_ui.g->setFont(font);
m_ui.b->setFont(font); } -void AssetTile::addCustomProperty(const QString& id, const QString& visibleName) { - QHBoxLayout* newLayout = new QHBoxLayout; - newLayout->addWidget(new QLabel(visibleName)); - QLabel* value = new QLabel; - value->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - value->setAlignment(Qt::AlignRight); - newLayout->addWidget(value); - m_customProperties[id] = value; - int index = layout()->indexOf(m_ui.line); - static_cast<QBoxLayout*>(layout())->insertLayout(index, newLayout); +int AssetTile::customLocation(const QString&) { + return layout()->indexOf(m_ui.line); } void AssetTile::setController(std::shared_ptr<CoreController> controller) {@@ -149,11 +141,3 @@ m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0')));
m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0'))); } - -void AssetTile::setCustomProperty(const QString& id, const QVariant& value) { - QLabel* label = m_customProperties[id]; - if (!label) { - return; - } - label->setText(value.toString()); -}
@@ -15,13 +15,12 @@ namespace QGBA {
class CoreController; -class AssetTile : public QGroupBox { +class AssetTile : public AssetInfo { Q_OBJECT public: AssetTile(QWidget* parent = nullptr); void setController(std::shared_ptr<CoreController>); - void addCustomProperty(const QString& id, const QString& visibleName); public slots: void setPalette(int);@@ -29,7 +28,9 @@ void setBoundary(int boundary, int set0, int set1);
void selectIndex(int); void setFlip(bool h, bool v); void selectColor(int); - void setCustomProperty(const QString& id, const QVariant& value); + +protected: + int customLocation(const QString& id = {}) override; private: Ui::AssetTile m_ui;
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>AssetTile</class> - <widget class="QGroupBox" name="AssetTile"> + <widget class="QGBA::AssetInfo" name="AssetTile"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>171</width> - <height>355</height> + <width>241</width> + <height>406</height> </rect> </property> <property name="sizePolicy">@@ -185,6 +185,12 @@ </item>
</layout> </widget> <customwidgets> + <customwidget> + <class>QGBA::AssetInfo</class> + <extends>QGroupBox</extends> + <header>AssetInfo.h</header> + <container>1</container> + </customwidget> <customwidget> <class>QGBA::Swatch</class> <extends>QWidget</extends>
@@ -59,6 +59,7 @@ AboutScreen.cpp
AbstractUpdater.cpp Action.cpp ActionMapper.cpp + AssetInfo.cpp AssetTile.cpp AssetView.cpp AudioProcessor.cpp
@@ -18,6 +18,7 @@ #include <mgba/internal/gba/memory.h>
#include <mgba/internal/gba/video.h> #endif #ifdef M_CORE_GB +#include <mgba/internal/gb/gb.h> #include <mgba/internal/gb/memory.h> #endif@@ -42,6 +43,12 @@ case PLATFORM_GBA:
m_boundary = 2048; m_addressBase = BASE_VRAM; m_addressWidth = 8; + m_ui.bgInfo->addCustomProperty("priority", tr("Priority")); + m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base")); + m_ui.bgInfo->addCustomProperty("charBase", tr("Tile base")); + m_ui.bgInfo->addCustomProperty("size", tr("Size")); + m_ui.bgInfo->addCustomProperty("offset", tr("Offset")); + m_ui.bgInfo->addCustomProperty("transform", tr("Xform")); break; #endif #ifdef M_CORE_GB@@ -49,6 +56,9 @@ case PLATFORM_GB:
m_boundary = 1024; m_addressBase = GB_BASE_VRAM; m_addressWidth = 4; + m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base")); + m_ui.bgInfo->addCustomProperty("charBase", tr("Tile base")); + m_ui.bgInfo->addCustomProperty("offset", tr("Offset")); break; #endif default:@@ -143,16 +153,58 @@ void MapView::updateTilesGBA(bool force) {
{ CoreController::Interrupter interrupter(m_controller); int bitmap = -1; + int priority = -1; + int frame = 0; + QString offset(tr("N/A")); + QString transform(tr("N/A")); if (m_controller->platform() == PLATFORM_GBA) { - int mode = GBARegisterDISPCNTGetMode(static_cast<GBA*>(m_controller->thread()->core->board)->memory.io[REG_DISPCNT]); + uint16_t* io = static_cast<GBA*>(m_controller->thread()->core->board)->memory.io; + int mode = GBARegisterDISPCNTGetMode(io[REG_DISPCNT >> 1]); if (m_map == 2 && mode > 2) { bitmap = mode == 4 ? 1 : 0; + if (mode != 3) { + frame = GBARegisterDISPCNTGetFrameSelect(io[REG_DISPCNT >> 1]); + } } + priority = GBARegisterBGCNTGetPriority(io[(REG_BG0CNT >> 1) + m_map]); + if (mode == 0 || (mode == 1 && m_map != 2)) { + offset = QString("%1, %2") + .arg(io[(REG_BG0HOFS >> 1) + (m_map << 1)]) + .arg(io[(REG_BG0VOFS >> 1) + (m_map << 1)]); + } else if ((mode > 0 && m_map == 2) || (mode == 2 && m_map == 3)) { + int32_t refX = io[(REG_BG2X_LO >> 1) + ((m_map - 2) << 2)]; + refX |= io[(REG_BG2X_HI >> 1) + ((m_map - 2) << 2)] << 16; + int32_t refY = io[(REG_BG2Y_LO >> 1) + ((m_map - 2) << 2)]; + refY |= io[(REG_BG2Y_HI >> 1) + ((m_map - 2) << 2)] << 16; + refX <<= 4; + refY <<= 4; + refX >>= 4; + refY >>= 4; + offset = QString("%1\n%2").arg(refX / 65536., 0, 'f', 3).arg(refY / 65536., 0, 'f', 3); + transform = QString("%1 %2\n%3 %4") + .arg(io[(REG_BG2PA >> 1) + ((m_map - 2) << 2)] / 256., 3, 'f', 2) + .arg(io[(REG_BG2PB >> 1) + ((m_map - 2) << 2)] / 256., 3, 'f', 2) + .arg(io[(REG_BG2PC >> 1) + ((m_map - 2) << 2)] / 256., 3, 'f', 2) + .arg(io[(REG_BG2PD >> 1) + ((m_map - 2) << 2)] / 256., 3, 'f', 2); + + } + } + if (m_controller->platform() == PLATFORM_GB) { + uint8_t* io = static_cast<GB*>(m_controller->thread()->core->board)->memory.io; + int x = io[m_map == 0 ? 0x42 : 0x4A]; + int y = io[m_map == 0 ? 0x43 : 0x4B]; + offset = QString("%1, %2").arg(x).arg(y); } if (bitmap >= 0) { mBitmapCache* bitmapCache = mBitmapCacheSetGetPointer(&m_cacheSet->bitmaps, bitmap); int width = mBitmapCacheSystemInfoGetWidth(bitmapCache->sysConfig); int height = mBitmapCacheSystemInfoGetHeight(bitmapCache->sysConfig); + m_ui.bgInfo->setCustomProperty("screenBase", QString("0x%1").arg(m_addressBase + bitmapCache->bitsStart[frame], 8, 16, QChar('0'))); + m_ui.bgInfo->setCustomProperty("charBase", tr("N/A")); + m_ui.bgInfo->setCustomProperty("size", QString("%1×%2").arg(width).arg(height)); + m_ui.bgInfo->setCustomProperty("priority", priority); + m_ui.bgInfo->setCustomProperty("offset", offset); + m_ui.bgInfo->setCustomProperty("transform", transform); m_rawMap = QImage(QSize(width, height), QImage::Format_ARGB32); uchar* bgBits = m_rawMap.bits(); for (int j = 0; j < height; ++j) {@@ -163,6 +215,16 @@ } else {
mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig); int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig); + m_ui.bgInfo->setCustomProperty("screenBase", QString("%0%1") + .arg(m_addressWidth == 8 ? "0x" : "") + .arg(m_addressBase + mapCache->mapStart, m_addressWidth, 16, QChar('0'))); + m_ui.bgInfo->setCustomProperty("charBase", QString("%0%1") + .arg(m_addressWidth == 8 ? "0x" : "") + .arg(m_addressBase + mapCache->tileCache->tileBase, m_addressWidth, 16, QChar('0'))); + m_ui.bgInfo->setCustomProperty("size", QString("%1×%2").arg(tilesW * 8).arg(tilesH * 8)); + m_ui.bgInfo->setCustomProperty("priority", priority); + m_ui.bgInfo->setCustomProperty("offset", offset); + m_ui.bgInfo->setCustomProperty("transform", transform); m_rawMap = QImage(QSize(tilesW * 8, tilesH * 8), QImage::Format_ARGB32); uchar* bgBits = m_rawMap.bits(); for (int j = 0; j < tilesH; ++j) {
@@ -6,18 +6,80 @@ <property name="geometry">
<rect> <x>0</x> <y>0</y> - <width>641</width> - <height>489</height> + <width>1273</width> + <height>736</height> </rect> </property> <property name="windowTitle"> <string>Maps</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <layout class="QVBoxLayout" name="bgLayout"/> + <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0"> + <item row="3" column="0"> + <widget class="QGBA::AssetTile" name="tile"/> + </item> + <item row="2" column="0"> + <widget class="QGBA::AssetInfo" name="bgInfo"> + <property name="title"> + <string/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"/> + </widget> + </item> + <item row="5" column="0"> + <widget class="QPushButton" name="exportButton"> + <property name="text"> + <string>Export</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="bgLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QSpinBox" name="magnification"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix"> + <string>×</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>8</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Magnification</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> </item> - <item row="0" column="1" rowspan="5"> + <item row="1" column="1" rowspan="5" colspan="2"> <widget class="QScrollArea" name="scrollArea"> <property name="widgetResizable"> <bool>true</bool>@@ -30,8 +92,8 @@ <property name="geometry">
<rect> <x>0</x> <y>0</y> - <width>457</width> - <height>463</height> + <width>835</width> + <height>720</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout">@@ -71,62 +133,15 @@ </layout>
</widget> </widget> </item> - <item row="2" column="0"> - <widget class="QGBA::AssetTile" name="tile"/> - </item> - <item row="4" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QSpinBox" name="magnification"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="suffix"> - <string>×</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>8</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Magnification</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="3" column="0"> - <widget class="QPushButton" name="exportButton"> - <property name="text"> - <string>Export</string> - </property> - </widget> - </item> </layout> </widget> <customwidgets> + <customwidget> + <class>QGBA::AssetInfo</class> + <extends>QGroupBox</extends> + <header>AssetInfo.h</header> + <container>1</container> + </customwidget> <customwidget> <class>QGBA::AssetTile</class> <extends>QGroupBox</extends>