diff --git a/CHANGES b/CHANGES index 3366a9ea9..b6a6143fe 100644 --- a/CHANGES +++ b/CHANGES @@ -7,7 +7,7 @@ Features: - 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 diff --git a/src/platform/qt/AssetInfo.cpp b/src/platform/qt/AssetInfo.cpp new file mode 100644 index 000000000..f70d8ea0d --- /dev/null +++ b/src/platform/qt/AssetInfo.cpp @@ -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 +#include + +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(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(); +} \ No newline at end of file diff --git a/src/platform/qt/AssetInfo.h b/src/platform/qt/AssetInfo.h new file mode 100644 index 000000000..c30a4f4c5 --- /dev/null +++ b/src/platform/qt/AssetInfo.h @@ -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 +#include +#include +#include + +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 m_customProperties; +}; + +} diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index ad16d47a3..ea3bcb28c 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -22,7 +22,7 @@ using namespace QGBA; AssetTile::AssetTile(QWidget* parent) - : QGroupBox(parent) + : AssetInfo(parent) { m_ui.setupUi(this); @@ -42,16 +42,8 @@ AssetTile::AssetTile(QWidget* parent) 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(layout())->insertLayout(index, newLayout); +int AssetTile::customLocation(const QString&) { + return layout()->indexOf(m_ui.line); } void AssetTile::setController(std::shared_ptr controller) { @@ -149,11 +141,3 @@ void AssetTile::selectColor(int index) { 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()); -} diff --git a/src/platform/qt/AssetTile.h b/src/platform/qt/AssetTile.h index 35dd14e5b..676582387 100644 --- a/src/platform/qt/AssetTile.h +++ b/src/platform/qt/AssetTile.h @@ -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); - void addCustomProperty(const QString& id, const QString& visibleName); public slots: void setPalette(int); @@ -29,7 +28,9 @@ public slots: 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; diff --git a/src/platform/qt/AssetTile.ui b/src/platform/qt/AssetTile.ui index e5557506b..403e26d60 100644 --- a/src/platform/qt/AssetTile.ui +++ b/src/platform/qt/AssetTile.ui @@ -1,13 +1,13 @@ AssetTile - + 0 0 - 171 - 355 + 241 + 406 @@ -185,6 +185,12 @@ + + QGBA::AssetInfo + QGroupBox +
AssetInfo.h
+ 1 +
QGBA::Swatch QWidget diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index e5ae84e58..0dbb75efa 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -59,6 +59,7 @@ set(SOURCE_FILES AbstractUpdater.cpp Action.cpp ActionMapper.cpp + AssetInfo.cpp AssetTile.cpp AssetView.cpp AudioProcessor.cpp diff --git a/src/platform/qt/MapView.cpp b/src/platform/qt/MapView.cpp index a0232c50b..91a283121 100644 --- a/src/platform/qt/MapView.cpp +++ b/src/platform/qt/MapView.cpp @@ -18,6 +18,7 @@ #include #endif #ifdef M_CORE_GB +#include #include #endif @@ -42,6 +43,12 @@ MapView::MapView(std::shared_ptr controller, QWidget* parent) 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 @@ MapView::MapView(std::shared_ptr controller, QWidget* parent) 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(m_controller->thread()->core->board)->memory.io[REG_DISPCNT]); + uint16_t* io = static_cast(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(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 @@ void MapView::updateTilesGBA(bool force) { 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) { diff --git a/src/platform/qt/MapView.ui b/src/platform/qt/MapView.ui index d07a832b5..b9d5418f3 100644 --- a/src/platform/qt/MapView.ui +++ b/src/platform/qt/MapView.ui @@ -6,18 +6,80 @@ 0 0 - 641 - 489 + 1273 + 736 Maps - - - + + + - + + + + + + + + + + + + Export + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + + + + × + + + 1 + + + 8 + + + + + + + Magnification + + + + + + + + true @@ -30,8 +92,8 @@ 0 0 - 457 - 463 + 835 + 720 @@ -71,62 +133,15 @@
- - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - × - - - 1 - - - 8 - - - - - - - Magnification - - - - - - - - - Export - - - + + QGBA::AssetInfo + QGroupBox +
AssetInfo.h
+ 1 +
QGBA::AssetTile QGroupBox