DS Video: Implement extended character base
Vicki Pfau vi@endrift.com
Thu, 23 Feb 2017 00:09:02 -0800
5 files changed,
41 insertions(+),
19 deletions(-)
M
include/mgba/internal/gba/renderers/video-software.h
→
include/mgba/internal/gba/renderers/video-software.h
@@ -24,6 +24,7 @@ unsigned index;
int enabled; unsigned priority; uint32_t charBase; + uint16_t control; int mosaic; int multipalette; uint32_t screenBase;
M
include/mgba/internal/gba/video.h
→
include/mgba/internal/gba/video.h
@@ -127,7 +127,7 @@ DECL_BITS(GBARegisterDISPSTAT, VcountSetting, 8, 8);
DECL_BITFIELD(GBARegisterBGCNT, uint16_t); DECL_BITS(GBARegisterBGCNT, Priority, 0, 2); -DECL_BITS(GBARegisterBGCNT, CharBase, 2, 2); +DECL_BITS(GBARegisterBGCNT, CharBase, 2, 4); DECL_BIT(GBARegisterBGCNT, Mosaic, 6); DECL_BIT(GBARegisterBGCNT, 256Color, 7); DECL_BITS(GBARegisterBGCNT, ScreenBase, 8, 5);
M
src/ds/renderers/software.c
→
src/ds/renderers/software.c
@@ -74,22 +74,23 @@ }
softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt); uint32_t charBase = DSRegisterDISPCNTGetCharBase(softwareRenderer->dispcntA) << 16; uint32_t screenBase = DSRegisterDISPCNTGetScreenBase(softwareRenderer->dispcntA) << 16; - softwareRenderer->engA.bg[0].charBase &= ~0x70000; - softwareRenderer->engA.bg[0].charBase |= charBase; + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG0CNT, softwareRenderer->engA.bg[0].control); + softwareRenderer->engA.bg[0].charBase += charBase; softwareRenderer->engA.bg[0].screenBase &= ~0x70000; softwareRenderer->engA.bg[0].screenBase |= screenBase; - softwareRenderer->engA.bg[1].charBase &= ~0x70000; - softwareRenderer->engA.bg[1].charBase |= charBase; + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG1CNT, softwareRenderer->engA.bg[1].control); + softwareRenderer->engA.bg[1].charBase += charBase; softwareRenderer->engA.bg[1].screenBase &= ~0x70000; softwareRenderer->engA.bg[1].screenBase |= screenBase; - softwareRenderer->engA.bg[2].charBase &= ~0x70000; - softwareRenderer->engA.bg[2].charBase |= charBase; + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG2CNT, softwareRenderer->engA.bg[2].control); + softwareRenderer->engA.bg[2].charBase += charBase; softwareRenderer->engA.bg[2].screenBase &= ~0x70000; softwareRenderer->engA.bg[2].screenBase |= screenBase; - softwareRenderer->engA.bg[3].charBase &= ~0x70000; - softwareRenderer->engA.bg[3].charBase |= charBase; + softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG3CNT, softwareRenderer->engA.bg[3].control); + softwareRenderer->engA.bg[3].charBase += charBase; softwareRenderer->engA.bg[3].screenBase &= ~0x70000; - softwareRenderer->engA.bg[3].screenBase |= screenBase;} + softwareRenderer->engA.bg[3].screenBase |= screenBase; +} static void DSVideoSoftwareRendererUpdateDISPCNTB(struct DSVideoSoftwareRenderer* softwareRenderer) { uint16_t fakeDispcnt = softwareRenderer->dispcntB & 0xFF87;
M
src/gba/renderers/software-obj.c
→
src/gba/renderers/software-obj.c
@@ -68,8 +68,11 @@ #define SPRITE_XBASE_16(localX) unsigned xBase = (localX & ~0x7) * 4 + ((localX >> 1) & 2);
#define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4; #define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \@@ -82,8 +85,11 @@ } \
} #define SPRITE_DRAW_PIXEL_16_NORMAL_OBJWIN(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \@@ -97,8 +103,11 @@ } \
} #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ if (tileData) { \@@ -109,8 +118,11 @@ #define SPRITE_XBASE_256(localX) unsigned xBase = (localX & ~0x7) * 8 + (localX & 6);
#define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 8; #define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \@@ -123,8 +135,11 @@ } \
} #define SPRITE_DRAW_PIXEL_256_NORMAL_OBJWIN(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \@@ -138,8 +153,11 @@ } \
} #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ - uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x3FFFE); \ uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vramBase)) { \ + return 0; \ + } \ LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ if (tileData) { \@@ -160,7 +178,6 @@ }
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23; x >>= 23; 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
@@ -637,14 +637,17 @@
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value) { UNUSED(renderer); bg->priority = GBARegisterBGCNTGetPriority(value); - bg->charBase &= ~0xC000; - bg->charBase |= GBARegisterBGCNTGetCharBase(value) << 14; + bg->charBase = GBARegisterBGCNTGetCharBase(value) << 14; + if (!renderer->d.vramBG[4]) { + bg->charBase &= 0xC000; + } bg->mosaic = GBARegisterBGCNTGetMosaic(value); bg->multipalette = GBARegisterBGCNTGet256Color(value); bg->screenBase &= ~0xF800; bg->screenBase |= GBARegisterBGCNTGetScreenBase(value) << 11; bg->overflow = GBARegisterBGCNTGetOverflow(value); bg->size = GBARegisterBGCNTGetSize(value); + bg->control = value; } static void GBAVideoSoftwareRendererWriteBGPA(struct GBAVideoSoftwareBackground* bg, uint16_t value) {