all repos — mgba @ 3415484d9db5528bfbeb71a5bf0bb30d0eeef410

mGBA Game Boy Advance Emulator

GBA Video: Fix out of bounds sprite transforms
Jeffrey Pfau jeffrey@endrift.com
Sun, 11 Dec 2016 17:55:41 -0800
commit

3415484d9db5528bfbeb71a5bf0bb30d0eeef410

parent

4085b9cdc5cce9397c349573bd6fcf53a3bae8ec

2 files changed, 19 insertions(+), 13 deletions(-)

jump to
M CHANGESCHANGES

@@ -34,6 +34,7 @@ - GBA BIOS: Implement BitUnPack

- GBA: Add savegame override for Crash Bandicoot 2 - ARM7: PSR mode bits should not get sign extended - GBA: Only unhalt CPU if an IRQ actually fires + - GBA Video: Fix out of bounds sprite transforms Misc: - SDL: Remove scancode key input - GBA Video: Clean up unused timers
M src/gba/renderers/software-obj.csrc/gba/renderers/software-obj.c

@@ -52,8 +52,8 @@ } \

renderer->spriteCyclesRemaining -= 2; \ xAccum += mat.a; \ yAccum += mat.c; \ - int localX = (xAccum >> 8) + (width >> 1); \ - int localY = (yAccum >> 8) + (height >> 1); \ + int localX = xAccum >> 8; \ + int localY = yAccum >> 8; \ \ if (localX & widthMask || localY & heightMask) { \ break; \

@@ -200,24 +200,25 @@ }

int outX = x >= start ? x : start; int condition = x + totalWidth; int inX = outX - x; - int xAccum = mat.a * (inX - 1 - (totalWidth >> 1)) + mat.b * (inY - (totalHeight >> 1)); - int yAccum = mat.c * (inX - 1 - (totalWidth >> 1)) + mat.d * (inY - (totalHeight >> 1)); - if (end < condition) { condition = end; } + int xAccum = mat.a * (inX - 1 - (totalWidth >> 1)) + mat.b * (inY - (totalHeight >> 1)) + (width << 7); + int yAccum = mat.c * (inX - 1 - (totalWidth >> 1)) + mat.d * (inY - (totalHeight >> 1)) + (height << 7); + // Clip off early pixels + // TODO: Transform end coordinates too if (mat.a) { - if ((xAccum >> 8) < -(width >> 1)) { - int32_t diffX = -(width << 7) - xAccum - 1; + if ((xAccum >> 8) < 0) { + int32_t diffX = -xAccum - 1; int32_t x = mat.a ? diffX / mat.a : 0; xAccum += mat.a * x; yAccum += mat.c * x; outX += x; inX += x; - } else if ((xAccum >> 8) >= (width >> 1)) { - int32_t diffX = (width << 7) - xAccum; + } else if ((xAccum >> 8) >= width) { + int32_t diffX = (width << 8) - xAccum; int32_t x = mat.a ? diffX / mat.a : 0; xAccum += mat.a * x; yAccum += mat.c * x;

@@ -226,21 +227,25 @@ inX += x;

} } if (mat.c) { - if ((yAccum >> 8) < -(height >> 1)) { - int32_t diffY = -(height << 7) - yAccum - 1; + if ((yAccum >> 8) < 0) { + int32_t diffY = - yAccum - 1; int32_t y = mat.c ? diffY / mat.c : 0; xAccum += mat.a * y; yAccum += mat.c * y; outX += y; inX += y; - } else if ((yAccum >> 8) >= (height >> 1)) { - int32_t diffY = (height << 7) - yAccum; + } else if ((yAccum >> 8) >= height) { + int32_t diffY = (height << 8) - yAccum; int32_t y = mat.c ? diffY / mat.c : 0; xAccum += mat.a * y; yAccum += mat.c * y; outX += y; inX += y; } + } + + if (outX < start || outX >= condition) { + return 0; } if (!GBAObjAttributesAIs256Color(sprite->a)) {