mirror of https://github.com/mgba-emu/mgba.git
GB Video: Draw SGB border pieces that overlap GB graphics (fixes #1339)
This commit is contained in:
parent
ca0cfa077e
commit
70f75bba49
1
CHANGES
1
CHANGES
|
@ -14,6 +14,7 @@ Features:
|
|||
Emulation fixes:
|
||||
- ARM7: Fix unsigned multiply timing
|
||||
- GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032)
|
||||
- GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339)
|
||||
- GBA: Improve timing when not booting from BIOS
|
||||
- GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059)
|
||||
- GBA I/O: Redo internal key input, enabling edge-based key IRQs
|
||||
|
|
|
@ -60,6 +60,7 @@ struct GBVideoSoftwareRenderer {
|
|||
uint8_t sgbPacket[128];
|
||||
uint8_t sgbCommandHeader;
|
||||
bool sgbBorders;
|
||||
uint32_t sgbBorderMask[18];
|
||||
|
||||
uint8_t lastHighlightAmount;
|
||||
};
|
||||
|
|
|
@ -64,37 +64,58 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) {
|
|||
}
|
||||
int x, y;
|
||||
for (y = 0; y < 224; ++y) {
|
||||
for (x = 0; x < 256; x += 8) {
|
||||
if (x >= 48 && x < 208 && y >= 40 && y < 184) {
|
||||
continue;
|
||||
int localY = y & 0x7;
|
||||
if (!localY && y >= 40 && y < 184) {
|
||||
renderer->sgbBorderMask[(y - 40) >> 3] = 0;
|
||||
}
|
||||
for (x = 0; x < 256; x += 8) {
|
||||
uint16_t mapData;
|
||||
LOAD_16LE(mapData, (x >> 2) + (y & ~7) * 8, renderer->d.sgbMapRam);
|
||||
if (UNLIKELY(SGBBgAttributesGetTile(mapData) >= 0x100)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int localY = y & 0x7;
|
||||
if (SGBBgAttributesIsYFlip(mapData)) {
|
||||
localY = 7 - localY;
|
||||
if (x >= 48 && x < 208 && y >= 40 && y < 184) {
|
||||
if (!localY) {
|
||||
unsigned tileBase = SGBBgAttributesGetTile(mapData) * 8;
|
||||
uint32_t bits = 0;
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 0];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 1];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 2];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 3];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 4];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 5];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 6];
|
||||
bits |= ((uint32_t*) renderer->d.sgbCharRam)[tileBase + 7];
|
||||
if (bits) {
|
||||
renderer->sgbBorderMask[(y - 40) >> 3] |= 1 << ((x - 48) >> 3);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int yFlip = 0;
|
||||
if (SGBBgAttributesIsYFlip(mapData)) {
|
||||
yFlip = 7;
|
||||
}
|
||||
unsigned tileBase = (SGBBgAttributesGetTile(mapData) * 16 + (localY ^ yFlip)) * 2;
|
||||
uint8_t tileData[4];
|
||||
tileData[0] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x00];
|
||||
tileData[1] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x01];
|
||||
tileData[2] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x10];
|
||||
tileData[3] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x11];
|
||||
tileData[0] = renderer->d.sgbCharRam[tileBase + 0x00];
|
||||
tileData[1] = renderer->d.sgbCharRam[tileBase + 0x01];
|
||||
tileData[2] = renderer->d.sgbCharRam[tileBase + 0x10];
|
||||
tileData[3] = renderer->d.sgbCharRam[tileBase + 0x11];
|
||||
|
||||
size_t base = y * renderer->outputBufferStride + x;
|
||||
int paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10;
|
||||
int colorSelector;
|
||||
|
||||
int flip = 0;
|
||||
int xFlip = 0;
|
||||
if (SGBBgAttributesIsXFlip(mapData)) {
|
||||
flip = 7;
|
||||
xFlip = 7;
|
||||
}
|
||||
for (i = 7; i >= 0; --i) {
|
||||
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
|
||||
renderer->outputBuffer[(base + 7 - i) ^ flip] = renderer->palette[paletteBase | colorSelector];
|
||||
renderer->outputBuffer[(base + 7 - i) ^ xFlip] = renderer->palette[paletteBase | colorSelector];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,6 +254,7 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
|
|||
}
|
||||
|
||||
memset(softwareRenderer->palette, 0, sizeof(softwareRenderer->palette));
|
||||
memset(softwareRenderer->sgbBorderMask, 0, sizeof(softwareRenderer->sgbBorderMask));
|
||||
|
||||
softwareRenderer->lastHighlightAmount = 0;
|
||||
}
|
||||
|
@ -667,6 +689,46 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
for (; x < endX; ++x) {
|
||||
row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & OBJ_PRIO_MASK]];
|
||||
}
|
||||
if (softwareRenderer->sgbBorderMask[y >> 3]) {
|
||||
uint32_t borderMask = softwareRenderer->sgbBorderMask[y >> 3];
|
||||
int localY = y & 0x7;
|
||||
for (x = startX; x < endX; x += 8) {
|
||||
if (!(borderMask & (1 << (x >> 3)))) {
|
||||
continue;
|
||||
}
|
||||
uint16_t mapData;
|
||||
LOAD_16LE(mapData, (x >> 2) + 12 + (y & ~7) * 8 + 320, softwareRenderer->d.sgbMapRam);
|
||||
if (UNLIKELY(SGBBgAttributesGetTile(mapData) >= 0x100)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int yFlip = 0;
|
||||
if (SGBBgAttributesIsYFlip(mapData)) {
|
||||
yFlip = 7;
|
||||
}
|
||||
unsigned tileBase = (SGBBgAttributesGetTile(mapData) * 16 + (localY ^ yFlip)) * 2;
|
||||
uint8_t tileData[4];
|
||||
tileData[0] = softwareRenderer->d.sgbCharRam[tileBase + 0x00];
|
||||
tileData[1] = softwareRenderer->d.sgbCharRam[tileBase + 0x01];
|
||||
tileData[2] = softwareRenderer->d.sgbCharRam[tileBase + 0x10];
|
||||
tileData[3] = softwareRenderer->d.sgbCharRam[tileBase + 0x11];
|
||||
|
||||
int paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10;
|
||||
int colorSelector;
|
||||
|
||||
int flip = 0;
|
||||
if (SGBBgAttributesIsXFlip(mapData)) {
|
||||
flip = 7;
|
||||
}
|
||||
int i;
|
||||
for (i = 7; i >= 0; --i) {
|
||||
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
|
||||
if (colorSelector) {
|
||||
row[(x + 7 - i) ^ flip] = softwareRenderer->palette[paletteBase | colorSelector];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue