all repos — mgba @ d6c055f9d878486b706194a320040d98a1e262c4

mGBA Game Boy Advance Emulator

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