mirror of https://github.com/mgba-emu/mgba.git
Qt: First pass at a tile view
This commit is contained in:
parent
739df1ed74
commit
b1f750e441
|
@ -102,6 +102,8 @@ set(SOURCE_FILES
|
|||
ShortcutController.cpp
|
||||
ShortcutView.cpp
|
||||
Swatch.cpp
|
||||
TilePainter.cpp
|
||||
TileView.cpp
|
||||
Window.cpp
|
||||
VFileDevice.cpp
|
||||
VideoView.cpp)
|
||||
|
@ -121,6 +123,7 @@ qt5_wrap_ui(UI_FILES
|
|||
SettingsView.ui
|
||||
ShaderSelector.ui
|
||||
ShortcutView.ui
|
||||
TileView.ui
|
||||
VideoView.ui)
|
||||
|
||||
set(QT_LIBRARIES)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (c) 2013-2016 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 "TilePainter.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
TilePainter::TilePainter(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_backing = QPixmap(256, 768);
|
||||
m_backing.fill(Qt::transparent);
|
||||
}
|
||||
|
||||
void TilePainter::paintEvent(QPaintEvent* event) {
|
||||
QPainter painter(this);
|
||||
painter.drawPixmap(QPoint(), m_backing);
|
||||
}
|
||||
|
||||
void TilePainter::mousePressEvent(QMouseEvent* event) {
|
||||
int x = event->x() / 8;
|
||||
int y = event->y() / 8;
|
||||
emit indexPressed(y * 32 + x);
|
||||
}
|
||||
|
||||
void TilePainter::setTile(int index, const uint16_t* data) {
|
||||
QPainter painter(&m_backing);
|
||||
int x = index & 31;
|
||||
int y = index / 32;
|
||||
QRect r(x * 8, y * 8, 8, 8);
|
||||
QImage tile(reinterpret_cast<const uchar*>(data), 8, 8, QImage::Format_RGB555);
|
||||
painter.fillRect(r, tile.rgbSwapped());
|
||||
update(r);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Copyright (c) 2013-2016 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/. */
|
||||
#ifndef QGBA_TILE_PAINTER
|
||||
#define QGBA_TILE_PAINTER
|
||||
|
||||
#include <QColor>
|
||||
#include <QWidget>
|
||||
#include <QVector>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class TilePainter : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TilePainter(QWidget* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void setTile(int index, const uint16_t*);
|
||||
|
||||
signals:
|
||||
void indexPressed(int index);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void mousePressEvent(QMouseEvent*) override;
|
||||
|
||||
private:
|
||||
QPixmap m_backing;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/* Copyright (c) 2013-2016 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 "TileView.h"
|
||||
|
||||
#include "GBAApp.h"
|
||||
|
||||
#include <QFontDatabase>
|
||||
|
||||
extern "C" {
|
||||
#include "gba/gba.h"
|
||||
}
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
TileView::TileView(GameController* controller, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_controller(controller)
|
||||
, m_paletteId(0)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
GBAVideoTileCacheInit(&m_tileCache);
|
||||
|
||||
m_ui.preview->setDimensions(QSize(8, 8));
|
||||
updateTiles();
|
||||
|
||||
const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
|
||||
m_ui.tileId->setFont(font);
|
||||
m_ui.address->setFont(font);
|
||||
|
||||
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateTiles()));
|
||||
connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
|
||||
connect(m_ui.tiles, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int)));
|
||||
connect(m_ui.paletteId, SIGNAL(valueChanged(int)), this, SLOT(updatePalette(int)));
|
||||
connect(m_ui.palette256, SIGNAL(toggled(bool)), this, SLOT(updateTiles()));
|
||||
}
|
||||
|
||||
TileView::~TileView() {
|
||||
GBAVideoTileCacheDeinit(&m_tileCache);
|
||||
}
|
||||
|
||||
void TileView::selectIndex(int index) {
|
||||
const uint16_t* data;
|
||||
m_ui.tileId->setText(QString::number(index));
|
||||
if (m_ui.palette256->isChecked()) {
|
||||
m_ui.address->setText(tr("0x%0").arg(index * 64 | BASE_VRAM, 8, 16, QChar('0')));
|
||||
if (index < 1024) {
|
||||
data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 0);
|
||||
} else {
|
||||
data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 1);
|
||||
}
|
||||
} else {
|
||||
m_ui.address->setText(tr("0x%0").arg(index * 32 | BASE_VRAM, 8, 16, QChar('0')));
|
||||
if (index < 2048) {
|
||||
data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId);
|
||||
} else {
|
||||
data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId + 16);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
m_ui.preview->setColor(i, data[i]);
|
||||
}
|
||||
m_ui.preview->update();
|
||||
}
|
||||
|
||||
void TileView::updateTiles() {
|
||||
if (!m_controller->thread() || !m_controller->thread()->core) {
|
||||
return;
|
||||
}
|
||||
|
||||
GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board);
|
||||
GBAVideoTileCacheAssociate(&m_tileCache, &gba->video);
|
||||
|
||||
if (m_ui.palette256->isChecked()) {
|
||||
m_ui.tiles->setMinimumSize(256, 384);
|
||||
for (int i = 0; i < 1024; ++i) {
|
||||
const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 0);
|
||||
if (data) {
|
||||
m_ui.tiles->setTile(i, data);
|
||||
}
|
||||
}
|
||||
for (int i = 1024; i < 1536; ++i) {
|
||||
const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 1);
|
||||
if (data) {
|
||||
m_ui.tiles->setTile(i, data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_ui.tiles->setMinimumSize(256, 768);
|
||||
for (int i = 0; i < 2048; ++i) {
|
||||
const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId);
|
||||
if (data) {
|
||||
m_ui.tiles->setTile(i, data);
|
||||
}
|
||||
}
|
||||
for (int i = 2048; i < 3072; ++i) {
|
||||
const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId + 16);
|
||||
if (data) {
|
||||
m_ui.tiles->setTile(i, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileView::updatePalette(int palette) {
|
||||
m_paletteId = palette;
|
||||
updateTiles();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (c) 2013-2016 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/. */
|
||||
#ifndef QGBA_TILE_VIEW
|
||||
#define QGBA_TILE_VIEW
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "GameController.h"
|
||||
|
||||
#include "ui_TileView.h"
|
||||
|
||||
extern "C" {
|
||||
#include "gba/renderers/tile-cache.h"
|
||||
}
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class TileView : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TileView(GameController* controller, QWidget* parent = nullptr);
|
||||
virtual ~TileView();
|
||||
|
||||
public slots:
|
||||
void updateTiles();
|
||||
void updatePalette(int);
|
||||
|
||||
private slots:
|
||||
void selectIndex(int);
|
||||
|
||||
private:
|
||||
Ui::TileView m_ui;
|
||||
|
||||
GameController* m_controller;
|
||||
GBAVideoTileCache m_tileCache;
|
||||
int m_paletteId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,199 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TileView</class>
|
||||
<widget class="QWidget" name="TileView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>288</width>
|
||||
<height>269</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tiles</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="palette256">
|
||||
<property name="text">
|
||||
<string>256 colors</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGBA::Swatch" name="preview" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>87</width>
|
||||
<height>87</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Tile #</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="tileId">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="address">
|
||||
<property name="text">
|
||||
<string>0x06000000</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSlider" name="paletteId">
|
||||
<property name="maximum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGBA::TilePainter" name="tiles" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QGBA::TilePainter</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>TilePainter.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QGBA::Swatch</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Swatch.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -30,6 +30,7 @@
|
|||
#include "MemoryView.h"
|
||||
#include "OverrideView.h"
|
||||
#include "PaletteView.h"
|
||||
#include "TileView.h"
|
||||
#include "ROMInfo.h"
|
||||
#include "SensorView.h"
|
||||
#include "SettingsView.h"
|
||||
|
@ -430,6 +431,11 @@ void Window::openPaletteWindow() {
|
|||
openView(paletteWindow);
|
||||
}
|
||||
|
||||
void Window::openTileWindow() {
|
||||
TileView* tileWindow = new TileView(m_controller);
|
||||
openView(tileWindow);
|
||||
}
|
||||
|
||||
void Window::openMemoryWindow() {
|
||||
MemoryView* memoryWindow = new MemoryView(m_controller);
|
||||
openView(memoryWindow);
|
||||
|
@ -1288,6 +1294,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_gbaActions.append(paletteView);
|
||||
addControlledAction(toolsMenu, paletteView, "paletteWindow");
|
||||
|
||||
QAction* tileView = new QAction(tr("View &tiles..."), toolsMenu);
|
||||
connect(tileView, SIGNAL(triggered()), this, SLOT(openTileWindow()));
|
||||
m_gameActions.append(tileView);
|
||||
m_gbaActions.append(tileView);
|
||||
addControlledAction(toolsMenu, tileView, "tileWindow");
|
||||
|
||||
QAction* memoryView = new QAction(tr("View memory..."), toolsMenu);
|
||||
connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow()));
|
||||
m_gameActions.append(memoryView);
|
||||
|
|
|
@ -82,6 +82,7 @@ public slots:
|
|||
void openCheatsWindow();
|
||||
|
||||
void openPaletteWindow();
|
||||
void openTileWindow();
|
||||
void openMemoryWindow();
|
||||
void openIOViewer();
|
||||
|
||||
|
|
Loading…
Reference in New Issue