changeset 1463:bde6a66bc2f6

Change dmDecodeGenericRLE() to use DMGrowBuf as output. Also add support for two different common types of RLE encoding. Add stub function of dmEncodeGenericRLE(), not implemented yet. Change functions using dmDecodeGenericRLE to use the new API. Also fix a problem in Amica Paint RLE decoding as the format seems to save one byte less than is necessary.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 10 May 2018 21:27:24 +0300
parents 9cb6dd1046bf
children 73e00bf7531c
files tools/lib64gfx.c
diffstat 1 files changed, 91 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64gfx.c	Thu May 10 21:22:31 2018 +0300
+++ b/tools/lib64gfx.c	Thu May 10 21:27:24 2018 +0300
@@ -33,6 +33,9 @@
     { 0x95, 0x95, 0x95, 0xff },
 };
 
+#define DM_RLE_MARKER    1
+#define DM_RLE_MASK      2
+
 
 #define DM_GET_ADDR_LO(addr) ((addr) & 0xff)
 #define DM_GET_ADDR_HI(addr) (((addr) >> 8) & 0xff)
@@ -222,32 +225,79 @@
 }
 
 
-static int dmDecodeGenericRLE(Uint8 **mem, Uint8 **pdstEnd, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker)
+static int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker, const Uint8 rleMask, const int rleType)
 {
-    Uint8 *dst, *dstEnd;
+    int res;
 
-    if ((*mem = dmMalloc(C64_RAM_SIZE)) == NULL)
-        return DMERR_MALLOC;
+    if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
+        goto err;
 
-    dst       = *mem;
-    dstEnd    = *mem + C64_RAM_SIZE;
-
-    while (src <= srcEnd && dst <= dstEnd)
+    // Perform RLE decode
+    while (src < srcEnd)
     {
         Uint8 c = *src++;
-        if (c == rleMarker && src + 2 <= srcEnd)
+        int cnt = 1;
+
+        switch (rleType)
         {
-            int cnt = *src++;
-            c = *src++;
-            while (cnt-- && dst <= dstEnd)
-                *dst++ = c;
+            case DM_RLE_MARKER:
+                if (c == rleMarker)
+                {
+                    if (srcEnd - src < 2)
+                    {
+                        res = dmError(DMERR_INVALID_DATA,
+                            "Foobar: %d\n", srcEnd - src);
+                        goto err;
+                    }
+                    cnt = *src++;
+                    c = *src++;
+                }
+                break;
+
+            case DM_RLE_MASK:
+                if ((c & rleMask) == rleMarker)
+                {
+                    if (srcEnd - src < 1)
+                    {
+                        res = dmError(DMERR_INVALID_DATA,
+                            "foobar2\n");
+                        goto err;
+                    }
+                    // XXX TODO actually we probably want another mask here
+                    cnt = c & (0xff ^ rleMask);
+                    c = *src++;
+                }
+                break;
         }
-        else
-            *dst++ = c;
+
+        while (cnt--)
+        {
+            if (!dmGrowBufPutU8(dst, c))
+            {
+                res = dmError(DMERR_MALLOC,
+                    "bazzooo\n");
+                goto err;
+            }
+        }
     }
 
-    *pdstEnd = dst;
+    // Reallocate the memory
+    if ((res = dmGrowBufResize(dst)) != DMERR_OK)
+        goto err;
+
+    res = DMERR_OK;
 
+err:
+    return res;
+}
+
+
+static int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker)
+{
+    (void) dst;
+    (void) src;
+    (void) srcEnd;
+    (void) rleMarker;
     return DMERR_OK;
 }
 
@@ -316,15 +366,15 @@
 static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
 {
     int res;
-    Uint8 *mem = NULL, *end;
+    DMGrowBuf mem;
 
-    if ((res = dmDecodeGenericRLE(&mem, &end, buf + 0x0e, buf + len - 1, *(buf + 0x0d))) != DMERR_OK)
+    if ((res = dmDecodeGenericRLE(&mem, buf + 0x0e, buf + len, *(buf + 0x0d), 0, DM_RLE_MARKER)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt);
+    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
 
 out:
-    dmFree(mem);
+    dmGrowBufFree(&mem);
     return res;
 }
 
@@ -388,15 +438,27 @@
 static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
 {
     int res;
-    Uint8 *mem = NULL, *end;
+    DMGrowBuf mem, tmp;
+
+    // Amica Paint apparently is broken and stores one byte less than it should
+    // so we need to do some crappy buffer expansion here ..
+    if ((res = dmGrowBufAlloc(&tmp, len + 4, 4)) != DMERR_OK)
+        return res;
 
-    if ((res = dmDecodeGenericRLE(&mem, &end, buf, buf + len - 1, 0xC2)) != DMERR_OK)
+    tmp.len = len;
+    memcpy(tmp.data, buf, len);
+    tmp.data[tmp.len++] = 0;
+
+    // Now do an RLE decode on the enlarged buffer
+    if ((res = dmDecodeGenericRLE(&mem, tmp.data, tmp.data + tmp.len, 0xC2, 0, DM_RLE_MARKER)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt);
+    // And finally decode to bitmap struct
+    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
 
 out:
-    dmFree(mem);
+    dmGrowBufFree(&tmp);
+    dmGrowBufFree(&mem);
     return res;
 }
 
@@ -502,15 +564,16 @@
 static int fmtDecodeFunPaint2Packed(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
 {
     int res;
-    Uint8 *mem = NULL, *end;
+    DMGrowBuf mem;
+    dmGrowBufInit(&mem);
 
-    if ((res = dmDecodeGenericRLE(&mem, &end, buf + FUNPAINT2_HEADER_SIZE, buf + len - 1, *(buf + 15))) != DMERR_OK)
+    if ((res = dmDecodeGenericRLE(&mem, buf + FUNPAINT2_HEADER_SIZE, buf + len, *(buf + 15), 0, DM_RLE_MARKER)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt);
+    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
 
 out:
-    dmFree(mem);
+    dmGrowBufFree(&mem);
     return res;
 }