all repos — mgba @ e5ae0209a6974f495b4f7f18629e1113ed6c6aa0

mGBA Game Boy Advance Emulator

DS Video: Implement extended character base
Vicki Pfau vi@endrift.com
Thu, 23 Feb 2017 00:09:02 -0800
commit

e5ae0209a6974f495b4f7f18629e1113ed6c6aa0

parent

76885a1c1765f198f0efff912f60dc5da22e7d80

M include/mgba/internal/gba/renderers/video-software.hinclude/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.hinclude/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.csrc/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.csrc/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.csrc/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) {