DS Video: Fix up sprites a bit
Vicki Pfau vi@endrift.com
Tue, 21 Feb 2017 22:07:23 -0800
5 files changed,
40 insertions(+),
5 deletions(-)
M
include/mgba/internal/ds/video.h
→
include/mgba/internal/ds/video.h
@@ -52,6 +52,10 @@ DECL_BIT(DSRegisterDISPCNT, Win1Enable, 14);
DECL_BIT(DSRegisterDISPCNT, ObjwinEnable, 15); DECL_BITS(DSRegisterDISPCNT, DispMode, 16, 2); DECL_BITS(DSRegisterDISPCNT, VRAMBlock, 18, 2); +DECL_BITS(DSRegisterDISPCNT, TileBoundary, 20, 2); +// TODO +DECL_BITS(DSRegisterDISPCNT, CharBase, 24, 3); +DECL_BITS(DSRegisterDISPCNT, ScreenBase, 27, 3); // TODO struct DSVideoRenderer {
M
include/mgba/internal/gba/renderers/video-software.h
→
include/mgba/internal/gba/renderers/video-software.h
@@ -155,6 +155,7 @@
int oamDirty; int oamMax; struct GBAVideoSoftwareSprite sprites[128]; + int tileStride; int start; int end;
M
src/ds/renderers/software.c
→
src/ds/renderers/software.c
@@ -61,11 +61,33 @@ softwareRenderer->engA.d.deinit(&softwareRenderer->engA.d);
softwareRenderer->engB.d.deinit(&softwareRenderer->engB.d); } +static void GBAVideoSoftwareRendererUpdateDISPCNTA(struct DSVideoSoftwareRenderer* softwareRenderer) { + uint16_t fakeDispcnt = softwareRenderer->dispcntA & 0xFF87; + if (!DSRegisterDISPCNTIsTileObjMapping(softwareRenderer->dispcntA)) { + softwareRenderer->engA.tileStride = 0x20; + } else { + softwareRenderer->engA.tileStride = 0x20 << DSRegisterDISPCNTGetTileBoundary(softwareRenderer->dispcntA); + fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt); + } + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt); +} + +static void GBAVideoSoftwareRendererUpdateDISPCNTB(struct DSVideoSoftwareRenderer* softwareRenderer) { + uint16_t fakeDispcnt = softwareRenderer->dispcntB & 0xFF87; + if (!DSRegisterDISPCNTIsTileObjMapping(softwareRenderer->dispcntB)) { + softwareRenderer->engB.tileStride = 0x20; + } else { + softwareRenderer->engB.tileStride = 0x20 << DSRegisterDISPCNTGetTileBoundary(softwareRenderer->dispcntB); + fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt); + } + softwareRenderer->engB.d.writeVideoRegister(&softwareRenderer->engB.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt); +} + static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) { struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer; - if (address <= DS9_REG_A_BLDY) { + if (address >= DS9_REG_A_BG0CNT && address <= DS9_REG_A_BLDY) { value = softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, address, value); - } else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) { + } else if (address >= DS9_REG_B_BG0CNT && address <= DS9_REG_B_BLDY) { value = softwareRenderer->engB.d.writeVideoRegister(&softwareRenderer->engB.d, address & 0xFF, value); } else { mLOG(DS_VIDEO, STUB, "Stub video register write: %04X:%04X", address, value);@@ -74,18 +96,23 @@ switch (address) {
case DS9_REG_A_DISPCNT_LO: softwareRenderer->dispcntA &= 0xFFFF0000; softwareRenderer->dispcntA |= value; + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, address, value & 0xFF87); + GBAVideoSoftwareRendererUpdateDISPCNTA(softwareRenderer); break; case DS9_REG_A_DISPCNT_HI: softwareRenderer->dispcntA &= 0x0000FFFF; softwareRenderer->dispcntA |= value << 16; + GBAVideoSoftwareRendererUpdateDISPCNTA(softwareRenderer); break; case DS9_REG_B_DISPCNT_LO: softwareRenderer->dispcntB &= 0xFFFF0000; softwareRenderer->dispcntB |= value; + GBAVideoSoftwareRendererUpdateDISPCNTB(softwareRenderer); break; case DS9_REG_B_DISPCNT_HI: softwareRenderer->dispcntB &= 0x0000FFFF; softwareRenderer->dispcntB |= value << 16; + GBAVideoSoftwareRendererUpdateDISPCNTB(softwareRenderer); break; } return value;
M
src/gba/renderers/software-obj.c
→
src/gba/renderers/software-obj.c
@@ -159,7 +159,7 @@ return 0;
} int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23; x >>= 23; - unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * 0x20; + unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * renderer->tileStride; uint16_t* vramBase = NULL; if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) { return 0;
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -62,6 +62,7 @@ renderer->d.disableBG[1] = false;
renderer->d.disableBG[2] = false; renderer->d.disableBG[3] = false; renderer->d.disableOBJ = false; + renderer->tileStride = 0x20; renderer->temporaryBuffer = 0; }@@ -635,10 +636,12 @@
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value) { UNUSED(renderer); bg->priority = GBARegisterBGCNTGetPriority(value); - bg->charBase = GBARegisterBGCNTGetCharBase(value) << 14; + bg->charBase &= ~0xC000; + bg->charBase |= GBARegisterBGCNTGetCharBase(value) << 14; bg->mosaic = GBARegisterBGCNTGetMosaic(value); bg->multipalette = GBARegisterBGCNTGet256Color(value); - bg->screenBase = GBARegisterBGCNTGetScreenBase(value) << 11; + bg->screenBase &= ~0xF800; + bg->screenBase |= GBARegisterBGCNTGetScreenBase(value) << 11; bg->overflow = GBARegisterBGCNTGetOverflow(value); bg->size = GBARegisterBGCNTGetSize(value); }