diff options
author | neonloop | 2021-08-13 15:38:49 +0000 |
---|---|---|
committer | neonloop | 2021-08-13 15:38:49 +0000 |
commit | 0abc2d2ddd9f22f4b4fa5c348873705041ddec93 (patch) | |
tree | f6d23c751d67ea980b03ce466db1b3d13175e8a4 /scale.c | |
parent | 95c2f03dca179259a11025b3e773ef705ae4f894 (diff) | |
download | picoarch-0abc2d2ddd9f22f4b4fa5c348873705041ddec93.tar.gz picoarch-0abc2d2ddd9f22f4b4fa5c348873705041ddec93.tar.bz2 picoarch-0abc2d2ddd9f22f4b4fa5c348873705041ddec93.zip |
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)
Diffstat (limited to 'scale.c')
-rw-r--r-- | scale.c | 48 |
1 files changed, 33 insertions, 15 deletions
@@ -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; |