GBA Video: Retrofit VRAM blocks
@@ -31,7 +31,10 @@
OBJ_HBLANK_FREE_LENGTH = 954, OBJ_LENGTH = 1210, - BASE_TILE = 0x00010000 + BASE_TILE = 0x00010000, + + VRAM_BLOCK_OFFSET = 14, + VRAM_BLOCK_MASK = 0x3FFF }; enum ObjMode {@@ -162,7 +165,8 @@ void (*getPixels)(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels);
void (*putPixels)(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); uint16_t* palette; - uint16_t* vram; + uint16_t* vramBG[32]; + uint16_t* vramOBJ[32]; union GBAOAM* oam; struct mTileCache* cache;
@@ -61,7 +61,7 @@ if (registers & 0x04) {
memset(gba->video.palette, 0, SIZE_PALETTE_RAM); } if (registers & 0x08) { - memset(gba->video.renderer->vram, 0, SIZE_VRAM); + memset(gba->video.vram, 0, SIZE_VRAM); } if (registers & 0x10) { memset(gba->video.oam.raw, 0, SIZE_OAM);
@@ -502,7 +502,7 @@ bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) { return false; } - uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0); + uint32_t hash = hash32(&video->vram[0x4000], 0x4000, 0); return hash == _logoHash; }
@@ -271,10 +271,10 @@ cpu->memory.activeMask = SIZE_PALETTE_RAM - 1;
break; case REGION_VRAM: if (address & 0x10000) { - cpu->memory.activeRegion = (uint32_t*) &gba->video.renderer->vram[0x8000]; + cpu->memory.activeRegion = (uint32_t*) &gba->video.vram[0x8000]; cpu->memory.activeMask = 0x00007FFF; } else { - cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram; + cpu->memory.activeRegion = (uint32_t*) gba->video.vram; cpu->memory.activeMask = 0x0000FFFF; } break;@@ -368,9 +368,9 @@ wait += waitstatesRegion[REGION_PALETTE_RAM];
#define LOAD_VRAM \ if ((address & 0x0001FFFF) < SIZE_VRAM) { \ - LOAD_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \ + LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \ } else { \ - LOAD_32(value, address & 0x00017FFC, gba->video.renderer->vram); \ + LOAD_32(value, address & 0x00017FFC, gba->video.vram); \ } \ wait += waitstatesRegion[REGION_VRAM];@@ -498,9 +498,9 @@ LOAD_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_16(value, address & 0x0001FFFE, gba->video.renderer->vram); + LOAD_16(value, address & 0x0001FFFE, gba->video.vram); } else { - LOAD_16(value, address & 0x00017FFE, gba->video.renderer->vram); + LOAD_16(value, address & 0x00017FFE, gba->video.vram); } break; case REGION_OAM:@@ -599,9 +599,9 @@ value = ((uint8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - value = ((uint8_t*) gba->video.renderer->vram)[address & 0x0001FFFF]; + value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF]; } else { - value = ((uint8_t*) gba->video.renderer->vram)[address & 0x00017FFF]; + value = ((uint8_t*) gba->video.vram)[address & 0x00017FFF]; } break; case REGION_OAM:@@ -682,11 +682,11 @@ gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
#define STORE_VRAM \ if ((address & 0x0001FFFF) < SIZE_VRAM) { \ - STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \ + STORE_32(value, address & 0x0001FFFC, gba->video.vram); \ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \ } else { \ - STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); \ + STORE_32(value, address & 0x00017FFC, gba->video.vram); \ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \ } \@@ -787,10 +787,10 @@ gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram); + STORE_16(value, address & 0x0001FFFE, gba->video.vram); gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } else { - STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram); + STORE_16(value, address & 0x00017FFE, gba->video.vram); gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE); } break;@@ -857,7 +857,7 @@ // TODO: check BG mode
mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address); break; } - gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8); + gba->video.vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8); gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); break; case REGION_OAM:@@ -1036,18 +1036,18 @@ case REGION_IO:
mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address); break; case REGION_PALETTE_RAM: - LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); + LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value); gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_32(oldValue, address & 0x0001FFFC, gba->video.renderer->vram); - STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); + LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); + STORE_32(value, address & 0x0001FFFC, gba->video.vram); } else { - LOAD_32(oldValue, address & 0x00017FFC, gba->video.renderer->vram); - STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); + LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram); + STORE_32(value, address & 0x00017FFC, gba->video.vram); } break; case REGION_OAM:@@ -1112,11 +1112,11 @@ gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_16(oldValue, address & 0x0001FFFE, gba->video.renderer->vram); - STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram); + LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram); + STORE_16(value, address & 0x0001FFFE, gba->video.vram); } else { - LOAD_16(oldValue, address & 0x00017FFE, gba->video.renderer->vram); - STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram); + LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram); + STORE_16(value, address & 0x00017FFE, gba->video.vram); } break; case REGION_OAM:
@@ -21,8 +21,10 @@
#define MODE_2_MOSAIC(COORD) \ if (!mosaicWait) { \ COORD \ - mapData = screenBase[(localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; \ - pixelData = charBase[(mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; \ + uint32_t screenBase = background->screenBase + (localX >> 11) + (((localY >> 7) & 0x7F0) << background->size); \ + mapData = ((uint8_t*) renderer->d.vramBG[screenBase >> VRAM_BLOCK_OFFSET])[screenBase & VRAM_BLOCK_MASK]; \ + uint32_t charBase = background->charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8); \ + pixelData = ((uint8_t*) renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET])[charBase & VRAM_BLOCK_MASK]; \ \ mosaicWait = mosaicH; \ } else { \@@ -31,8 +33,10 @@ }
#define MODE_2_NO_MOSAIC(COORD) \ COORD \ - mapData = screenBase[(localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; \ - pixelData = charBase[(mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; + uint32_t screenBase = background->screenBase + (localX >> 11) + (((localY >> 7) & 0x7F0) << background->size); \ + mapData = ((uint8_t*) renderer->d.vramBG[screenBase >> VRAM_BLOCK_OFFSET])[screenBase & VRAM_BLOCK_MASK]; \ + uint32_t charBase = background->charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8); \ + pixelData = ((uint8_t*) renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET])[charBase & VRAM_BLOCK_MASK]; \ #define MODE_2_LOOP(MOSAIC, COORD, BLEND, OBJWIN) \ for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { \@@ -66,8 +70,6 @@ int sizeAdjusted = 0x8000 << background->size;
BACKGROUND_BITMAP_INIT; - uint8_t* screenBase = &((uint8_t*) renderer->d.vram)[background->screenBase]; - uint8_t* charBase = &((uint8_t*) renderer->d.vram)[background->charBase]; uint8_t mapData; uint8_t pixelData = 0;@@ -100,7 +102,7 @@ for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); if (!mosaicWait) { - LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vram); + LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vramBG[0]); #ifndef COLOR_16_BIT unsigned color32; color32 = 0;@@ -153,7 +155,7 @@ for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); if (!mosaicWait) { - color = ((uint8_t*)renderer->d.vram)[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS]; + color = ((uint8_t*)renderer->d.vramBG[0])[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS]; mosaicWait = mosaicH; } else {@@ -191,7 +193,7 @@ for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
BACKGROUND_BITMAP_ITERATE(160, 128); if (!mosaicWait) { - LOAD_16(color, offset + (localX >> 8) * 2 + (localY >> 8) * 320, renderer->d.vram); + LOAD_16(color, offset + (localX >> 8) * 2 + (localY >> 8) * 320, renderer->d.vramBG[0]); #ifndef COLOR_16_BIT unsigned color32 = 0; color32 |= (color << 9) & 0xF80000;
@@ -13,8 +13,9 @@ xBase = localX & 0xF8; \
if (background->size & 1) { \ xBase += (localX & 0x100) << 5; \ } \ - screenBase = yBase + (xBase >> 3); \ - LOAD_16(mapData, screenBase << 1, vram); \ + screenBase = background->screenBase + yBase + (xBase >> 2); \ + uint16_t* screenBlock = renderer->d.vramBG[screenBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(mapData, screenBase & VRAM_BLOCK_MASK, screenBlock); \ localY = inY & 0x7; \ if (GBA_TEXT_MAP_VFLIP(mapData)) { \ localY = 7 - localY; \@@ -24,22 +25,29 @@ #define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_16(BLEND, OBJWIN) \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ - LOAD_32(tileData, charBase, vram); \ - if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ - tileData >>= 4 * mod8; \ - for (; outX < end; ++outX, ++pixel) { \ - BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \ - } \ - } else { \ - for (outX = end - 1; outX >= renderer->start; --outX) { \ - uint32_t* pixel = &renderer->row[outX]; \ - BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (LIKELY(vram)) { \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ + if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ + tileData >>= 4 * mod8; \ + for (; outX < end; ++outX, ++pixel) { \ + BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \ + } \ + } else { \ + for (outX = end - 1; outX >= renderer->start; --outX) { \ + uint32_t* pixel = &renderer->row[outX]; \ + BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \ + } \ } \ } #define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_16(BLEND, OBJWIN) \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ - LOAD_32(tileData, charBase, vram); \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vram)) { \ + return; \ + } \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ pixel = &renderer->row[outX]; \@@ -84,12 +92,13 @@ } else { \
BACKGROUND_TEXT_SELECT_CHARACTER; \ } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ - if (UNLIKELY(charBase >= 0x10000)) { \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vram)) { \ carryData = 0; \ } else { \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ tileData >>= 4 * baseX; \ } else { \@@ -105,15 +114,16 @@ } \
for (; length; ++tileX) { \ BACKGROUND_TEXT_SELECT_CHARACTER; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ tileData = carryData; \ for (; x < 8 && length; ++x, --length) { \ if (!mosaicWait) { \ - if (UNLIKELY(charBase >= 0x10000)) { \ + if (UNLIKELY(!vram)) { \ carryData = 0; \ } else { \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ tileData >>= x * 4; \ } else { \@@ -140,11 +150,12 @@ BACKGROUND_TEXT_SELECT_CHARACTER; \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ - if (UNLIKELY(charBase >= 0x10000)) { \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vram)) { \ pixel += 8; \ continue; \ } \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ if (tileData) { \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \@@ -171,12 +182,13 @@ }
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256(BLEND, OBJWIN) \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ int end2 = end - 4; \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ int shift = inX & 0x3; \ - if (LIKELY(charBase < 0x10000)) { \ + if (LIKELY(vram)) { \ if (end2 > outX) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ tileData >>= 8 * shift; \ shift = 0; \ for (; outX < end2; ++outX, ++pixel) { \@@ -185,8 +197,8 @@ } \
} \ } \ \ - if (LIKELY(charBase < 0x10000)) { \ - LOAD_32(tileData, charBase + 4, vram); \ + if (LIKELY(vram)) { \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ tileData >>= 8 * shift; \ for (; outX < end; ++outX, ++pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \@@ -196,9 +208,9 @@ } else { \
int start = outX; \ outX = end - 1; \ pixel = &renderer->row[outX]; \ - if (LIKELY(charBase < 0x10000)) { \ + if (LIKELY(vram)) { \ if (end2 > start) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ for (; outX >= end2; --outX, --pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ } \@@ -206,7 +218,7 @@ charBase += 4; \
} \ } \ \ - if (LIKELY(charBase < 0x10000)) { \ + if (LIKELY(vram)) { \ LOAD_32(tileData, charBase, vram); \ for (; outX >= renderer->start; --outX, --pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \@@ -218,21 +230,22 @@ }
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ - if (UNLIKELY(charBase >= 0x10000)) { \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vram)) { \ return; \ } \ int end = mod8 - 4; \ pixel = &renderer->row[outX]; \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ if (end > 0) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ for (; outX < renderer->end - end; ++outX, ++pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ } \ charBase += 4; \ } \ \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ for (; outX < renderer->end; ++outX, ++pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ } \@@ -242,7 +255,7 @@ int start = outX; \
outX = renderer->end - 1; \ pixel = &renderer->row[outX]; \ if (end > 0) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ tileData >>= 8 * shift; \ for (; outX >= start + 4; --outX, --pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \@@ -250,7 +263,7 @@ } \
shift = 0; \ } \ \ - LOAD_32(tileData, charBase + 4, vram); \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ tileData >>= 8 * shift; \ for (; outX >= start; --outX, --pixel) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \@@ -266,12 +279,13 @@ #define DRAW_BACKGROUND_MODE_0_TILES_256(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \ BACKGROUND_TEXT_SELECT_CHARACTER; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ - if (UNLIKELY(charBase >= 0x10000)) { \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ + if (UNLIKELY(!vram)) { \ pixel += 8; \ continue; \ } \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ if (tileData) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \@@ -279,7 +293,7 @@ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \ } \ pixel += 4; \ - LOAD_32(tileData, charBase + 4, vram); \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ if (tileData) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \@@ -288,7 +302,7 @@ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
} \ pixel += 4; \ } else { \ - LOAD_32(tileData, charBase + 4, vram); \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ if (tileData) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \@@ -296,7 +310,7 @@ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \ } \ pixel += 4; \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ if (tileData) { \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \ BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \@@ -311,26 +325,27 @@ #define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \ BACKGROUND_TEXT_SELECT_CHARACTER; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ + vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ tileData = carryData; \ for (x = 0; x < 8; ++x) { \ if (!mosaicWait) { \ - if (UNLIKELY(charBase >= 0x10000)) { \ + if (UNLIKELY(!vram)) { \ carryData = 0; \ } else { \ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \ if (x >= 4) { \ - LOAD_32(tileData, charBase + 4, vram); \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ tileData >>= (x - 4) * 8; \ } else { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ tileData >>= x * 8; \ } \ } else { \ if (x >= 4) { \ - LOAD_32(tileData, charBase, vram); \ + LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \ tileData >>= (7 - x) * 8; \ } else { \ - LOAD_32(tileData, charBase + 4, vram); \ + LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \ tileData >>= (3 - x) * 8; \ } \ } \@@ -425,7 +440,7 @@ yBase += inY & 0x100;
} else if (background->size == 3) { yBase += (inY & 0x100) << 1; } - yBase = (background->screenBase >> 1) + (yBase << 2); + yBase <<= 3; int localX; int localY;@@ -460,7 +475,7 @@ int pixelData;
int paletteData; int tileX = 0; int tileEnd = ((length + inX) >> 3) - (inX >> 3); - uint16_t* vram = renderer->d.vram; + uint16_t* vram = NULL; if (!objwinSlowPath) { if (!(flags & FLAG_TARGET_2)) {
@@ -68,7 +68,9 @@ #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) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \@@ -80,7 +82,9 @@ } \
} #define SPRITE_DRAW_PIXEL_16_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \@@ -93,7 +97,9 @@ } \
} #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \@@ -103,7 +109,9 @@ #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) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \@@ -115,7 +123,9 @@ } \
} #define SPRITE_DRAW_PIXEL_256_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \@@ -128,7 +138,9 @@ } \
} #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + uint32_t spriteBase = ((yBase + charBase + xBase) & 0x7FFE); \ + uint16_t* vramBase = renderer->d.vramOBJ[spriteBase >> VRAM_BLOCK_OFFSET]; \ + LOAD_16(tileData, spriteBase & VRAM_BLOCK_MASK, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \@@ -147,8 +159,8 @@ return 0;
} int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23; x >>= 23; - uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1]; unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * 0x20; + uint16_t* vramBase = NULL; if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) { return 0; }
@@ -75,7 +75,14 @@ RingFIFOInit(&proxyRenderer->dirtyQueue, 0x40000);
proxyRenderer->vramProxy = anonymousMemoryMap(SIZE_VRAM); proxyRenderer->backend->palette = proxyRenderer->paletteProxy; - proxyRenderer->backend->vram = proxyRenderer->vramProxy; + memset(renderer->vramBG, 0, sizeof(renderer->vramBG)); + proxyRenderer->backend->vramBG[0] = &proxyRenderer->vramProxy[0x0000]; + proxyRenderer->backend->vramBG[1] = &proxyRenderer->vramProxy[0x2000]; + proxyRenderer->backend->vramBG[2] = &proxyRenderer->vramProxy[0x4000]; + proxyRenderer->backend->vramBG[3] = &proxyRenderer->vramProxy[0x6000]; + memset(renderer->vramOBJ, 0, sizeof(renderer->vramOBJ)); + proxyRenderer->backend->vramOBJ[0] = &proxyRenderer->vramProxy[0x8000]; + proxyRenderer->backend->vramOBJ[1] = &proxyRenderer->vramProxy[0xA000]; proxyRenderer->backend->oam = &proxyRenderer->oamProxy; proxyRenderer->backend->cache = NULL;@@ -95,7 +102,7 @@ ConditionWait(&proxyRenderer->fromThreadCond, &proxyRenderer->mutex);
} memcpy(&proxyRenderer->oamProxy.raw, &renderer->oam->raw, SIZE_OAM); memcpy(proxyRenderer->paletteProxy, renderer->palette, SIZE_PALETTE_RAM); - memcpy(proxyRenderer->vramProxy, renderer->vram, SIZE_VRAM); + memcpy(&proxyRenderer->vramProxy, renderer->vramBG[0], SIZE_VRAM); proxyRenderer->backend->reset(proxyRenderer->backend); MutexUnlock(&proxyRenderer->mutex); }@@ -242,7 +249,7 @@ 0xABCD,
0xDEADBEEF, }; _writeData(proxyRenderer, &dirty, sizeof(dirty)); - _writeData(proxyRenderer, &proxyRenderer->d.vram[j * 0x800], 0x1000); + _writeData(proxyRenderer, &proxyRenderer->d.vramBG[0][j * 0x800], 0x1000); } } struct GBAVideoDirtyInfo dirty = {
@@ -95,7 +95,14 @@ if (video->vram) {
mappedMemoryFree(video->vram, SIZE_VRAM); } video->vram = anonymousMemoryMap(SIZE_VRAM); - video->renderer->vram = video->vram; + memset(video->renderer->vramBG, 0, sizeof(video->renderer->vramBG)); + video->renderer->vramBG[0] = &video->vram[0x0000]; + video->renderer->vramBG[1] = &video->vram[0x2000]; + video->renderer->vramBG[2] = &video->vram[0x4000]; + video->renderer->vramBG[3] = &video->vram[0x6000]; + memset(video->renderer->vramOBJ, 0, sizeof(video->renderer->vramOBJ)); + video->renderer->vramOBJ[0] = &video->vram[0x8000]; + video->renderer->vramOBJ[1] = &video->vram[0xA000]; memset(video->palette, 0, sizeof(video->palette)); memset(video->oam.raw, 0, sizeof(video->oam.raw));@@ -114,7 +121,14 @@ video->renderer->deinit(video->renderer);
renderer->cache = video->renderer->cache; video->renderer = renderer; renderer->palette = video->palette; - renderer->vram = video->vram; + memset(renderer->vramBG, 0, sizeof(renderer->vramBG)); + renderer->vramBG[0] = &video->vram[0x0000]; + renderer->vramBG[1] = &video->vram[0x2000]; + renderer->vramBG[2] = &video->vram[0x4000]; + renderer->vramBG[3] = &video->vram[0x6000]; + memset(renderer->vramOBJ, 0, sizeof(renderer->vramOBJ)); + renderer->vramOBJ[0] = &video->vram[0x8000]; + renderer->vramOBJ[1] = &video->vram[0xA000]; renderer->oam = &video->oam; video->renderer->init(video->renderer); }@@ -295,7 +309,7 @@ // Nothing to do
} void GBAVideoSerialize(const struct GBAVideo* video, struct GBASerializedState* state) { - memcpy(state->vram, video->renderer->vram, SIZE_VRAM); + memcpy(state->vram, video->vram, SIZE_VRAM); memcpy(state->oam, video->oam.raw, SIZE_OAM); memcpy(state->pram, video->palette, SIZE_PALETTE_RAM); STORE_32(video->event.when - mTimingCurrentTime(&video->p->timing), 0, &state->video.nextEvent);@@ -303,7 +317,7 @@ STORE_32(video->frameCounter, 0, &state->video.frameCounter);
} void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState* state) { - memcpy(video->renderer->vram, state->vram, SIZE_VRAM); + memcpy(video->vram, state->vram, SIZE_VRAM); uint16_t value; int i; for (i = 0; i < SIZE_OAM; i += 2) {