GBA Video: Retrofit VRAM blocks

This commit is contained in:
Vicki Pfau 2017-02-21 11:43:01 -08:00
parent 1039569b01
commit 9f31a1cc2c
9 changed files with 146 additions and 92 deletions

View File

@ -31,7 +31,10 @@ enum {
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 @@ struct GBAVideoRenderer {
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;

View File

@ -61,7 +61,7 @@ static void _RegisterRamReset(struct GBA* gba) {
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);

View File

@ -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;
}

View File

@ -271,10 +271,10 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
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 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
#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 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
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 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
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 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
#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 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
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 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
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 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o
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 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o
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:

View File

@ -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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode2(struct GBAVideoSoftwareRenderer
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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer
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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer
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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer
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;

View File

@ -13,8 +13,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
} \
} \
\
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 @@
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 @@
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, 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 @@
} \
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, 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 @@
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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
} 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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
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)) {

View File

@ -68,7 +68,9 @@
#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_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 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
}
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;
}

View File

@ -75,7 +75,14 @@ void GBAVideoThreadProxyRendererInit(struct GBAVideoRenderer* renderer) {
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 @@ void GBAVideoThreadProxyRendererReset(struct GBAVideoRenderer* renderer) {
}
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 @@ void GBAVideoThreadProxyRendererDrawScanline(struct GBAVideoRenderer* renderer,
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 = {

View File

@ -95,7 +95,14 @@ void GBAVideoReset(struct GBAVideo* video) {
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 @@ void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer*
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 @@ static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, si
}
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 @@ void GBAVideoSerialize(const struct GBAVideo* video, struct GBASerializedState*
}
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) {