mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Retrofit VRAM blocks
This commit is contained in:
parent
1039569b01
commit
9f31a1cc2c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 @@ 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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue