GBA Video: Add window toggling

This commit is contained in:
Vicki Pfau 2020-10-22 19:49:26 -07:00
parent 9064cb107b
commit c8e1e14d3f
9 changed files with 98 additions and 28 deletions

View File

@ -11,6 +11,7 @@ Features:
- Command scripts for CLI debugger (by ahigerd) - Command scripts for CLI debugger (by ahigerd)
- ARM disassembler now resolves addresses to symbol names - ARM disassembler now resolves addresses to symbol names
- Add Game Boy Player feature support to ports - Add Game Boy Player feature support to ports
- Individual window types can now be toggled in GBA debugging views
Emulation fixes: Emulation fixes:
- ARM: Fix ALU reading PC after shifting - ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation - ARM: Fix STR storing PC after address calculation

View File

@ -34,6 +34,17 @@ enum GBASIOJOYCommand {
JOY_RECV = 0x15 JOY_RECV = 0x15
}; };
enum GBAVideoLayer {
GBA_LAYER_BG0 = 0,
GBA_LAYER_BG1,
GBA_LAYER_BG2,
GBA_LAYER_BG3,
GBA_LAYER_OBJ,
GBA_LAYER_WIN0,
GBA_LAYER_WIN1,
GBA_LAYER_OBJWIN,
};
struct GBA; struct GBA;
struct GBAAudio; struct GBAAudio;
struct GBASIO; struct GBASIO;

View File

@ -194,6 +194,8 @@ struct GBAVideoRenderer {
bool disableBG[4]; bool disableBG[4];
bool disableOBJ; bool disableOBJ;
bool disableWIN[2];
bool disableOBJWIN;
bool highlightBG[4]; bool highlightBG[4];
bool highlightOBJ[128]; bool highlightOBJ[128];

View File

@ -33,11 +33,14 @@
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
static const struct mCoreChannelInfo _GBAVideoLayers[] = { static const struct mCoreChannelInfo _GBAVideoLayers[] = {
{ 0, "bg0", "Background 0", NULL }, { GBA_LAYER_BG0, "bg0", "Background 0", NULL },
{ 1, "bg1", "Background 1", NULL }, { GBA_LAYER_BG1, "bg1", "Background 1", NULL },
{ 2, "bg2", "Background 2", NULL }, { GBA_LAYER_BG2, "bg2", "Background 2", NULL },
{ 3, "bg3", "Background 3", NULL }, { GBA_LAYER_BG3, "bg3", "Background 3", NULL },
{ 4, "obj", "Objects", NULL }, { GBA_LAYER_OBJ, "obj", "Objects", NULL },
{ GBA_LAYER_WIN0, "win0", "Window 0", NULL },
{ GBA_LAYER_WIN1, "win1", "Window 1", NULL },
{ GBA_LAYER_OBJWIN, "objwin", "Object Window", NULL },
}; };
static const struct mCoreChannelInfo _GBAAudioChannels[] = { static const struct mCoreChannelInfo _GBAAudioChannels[] = {
@ -1038,15 +1041,24 @@ static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct m
static void _GBACoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) { static void _GBACoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
struct GBA* gba = core->board; struct GBA* gba = core->board;
switch (id) { switch (id) {
case 0: case GBA_LAYER_BG0:
case 1: case GBA_LAYER_BG1:
case 2: case GBA_LAYER_BG2:
case 3: case GBA_LAYER_BG3:
gba->video.renderer->disableBG[id] = !enable; gba->video.renderer->disableBG[id] = !enable;
break; break;
case 4: case GBA_LAYER_OBJ:
gba->video.renderer->disableOBJ = !enable; gba->video.renderer->disableOBJ = !enable;
break; break;
case GBA_LAYER_WIN0:
gba->video.renderer->disableWIN[0] = !enable;
break;
case GBA_LAYER_WIN1:
gba->video.renderer->disableWIN[1] = !enable;
break;
case GBA_LAYER_OBJWIN:
gba->video.renderer->disableOBJWIN = !enable;
break;
default: default:
break; break;
} }
@ -1075,14 +1087,14 @@ static void _GBACoreEnableAudioChannel(struct mCore* core, size_t id, bool enabl
static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) { static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
struct GBACore* gbacore = (struct GBACore*) core; struct GBACore* gbacore = (struct GBACore*) core;
switch (id) { switch (id) {
case 0: case GBA_LAYER_BG0:
case 1: case GBA_LAYER_BG1:
case 2: case GBA_LAYER_BG2:
case 3: case GBA_LAYER_BG3:
gbacore->renderer.bg[id].offsetX = x; gbacore->renderer.bg[id].offsetX = x;
gbacore->renderer.bg[id].offsetY = y; gbacore->renderer.bg[id].offsetY = y;
break; break;
case 4: case GBA_LAYER_OBJ:
gbacore->renderer.objOffsetX = x; gbacore->renderer.objOffsetX = x;
gbacore->renderer.objOffsetY = y; gbacore->renderer.objOffsetY = y;
gbacore->renderer.oamDirty = 1; gbacore->renderer.oamDirty = 1;

View File

@ -43,6 +43,9 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct
renderer->d.disableBG[2] = false; renderer->d.disableBG[2] = false;
renderer->d.disableBG[3] = false; renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false; renderer->d.disableOBJ = false;
renderer->d.disableWIN[0] = false;
renderer->d.disableWIN[1] = false;
renderer->d.disableOBJWIN = false;
renderer->d.highlightBG[0] = false; renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false; renderer->d.highlightBG[1] = false;
@ -202,6 +205,9 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2];
proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3];
proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ;
proxyRenderer->backend->disableWIN[0] = proxyRenderer->d.disableWIN[0];
proxyRenderer->backend->disableWIN[1] = proxyRenderer->d.disableWIN[1];
proxyRenderer->backend->disableOBJWIN = proxyRenderer->d.disableOBJWIN;
proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0]; proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0];
proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1]; proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1];
proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2]; proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2];
@ -302,6 +308,9 @@ void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y)
proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2];
proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3];
proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ;
proxyRenderer->backend->disableWIN[0] = proxyRenderer->d.disableWIN[0];
proxyRenderer->backend->disableWIN[1] = proxyRenderer->d.disableWIN[1];
proxyRenderer->backend->disableOBJWIN = proxyRenderer->d.disableOBJWIN;
proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0]; proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0];
proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1]; proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1];
proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2]; proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2];

