GBA Video: Fix out of bounds sprite transforms

This commit is contained in:
Jeffrey Pfau 2016-12-11 17:55:41 -08:00
parent 961035cd92
commit 9ec050bfcb
2 changed files with 19 additions and 13 deletions

View File

@ -22,6 +22,7 @@ Bugfixes:
- All: Fix fullscreen config option being ignored - All: Fix fullscreen config option being ignored
- GBA: Add savegame override for Crash Bandicoot 2 - GBA: Add savegame override for Crash Bandicoot 2
- ARM7: PSR mode bits should not get sign extended - ARM7: PSR mode bits should not get sign extended
- GBA Video: Fix out of bounds sprite transforms
- GBA: Only unhalt CPU if appropriate bit is set in IE - GBA: Only unhalt CPU if appropriate bit is set in IE
Misc: Misc:
- PSP2: Improved controller rumble - PSP2: Improved controller rumble

View File

@ -52,8 +52,8 @@
renderer->spriteCyclesRemaining -= 2; \ renderer->spriteCyclesRemaining -= 2; \
xAccum += mat.a; \ xAccum += mat.a; \
yAccum += mat.c; \ yAccum += mat.c; \
int localX = (xAccum >> 8) + (width >> 1); \ int localX = xAccum >> 8; \
int localY = (yAccum >> 8) + (height >> 1); \ int localY = yAccum >> 8; \
\ \
if (localX & widthMask || localY & heightMask) { \ if (localX & widthMask || localY & heightMask) { \
break; \ break; \
@ -200,24 +200,25 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
int outX = x >= start ? x : start; int outX = x >= start ? x : start;
int condition = x + totalWidth; int condition = x + totalWidth;
int inX = outX - x; 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) { if (end < condition) {
condition = end; 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 // Clip off early pixels
// TODO: Transform end coordinates too
if (mat.a) { if (mat.a) {
if ((xAccum >> 8) < -(width >> 1)) { if ((xAccum >> 8) < 0) {
int32_t diffX = -(width << 7) - xAccum - 1; int32_t diffX = -xAccum - 1;
int32_t x = mat.a ? diffX / mat.a : 0; int32_t x = mat.a ? diffX / mat.a : 0;
xAccum += mat.a * x; xAccum += mat.a * x;
yAccum += mat.c * x; yAccum += mat.c * x;
outX += x; outX += x;
inX += x; inX += x;
} else if ((xAccum >> 8) >= (width >> 1)) { } else if ((xAccum >> 8) >= width) {
int32_t diffX = (width << 7) - xAccum; int32_t diffX = (width << 8) - xAccum;
int32_t x = mat.a ? diffX / mat.a : 0; int32_t x = mat.a ? diffX / mat.a : 0;
xAccum += mat.a * x; xAccum += mat.a * x;
yAccum += mat.c * x; yAccum += mat.c * x;
@ -226,15 +227,15 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
} }
} }
if (mat.c) { if (mat.c) {
if ((yAccum >> 8) < -(height >> 1)) { if ((yAccum >> 8) < 0) {
int32_t diffY = -(height << 7) - yAccum - 1; int32_t diffY = - yAccum - 1;
int32_t y = mat.c ? diffY / mat.c : 0; int32_t y = mat.c ? diffY / mat.c : 0;
xAccum += mat.a * y; xAccum += mat.a * y;
yAccum += mat.c * y; yAccum += mat.c * y;
outX += y; outX += y;
inX += y; inX += y;
} else if ((yAccum >> 8) >= (height >> 1)) { } else if ((yAccum >> 8) >= height) {
int32_t diffY = (height << 7) - yAccum; int32_t diffY = (height << 8) - yAccum;
int32_t y = mat.c ? diffY / mat.c : 0; int32_t y = mat.c ? diffY / mat.c : 0;
xAccum += mat.a * y; xAccum += mat.a * y;
yAccum += mat.c * y; yAccum += mat.c * y;
@ -243,6 +244,10 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
} }
} }
if (outX < start || outX >= condition) {
return 0;
}
if (!GBAObjAttributesAIs256Color(sprite->a)) { if (!GBAObjAttributesAIs256Color(sprite->a)) {
palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4]; palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4];
if (flags & FLAG_OBJWIN) { if (flags & FLAG_OBJWIN) {