GBA Video: Add window toggling
@@ -11,6 +11,7 @@ - Stack tracing tools in ARM debugger (by ahigerd)
- Command scripts for CLI debugger (by ahigerd) - ARM disassembler now resolves addresses to symbol names - Add Game Boy Player feature support to ports + - Individual window types can now be toggled in GBA debugging views Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation
@@ -34,6 +34,17 @@ JOY_TRANS = 0x14,
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 GBAAudio; struct GBASIO;
@@ -194,6 +194,8 @@ struct mCacheSet* cache;
bool disableBG[4]; bool disableOBJ; + bool disableWIN[2]; + bool disableOBJWIN; bool highlightBG[4]; bool highlightOBJ[128];
@@ -33,11 +33,14 @@ #include <mgba-util/patch.h>
#include <mgba-util/vfs.h> static const struct mCoreChannelInfo _GBAVideoLayers[] = { - { 0, "bg0", "Background 0", NULL }, - { 1, "bg1", "Background 1", NULL }, - { 2, "bg2", "Background 2", NULL }, - { 3, "bg3", "Background 3", NULL }, - { 4, "obj", "Objects", NULL }, + { GBA_LAYER_BG0, "bg0", "Background 0", NULL }, + { GBA_LAYER_BG1, "bg1", "Background 1", NULL }, + { GBA_LAYER_BG2, "bg2", "Background 2", NULL }, + { GBA_LAYER_BG3, "bg3", "Background 3", 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[] = {@@ -1038,14 +1041,23 @@
static void _GBACoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) { struct GBA* gba = core->board; switch (id) { - case 0: - case 1: - case 2: - case 3: + case GBA_LAYER_BG0: + case GBA_LAYER_BG1: + case GBA_LAYER_BG2: + case GBA_LAYER_BG3: gba->video.renderer->disableBG[id] = !enable; break; - case 4: + case GBA_LAYER_OBJ: gba->video.renderer->disableOBJ = !enable; + 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: break;@@ -1075,14 +1087,14 @@
static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) { struct GBACore* gbacore = (struct GBACore*) core; switch (id) { - case 0: - case 1: - case 2: - case 3: + case GBA_LAYER_BG0: + case GBA_LAYER_BG1: + case GBA_LAYER_BG2: + case GBA_LAYER_BG3: gbacore->renderer.bg[id].offsetX = x; gbacore->renderer.bg[id].offsetY = y; break; - case 4: + case GBA_LAYER_OBJ: gbacore->renderer.objOffsetX = x; gbacore->renderer.objOffsetY = y; gbacore->renderer.oamDirty = 1;
@@ -43,6 +43,9 @@ renderer->d.disableBG[1] = false;
renderer->d.disableBG[2] = false; renderer->d.disableBG[3] = 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[1] = false;@@ -202,6 +205,9 @@ proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1];
proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; 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[1] = proxyRenderer->d.highlightBG[1]; proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2];@@ -302,6 +308,9 @@ proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1];
proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2]; proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; 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[1] = proxyRenderer->d.highlightBG[1]; proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2];
@@ -148,7 +148,7 @@ int end = renderer->end;
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_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; } int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
@@ -61,6 +61,9 @@ renderer->d.disableBG[1] = false;
renderer->d.disableBG[2] = false; renderer->d.disableBG[3] = 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[1] = false;@@ -572,10 +575,10 @@ softwareRenderer->windows[0].endX = GBA_VIDEO_HORIZONTAL_PIXELS;
softwareRenderer->nWindows = 1; if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) { softwareRenderer->windows[0].control = softwareRenderer->winout; - if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt)) { + if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[1]) { _breakWindow(softwareRenderer, &softwareRenderer->winN[1], y); } - if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt)) { + if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[0]) { _breakWindow(softwareRenderer, &softwareRenderer->winN[0], y); } } else {
@@ -154,15 +154,43 @@ CoreController::Interrupter interrupter(m_controller);
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]); - m_gbaDispcnt = io[REG_DISPCNT >> 1]; - int mode = GBARegisterDISPCNTGetMode(m_gbaDispcnt); + GBARegisterDISPCNT gbaDispcnt = io[REG_DISPCNT >> 1]; + int mode = GBARegisterDISPCNTGetMode(gbaDispcnt); std::array<bool, 4> enabled{ - bool(GBARegisterDISPCNTIsBg0Enable(m_gbaDispcnt)), - bool(GBARegisterDISPCNTIsBg1Enable(m_gbaDispcnt)), - bool(GBARegisterDISPCNTIsBg2Enable(m_gbaDispcnt)), - bool(GBARegisterDISPCNTIsBg3Enable(m_gbaDispcnt)), + bool(GBARegisterDISPCNTIsBg0Enable(gbaDispcnt)), + bool(GBARegisterDISPCNTIsBg1Enable(gbaDispcnt)), + bool(GBARegisterDISPCNTIsBg2Enable(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 sprite = 0; sprite < 128; ++sprite) {@@ -270,6 +298,9 @@ m_vl->enableVideoLayer(m_vl, layer.id.index, layer.enabled);
if (layer.id == m_active) { gba->video.renderer->highlightBG[layer.id.index] = true; } + break; + case LayerId::WINDOW: + m_vl->enableVideoLayer(m_vl, GBA_LAYER_WIN0 + layer.id.index, layer.enabled); break; } }@@ -521,6 +552,11 @@ typeStr = tr("Background");
break; case WINDOW: typeStr = tr("Window"); +#ifdef M_CORE_GBA + if (index == 2) { + return tr("Objwin"); + } +#endif break; case SPRITE: typeStr = tr("Sprite");
@@ -112,10 +112,6 @@ mMapCacheEntry m_mapStatus[4][128 * 128] = {}; // TODO: Correct size
ColorPicker m_backdropPicker; QColor m_overrideBackdrop; -#ifdef M_CORE_GBA - uint16_t m_gbaDispcnt; -#endif - std::shared_ptr<bool> m_callbackLocker{std::make_shared<bool>(true)}; };