src/platform/qt/ObjView.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 "ObjView.h"
7
8#include "GBAApp.h"
9
10#include <QFontDatabase>
11#include <QTimer>
12
13extern "C" {
14#include "gba/gba.h"
15#ifdef M_CORE_GB
16#include "gb/gb.h"
17#endif
18}
19
20using namespace QGBA;
21
22ObjView::ObjView(GameController* controller, QWidget* parent)
23 : AssetView(controller, parent)
24 , m_controller(controller)
25 , m_tileStatus{}
26 , m_objId(0)
27{
28 m_ui.setupUi(this);
29 m_ui.tile->setController(controller);
30
31 const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
32
33 m_ui.x->setFont(font);
34 m_ui.y->setFont(font);
35 m_ui.w->setFont(font);
36 m_ui.h->setFont(font);
37 m_ui.address->setFont(font);
38 m_ui.priority->setFont(font);
39 m_ui.palette->setFont(font);
40 m_ui.transform->setFont(font);
41 m_ui.mode->setFont(font);
42
43 connect(m_ui.tiles, SIGNAL(indexPressed(int)), this, SLOT(translateIndex(int)));
44 connect(m_ui.objId, SIGNAL(valueChanged(int)), this, SLOT(selectObj(int)));
45 connect(m_ui.magnification, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this]() {
46 updateTiles(true);
47 });
48}
49
50void ObjView::selectObj(int obj) {
51 m_objId = obj;
52 updateTiles(true);
53}
54
55void ObjView::translateIndex(int index) {
56 m_ui.tile->selectIndex(index + m_tileOffset);
57}
58
59#ifdef M_CORE_GBA
60void ObjView::updateTilesGBA(bool force) {
61 const GBA* gba = static_cast<const GBA*>(m_controller->thread()->core->board);
62 const GBAObj* obj = &gba->video.oam.obj[m_objId];
63
64 unsigned shape = GBAObjAttributesAGetShape(obj->a);
65 unsigned size = GBAObjAttributesBGetSize(obj->b);
66 unsigned width = GBAVideoObjSizes[shape * 4 + size][0];
67 unsigned height = GBAVideoObjSizes[shape * 4 + size][1];
68 m_ui.tiles->setTileCount(width * height / 64);
69 m_ui.tiles->setMinimumSize(QSize(width, height) * m_ui.magnification->value());
70 unsigned palette = GBAObjAttributesCGetPalette(obj->c);
71 unsigned tile = GBAObjAttributesCGetTile(obj->c);
72 int i = 0;
73 // TODO: Tile stride
74 // TODO: Check to see if parameters are changed (so as to enable force if needed)
75 if (GBAObjAttributesAIs256Color(obj->a)) {
76 m_ui.palette->setText("256-color");
77 mTileCacheSetPalette(m_tileCache.get(), 1);
78 m_ui.tile->setPalette(0);
79 m_ui.tile->setPaletteSet(1, 1024, 1536);
80 tile /= 2;
81 for (int y = 0; y < height / 8; ++y) {
82 for (int x = 0; x < width / 8; ++x, ++i) {
83 unsigned t = tile + i;
84 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * t], t + 1024, 1);
85 if (data) {
86 m_ui.tiles->setTile(i, data);
87 } else if (force) {
88 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), t + 1024, 1));
89 }
90 }
91 }
92 tile += 1024;
93 } else {
94 m_ui.palette->setText(QString::number(palette));
95 mTileCacheSetPalette(m_tileCache.get(), 0);
96 m_ui.tile->setPalette(palette);
97 m_ui.tile->setPaletteSet(0, 2048, 3072);
98 for (int y = 0; y < height / 8; ++y) {
99 for (int x = 0; x < width / 8; ++x, ++i) {
100 unsigned t = tile + i;
101 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * t], t + 2048, palette + 16);
102 if (data) {
103 m_ui.tiles->setTile(i, data);
104 } else if (force) {
105 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), t + 2048, palette + 16));
106 }
107 }
108 }
109 tile += 2048;
110 }
111 m_tileOffset = tile;
112
113 m_ui.x->setText(QString::number(GBAObjAttributesBGetX(obj->b)));
114 m_ui.y->setText(QString::number(GBAObjAttributesAGetY(obj->a)));
115 m_ui.w->setText(QString::number(width));
116 m_ui.h->setText(QString::number(height));
117
118 m_ui.address->setText(tr("0x%0").arg(BASE_OAM + m_objId * sizeof(*obj), 8, 16, QChar('0')));
119 m_ui.priority->setText(QString::number(GBAObjAttributesCGetPriority(obj->c)));
120 m_ui.flippedH->setChecked(GBAObjAttributesBIsHFlip(obj->b));
121 m_ui.flippedV->setChecked(GBAObjAttributesBIsVFlip(obj->b));
122 m_ui.enabled->setChecked(!GBAObjAttributesAIsDisable(obj->a) || GBAObjAttributesAIsTransformed(obj->a));
123 m_ui.doubleSize->setChecked(GBAObjAttributesAIsDoubleSize(obj->a) && GBAObjAttributesAIsTransformed(obj->a));
124 m_ui.mosaic->setChecked(GBAObjAttributesAIsMosaic(obj->a));
125
126 if (GBAObjAttributesAIsTransformed(obj->a)) {
127 m_ui.transform->setText(QString::number(GBAObjAttributesBGetMatIndex(obj->b)));
128 } else {
129 m_ui.transform->setText(tr("Off"));
130 }
131
132 switch (GBAObjAttributesAGetMode(obj->a)) {
133 case OBJ_MODE_NORMAL:
134 m_ui.mode->setText(tr("Normal"));
135 break;
136 case OBJ_MODE_SEMITRANSPARENT:
137 m_ui.mode->setText(tr("Trans"));
138 break;
139 case OBJ_MODE_OBJWIN:
140 m_ui.mode->setText(tr("OBJWIN"));
141 break;
142 default:
143 m_ui.mode->setText(tr("Invalid"));
144 break;
145 }
146}
147#endif
148
149#ifdef M_CORE_GB
150void ObjView::updateTilesGB(bool force) {
151 const GB* gb = static_cast<const GB*>(m_controller->thread()->core->board);
152 const GBObj* obj = &gb->video.oam.obj[m_objId];
153
154 unsigned width = 8;
155 unsigned height = 8; // TODO
156 m_ui.tiles->setTileCount(width * height / 64);
157 m_ui.tiles->setMinimumSize(QSize(width, height) * m_ui.magnification->value());
158 int palette = 0;
159 unsigned tile = obj->tile;
160 if (gb->model >= GB_MODEL_CGB) {
161 if (GBObjAttributesIsBank(obj->attr)) {
162 tile += 512;
163 }
164 palette = GBObjAttributesGetCGBPalette(obj->attr);
165 } else {
166 palette = GBObjAttributesGetPalette(obj->attr);
167 }
168 int i = 0;
169 // TODO: Check to see if parameters are changed (so as to enable force if needed)
170 m_ui.palette->setText(QString::number(palette));
171 mTileCacheSetPalette(m_tileCache.get(), 0);
172 m_ui.tile->setPalette(palette + 8);
173 m_ui.tile->setPaletteSet(0, 512, 1024);
174 for (int y = 0; y < height / 8; ++y, ++i) {
175 unsigned t = tile + i;
176 const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[16 * t], t, palette + 8);
177 if (data) {
178 m_ui.tiles->setTile(i, data);
179 } else if (force) {
180 m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), t, palette + 8));
181 }
182 }
183 m_tileOffset = tile;
184
185 m_ui.x->setText(QString::number(obj->x));
186 m_ui.y->setText(QString::number(obj->y));
187 m_ui.w->setText(QString::number(width));
188 m_ui.h->setText(QString::number(height));
189
190 m_ui.address->setText(tr("0x%0").arg(GB_BASE_OAM + m_objId * sizeof(*obj), 4, 16, QChar('0')));
191 m_ui.priority->setText(QString::number(GBObjAttributesGetPriority(obj->attr)));
192 m_ui.flippedH->setChecked(GBObjAttributesIsXFlip(obj->attr));
193 m_ui.flippedV->setChecked(GBObjAttributesIsYFlip(obj->attr));
194 m_ui.enabled->setChecked(obj->y == 0 || obj->y >= 160);
195 m_ui.doubleSize->setChecked(false);
196 m_ui.mosaic->setChecked(false);
197 m_ui.transform->setText(tr("N/A"));
198 m_ui.mode->setText(tr("N/A"));
199}
200#endif