src/platform/qt/TileView.cpp (view raw)
1/* Copyright (c) 2013-2016 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 "TileView.h"
7
8#include "GBAApp.h"
9
10#include <QFontDatabase>
11#include <QTimer>
12
13extern "C" {
14#include "gba/gba.h"
15}
16
17using namespace QGBA;
18
19TileView::TileView(GameController* controller, QWidget* parent)
20 : QWidget(parent)
21 , m_controller(controller)
22 , m_paletteId(0)
23{
24 m_ui.setupUi(this);
25 GBAVideoTileCacheInit(&m_tileCache);
26
27 m_ui.preview->setDimensions(QSize(8, 8));
28 m_updateTimer.setSingleShot(true);
29 m_updateTimer.setInterval(1);
30 connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTiles()));
31
32 const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
33
34 m_ui.tileId->setFont(font);
35 m_ui.address->setFont(font);
36
37 connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), &m_updateTimer, SLOT(start()));
38 connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
39 connect(m_ui.tiles, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int)));
40 connect(m_ui.paletteId, SIGNAL(valueChanged(int)), this, SLOT(updatePalette(int)));
41 connect(m_ui.palette256, &QAbstractButton::toggled, [this]() {
42 updateTiles(true);
43 });
44 connect(m_ui.magnification, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this]() {
45 updateTiles(true);
46 });
47}
48
49TileView::~TileView() {
50 if (m_controller->isLoaded() && m_controller->thread() && m_controller->thread()->core) {
51 GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board);
52 gba->video.renderer->cache = nullptr;
53 }
54
55 GBAVideoTileCacheDeinit(&m_tileCache);
56}
57
58void TileView::selectIndex(int index) {
59 const uint16_t* data;
60 m_ui.tileId->setText(QString::number(index));
61 if (m_ui.palette256->isChecked()) {
62 m_ui.address->setText(tr("0x%0").arg(index * 64 | BASE_VRAM, 8, 16, QChar('0')));
63 if (index < 1024) {
64 data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 0);
65 } else {
66 data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 1);
67 }
68 } else {
69 m_ui.address->setText(tr("0x%0").arg(index * 32 | BASE_VRAM, 8, 16, QChar('0')));
70 if (index < 2048) {
71 data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId);
72 } else {
73 data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId + 16);
74 }
75 }
76 for (int i = 0; i < 64; ++i) {
77 m_ui.preview->setColor(i, data[i]);
78 }
79 m_ui.preview->update();
80}
81
82void TileView::updateTiles(bool force) {
83 if (!m_controller->thread() || !m_controller->thread()->core) {
84 return;
85 }
86
87 GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board);
88 GBAVideoTileCacheAssociate(&m_tileCache, &gba->video);
89
90 if (m_ui.palette256->isChecked()) {
91 m_ui.tiles->setTileCount(1536);
92 for (int i = 0; i < 1024; ++i) {
93 const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 0);
94 if (data) {
95 m_ui.tiles->setTile(i, data);
96 } else if (force) {
97 m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(&m_tileCache, i, 0));
98 }
99 }
100 for (int i = 1024; i < 1536; ++i) {
101 const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 1);
102 if (data) {
103 m_ui.tiles->setTile(i, data);
104 } else if (force) {
105 m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(&m_tileCache, i, 1));
106 }
107 }
108 } else {
109 m_ui.tiles->setTileCount(3072);
110 for (int i = 0; i < 2048; ++i) {
111 const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId);
112 if (data) {
113 m_ui.tiles->setTile(i, data);
114 } else if (force) {
115 m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(&m_tileCache, i, m_paletteId));
116 }
117 }
118 for (int i = 2048; i < 3072; ++i) {
119 const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId + 16);
120 if (data) {
121 m_ui.tiles->setTile(i, data);
122 } else if (force) {
123 m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(&m_tileCache, i, m_paletteId + 16));
124 }
125 }
126 }
127}
128
129void TileView::updatePalette(int palette) {
130 m_paletteId = palette;
131 updateTiles(true);
132}
133
134void TileView::resizeEvent(QResizeEvent*) {
135 updateTiles(true);
136}
137
138void TileView::showEvent(QShowEvent*) {
139 updateTiles(true);
140}