From 0abc2d2ddd9f22f4b4fa5c348873705041ddec93 Mon Sep 17 00:00:00 2001 From: neonloop Date: Fri, 13 Aug 2021 15:38:49 +0000 Subject: Fixes several scaling problems - Shouldn't read beyond last line - Overflow issue with first add when averaging - Only copy reported screen width (fixes some gambatte glitches) --- scale.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'scale.c') diff --git a/scale.c b/scale.c index 39175e2..5db2746 100644 --- a/scale.c +++ b/scale.c @@ -29,18 +29,6 @@ static unsigned dst_w, dst_h, dst_offs; struct dimensions prev; #if __ARM_ARCH >= 5 -static inline uint32_t average32(uint32_t c1, uint32_t c2) { - uint32_t ret, lowbits = 0x08210821; - asm ("eor %0, %2, %3\r\n" - "and %0, %0, %1\r\n" - "add %0, %3, %0\r\n" - "adds %0, %0, %2\r\n" - "lsr %0, %0, #1\r\n" - "orrcs %0, %0, #0x80000000\r\n" - : "=&r" (ret) : "r" (lowbits), "r" (c1), "r" (c2) : "cc" ); - return ret; -} - static inline uint32_t average16(uint32_t c1, uint32_t c2) { uint32_t ret, lowbits = 0x0821; asm ("eor %0, %2, %3\r\n" @@ -52,13 +40,41 @@ static inline uint32_t average16(uint32_t c1, uint32_t c2) { return ret; } +static inline uint32_t average32(uint32_t c1, uint32_t c2) { + uint32_t ret, lowbits = 0x08210821; + + asm ("eor %0, %3, %1\r\n" + "and %0, %0, %2\r\n" + "adds %0, %1, %0\r\n" + "and %1, %1, #0\r\n" + "movcs %1, #0x80000000\r\n" + "adds %0, %0, %3\r\n" + "rrx %0, %0\r\n" + "orr %0, %0, %1\r\n" + : "=&r" (ret), "+r" (c2) : "r" (lowbits), "r" (c1) : "cc" ); + + return ret; +} + #define AVERAGE16_NOCHK(c1, c2) (average16((c1), (c2))) #define AVERAGE32_NOCHK(c1, c2) (average32((c1), (c2))) #else -#define AVERAGE16_NOCHK(c1, c2) (((c1) + (c2) + (((c1) ^ (c2)) & 0x0821))>>1) //More accurate -#define AVERAGE32_NOCHK(c1, c2) ((((c1) + (c2) + (((c1) ^ (c2)) & 0x08210821))>>1) | (((c1) + (c2) < (c1)) << 31)) +static inline uint32_t average16(uint32_t c1, uint32_t c2) { + return (c1 + c2 + ((c1 ^ c2) & 0x0821))>>1; +} + +static inline uint32_t average32(uint32_t c1, uint32_t c2) { + uint32_t sum = c1 + c2; + uint32_t ret = sum + ((c1 ^ c2) & 0x08210821); + uint32_t of = ((sum < c1) | (ret < sum)) << 31; + + return (ret >> 1) | of; +} + +#define AVERAGE16_NOCHK(c1, c2) (average16((c1), (c2))) +#define AVERAGE32_NOCHK(c1, c2) (average32((c1), (c2))) #endif @@ -82,7 +98,7 @@ static void scale_1x(unsigned w, unsigned h, size_t pitch, const void *src, void dst += dst_offs; for (unsigned y = 0; y < h; y++) { - memcpy(dst + y * SCREEN_PITCH, src + y * pitch, pitch); + memcpy(dst + y * SCREEN_PITCH, src + y * pitch, w * SCREEN_BPP); } } @@ -156,6 +172,8 @@ static void scale_blend(unsigned w, unsigned h, size_t pitch, const void *src, v int dx = 0; uint16_t *pnext = (uint16_t *)(src + pitch); + if (!lines) + pnext -= (pitch / sizeof(uint16_t)); if (dy > rat_dst_h - bh[0]) { pblend = pnext; -- cgit v1.2.3