diff --git a/CHANGES b/CHANGES index f856b9737..8e349e6eb 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Bugfixes: - GBA Video: Fix windows not disabling target 1 appropriately (fixes #161) - Debugger: Align PC-relative loads in Thumb - Debugger: Fix watchpoints triggering too late + - GBA Video: Fix sprite mis-ordering behavior in some cases (fixes #168) Misc: - Qt: Disable sync to video by default - GBA: Exit cleanly on FATAL if the port supports it diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 91bd20e41..bb4d3a00c 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -1584,8 +1584,13 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru #define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \ LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ - if (tileData && (renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags) { \ - renderer->spriteLayer[outX] = palette[tileData] | flags; \ + current = renderer->spriteLayer[outX]; \ + if ((current & FLAG_ORDER_MASK) > flags) { \ + if (tileData) { \ + renderer->spriteLayer[outX] = palette[tileData] | flags; \ + } else if (current != FLAG_UNWRITTEN) { \ + renderer->spriteLayer[outX] = (current & ~FLAG_ORDER_MASK) | GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY; \ + } \ } #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ @@ -1601,8 +1606,13 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru #define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \ LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ - if (tileData && (renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags) { \ - renderer->spriteLayer[outX] = palette[tileData] | flags; \ + current = renderer->spriteLayer[outX]; \ + if ((current & FLAG_ORDER_MASK) > flags) { \ + if (tileData) { \ + renderer->spriteLayer[outX] = palette[tileData] | flags; \ + } else if (current != FLAG_UNWRITTEN) { \ + renderer->spriteLayer[outX] = (current & ~FLAG_ORDER_MASK) | GBAObjAttributesCGetPriority(sprite->c) << OFFSET_PRIORITY; \ + } \ } #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ @@ -1636,6 +1646,7 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G int inY = y - (int) GBAObjAttributesAGetY(sprite->a); + uint32_t current; if (GBAObjAttributesAIsTransformed(sprite->a)) { int totalWidth = width << GBAObjAttributesAGetDoubleSize(sprite->a); int totalHeight = height << GBAObjAttributesAGetDoubleSize(sprite->a);