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_tileStatus{}
23 , m_tileCache(controller->tileCache())
24 , m_paletteId(0)
25{
26 m_ui.setupUi(this);
27
28 m_ui.preview->setDimensions(QSize(8, 8));
29 m_updateTimer.setSingleShot(true);
30 m_updateTimer.setInterval(1);
31 connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTiles()));
32
33 const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
34
35 m_ui.tileId->setFont(font);
36 m_ui.address->setFont(font);
37
38 connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), &m_updateTimer, SLOT(start()));
39 connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
40 connect(m_ui.tiles, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int)));
41 connect(m_ui.paletteId, SIGNAL(valueChanged(int)), this, SLOT(updatePalette(int)));
42 connect(m_ui.palette256, &QAbstractButton::toggled, [this]() {
43 updateTiles(true);
44 });
45 connect(m_ui.magnification, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this]() {
46 updateTiles(true);
47 });
48}
49
50void TileView::selectIndex(int index) {
51 const uint16_t* data;
52 m_ui.tileId->setText(QString::number(index));
53 if (m_ui.palette256->isChecked()) {
54 m_ui.address->setText(tr("0x%0").arg(index * 64 | BASE_VRAM, 8, 16, QChar('0')));
55 if (index < 1024) {
56 data = mTileCacheGetTile(m_tileCache.get(), index, 0);
57 } else {
58 data = mTileCacheGetTile(m_tileCache.get(), index, 1);
59 }
60 } else {
61 m_ui.address->setText(tr("0x%0").arg(index * 32 | BASE_VRAM, 8, 16, QChar('0')));
62 if (index < 2048) {
63 data = mTileCacheGetTile(m_tileCache.get(), index, m_paletteId);
64 } else {
65 data = mTileCacheGetTile(m_tileCache.get(), index, m_paletteId + 16);
66 }
67 }
68 for (int i = 0; i < 64; ++i) {
69 m_ui.preview->setColor(i, data[i]);
70 }
71 m_ui.preview->update();
72}
73
74void TileView::updateTiles(bool force) {
75 if (!m_controller->thread() || !m_controller->thread()->core) {
76 return;
77 }
78
79 switch (m_controller->platform()) {
80#ifdef M_CORE_GBA
81 case PLATFORM_GBA:
82 updateTilesGBA(force);
83 break;
84#endif
85#ifdef M_CORE_GB
86 case PLATFORM_GB:
87 updateTilesGB(force);
88 break;
89#endif
90 default:
91 return;
92 }
93}
94
95#ifdef M_CORE_GBA
96void TileView::updateTilesGBA(bool force) {
97 if (m_ui.palette256->isChecked()) {
98 m_ui.tiles->setTileCount(1536);
99 mTileCacheSetPalette(m_tileCache.get(), 1);
100 for (int i = 0; i < 1024; ++i) {
101 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, 0);
102 if (data) {
103 m_ui.tiles->setTile(i, data);
104 } else if (force) {
105 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, 0));
106 }
107 }
108 for (int i = 1024; i < 1536; ++i) {
109 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, 1);
110 if (data) {
111 m_ui.tiles->setTile(i, data);
112 } else if (force) {
113 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, 1));
114 }
115 }
116 } else {
117 m_ui.tiles->setTileCount(3072);
118 mTileCacheSetPalette(m_tileCache.get(), 0);
119 for (int i = 0; i < 2048; ++i) {
120 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, m_paletteId);
121 if (data) {
122 m_ui.tiles->setTile(i, data);
123 } else if (force) {
124 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId));
125 }
126 }
127 for (int i = 2048; i < 3072; ++i) {
128 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, m_paletteId + 16);
129 if (data) {
130 m_ui.tiles->setTile(i, data);
131 } else if (force) {
132 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId + 16));
133 }
134 }
135 }
136}
137#endif
138
139#ifdef M_CORE_GB
140void TileView::updateTilesGB(bool force) {
141 m_ui.tiles->setTileCount(1024);
142 mTileCacheSetPalette(m_tileCache.get(), 0);
143 for (int i = 0; i < 1024; ++i) {
144 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[16 * i], i, m_paletteId);
145 if (data) {
146 m_ui.tiles->setTile(i, data);
147 } else if (force) {
148 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId));
149 }
150 }
151}
152#endif
153
154void TileView::updatePalette(int palette) {
155 m_paletteId = palette;
156 updateTiles(true);
157}
158
159void TileView::resizeEvent(QResizeEvent*) {
160 updateTiles(true);
161}
162
163void TileView::showEvent(QShowEvent*) {
164 updateTiles(true);
165}