View File

@ -148,7 +148,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
uint32_t flags = GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY; uint32_t flags = GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY;
flags |= FLAG_TARGET_1 * ((GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT); flags |= FLAG_TARGET_1 * ((GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT);
flags |= FLAG_OBJWIN * (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN); flags |= FLAG_OBJWIN * (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN);
if ((flags & FLAG_OBJWIN) && renderer->currentWindow.priority < renderer->objwin.priority) { if ((flags & FLAG_OBJWIN) && (renderer->currentWindow.priority < renderer->objwin.priority || renderer->d.disableOBJWIN)) {
return 0; return 0;
} }
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23; int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;

View File

@ -61,6 +61,9 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->d.disableBG[2] = false; renderer->d.disableBG[2] = false;
renderer->d.disableBG[3] = false; renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false; renderer->d.disableOBJ = false;
renderer->d.disableWIN[0] = false;
renderer->d.disableWIN[1] = false;
renderer->d.disableOBJWIN = false;
renderer->d.highlightBG[0] = false; renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false; renderer->d.highlightBG[1] = false;
@ -572,10 +575,10 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
softwareRenderer->nWindows = 1; softwareRenderer->nWindows = 1;
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) { if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
softwareRenderer->windows[0].control = softwareRenderer->winout; softwareRenderer->windows[0].control = softwareRenderer->winout;
if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt)) { if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[1]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[1], y); _breakWindow(softwareRenderer, &softwareRenderer->winN[1], y);
} }
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt)) { if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[0]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[0], y); _breakWindow(softwareRenderer, &softwareRenderer->winN[0], y);
} }
} else { } else {

View File

@ -154,16 +154,44 @@ void FrameView::updateTilesGBA(bool) {
uint16_t* io = static_cast<GBA*>(m_controller->thread()->core->board)->memory.io; uint16_t* io = static_cast<GBA*>(m_controller->thread()->core->board)->memory.io;
QRgb backdrop = M_RGB5_TO_RGB8(static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[0]); QRgb backdrop = M_RGB5_TO_RGB8(static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[0]);
m_gbaDispcnt = io[REG_DISPCNT >> 1]; GBARegisterDISPCNT gbaDispcnt = io[REG_DISPCNT >> 1];
int mode = GBARegisterDISPCNTGetMode(m_gbaDispcnt); int mode = GBARegisterDISPCNTGetMode(gbaDispcnt);
std::array<bool, 4> enabled{ std::array<bool, 4> enabled{
bool(GBARegisterDISPCNTIsBg0Enable(m_gbaDispcnt)), bool(GBARegisterDISPCNTIsBg0Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg1Enable(m_gbaDispcnt)), bool(GBARegisterDISPCNTIsBg1Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg2Enable(m_gbaDispcnt)), bool(GBARegisterDISPCNTIsBg2Enable(gbaDispcnt)),
bool(GBARegisterDISPCNTIsBg3Enable(m_gbaDispcnt)), bool(GBARegisterDISPCNTIsBg3Enable(gbaDispcnt)),
}; };
if (GBARegisterDISPCNTIsWin0Enable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 0 },
!m_disabled.contains({ LayerId::WINDOW, 0 }),
{},
{}, {0, 0}, true, false
});
}
if (GBARegisterDISPCNTIsWin1Enable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 1 },
!m_disabled.contains({ LayerId::WINDOW, 1 }),
{},
{}, {0, 0}, true, false
});
}
if (GBARegisterDISPCNTIsObjwinEnable(gbaDispcnt)) {
m_queue.append({
{ LayerId::WINDOW, 2 },
!m_disabled.contains({ LayerId::WINDOW, 2 }),
{},
{}, {0, 0}, true, false
});
}
for (int priority = 0; priority < 4; ++priority) { for (int priority = 0; priority < 4; ++priority) {
for (int sprite = 0; sprite < 128; ++sprite) { for (int sprite = 0; sprite < 128; ++sprite) {
ObjInfo info; ObjInfo info;
@ -271,6 +299,9 @@ void FrameView::injectGBA() {
gba->video.renderer->highlightBG[layer.id.index] = true; gba->video.renderer->highlightBG[layer.id.index] = true;
} }
break; break;
case LayerId::WINDOW:
m_vl->enableVideoLayer(m_vl, GBA_LAYER_WIN0 + layer.id.index, layer.enabled);
break;
} }
} }
if (m_overrideBackdrop.isValid()) { if (m_overrideBackdrop.isValid()) {
@ -521,6 +552,11 @@ QString FrameView::LayerId::readable() const {
break; break;
case WINDOW: case WINDOW:
typeStr = tr("Window"); typeStr = tr("Window");
#ifdef M_CORE_GBA
if (index == 2) {
return tr("Objwin");
}
#endif
break; break;
case SPRITE: case SPRITE:
typeStr = tr("Sprite"); typeStr = tr("Sprite");

View File

@ -112,10 +112,6 @@ private:
ColorPicker m_backdropPicker; ColorPicker m_backdropPicker;
QColor m_overrideBackdrop; QColor m_overrideBackdrop;
#ifdef M_CORE_GBA
uint16_t m_gbaDispcnt;
#endif
std::shared_ptr<bool> m_callbackLocker{std::make_shared<bool>(true)}; std::shared_ptr<bool> m_callbackLocker{std::make_shared<bool>(true)};
}; };