aboutsummaryrefslogtreecommitdiff
path: root/scale.c
diff options
context:
space:
mode:
authorneonloop2021-08-13 15:38:49 +0000
committerneonloop2021-08-13 15:38:49 +0000
commit0abc2d2ddd9f22f4b4fa5c348873705041ddec93 (patch)
treef6d23c751d67ea980b03ce466db1b3d13175e8a4 /scale.c
parent95c2f03dca179259a11025b3e773ef705ae4f894 (diff)
downloadpicoarch-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.c48
1 files changed, 33 insertions, 15 deletions
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;