changeset 2150:b4fbb90937f7

Fix Cosmos Designs Hires Manager unpacker. What a mess. Ugh.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 04 Jun 2019 15:00:58 +0300
parents 810fc98d9003
children 0a7ebb7198e3
files tools/lib64fmts.c
diffstat 1 files changed, 41 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64fmts.c	Sun Jun 02 23:37:35 2019 +0300
+++ b/tools/lib64fmts.c	Tue Jun 04 15:00:58 2019 +0300
@@ -981,84 +981,79 @@
 static int fmtDecodeCosmosDesignsHiresManagerPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf src, tmp;
-    DMCompParams cfg;
-    Uint8 data, count, *dstBuf;
-    const size_t dstSize = 0x7ff2 - 0x4000;
-    size_t dstOffs;
-    BOOL getByte = TRUE;
-
-    // Setup the RLE config, only for input
-    cfg.func         = fmt->name;
-    cfg.type         = DM_COMP_RLE_MARKER;
-    cfg.flags        = DM_RLE_BACKWARDS_INPUT;
+    DMGrowBuf tmp;
+    Uint8 data, *dstBuf;
+    const size_t baseAddr = 0x4000;
+    const size_t dstSize = 0x8000 - baseAddr;
+    size_t dstOffs, srcOffs;
 
     // Allocate output buffer
     if ((dstBuf = dmMalloc0(dstSize)) == NULL)
     {
         return dmError(DMERR_MALLOC,
-            "%s: Could not allocate memory for RLE decoding buffer.\n",
-            cfg.func);
+            "Could not allocate memory for RLE decoding buffer.\n");
     }
 
     // Setup input buffer
-    dmGrowBufConstCopy(&src, psrc);
-    dmSetupRLEBuffers(NULL, &src, &cfg);
-    dstOffs = dstSize;
+    dstOffs = 0x7ff2 - baseAddr - 1;
+    srcOffs = psrc->len - 1;
 
-    while (dstOffs > 0 && src.offs > 0)
+    while (dstOffs > 0 && srcOffs > 0)
     {
-        if (getByte && !dmGrowBufGetU8(&src, &data))
-        {
-            res = dmError(DMERR_INVALID_DATA,
-                "%s: RLE: Invalid data/out of data for literal sequence.\n",
-                cfg.func);
-            goto out;
-        }
+        data = psrc->data[srcOffs];
 
-        // A simple marker byte RLE variant: [Marker] [count] [data]
+
+        // Current data byte tells us the mode
         if (data == 0)
         {
-            if (!dmGrowBufGetU8(&src, &count) ||
-                !dmGrowBufGetU8(&src, &data))
+            // RLE run
+            if (srcOffs < 3)
             {
                 res = dmError(DMERR_INVALID_DATA,
-                    "%s: RLE: Invalid data/out of data for run sequence.\n",
-                    cfg.func);
+                    "RLE: Invalid data/out of data for run sequence.\n");
                 goto out;
             }
 
-            int ncount = (int) count;
-            for (int n = 1; n < ncount && dstOffs > 0; n++)
-                dstBuf[--dstOffs] = data;
+            size_t ncount = psrc->data[--srcOffs];
+            data = psrc->data[--srcOffs];
+
+            srcOffs--;
 
-            getByte = TRUE;
+            if (dstOffs < ncount)
+                goto finish;
+
+            dstOffs -= ncount;
+            ncount++;
+            for (size_t n = 0; n < ncount; n++)
+                dstBuf[dstOffs + n] = data;
         }
         else
-        // Literal run of data bytes
         {
-            int ncount = (int) data;
-            for (int n = 0; n < ncount; n++)
+            // Literal run of data bytes
+            size_t ncount = data;
+            if (srcOffs < ncount)
+                ncount = srcOffs;
+
+            if (dstOffs < ncount)
+                ncount = dstOffs;
+
+            srcOffs -= ncount;
+            dstOffs -= ncount - 1;
+
+            for (size_t n = 0; n < ncount; n++)
             {
-                if (!dmGrowBufGetU8(&src, &data))
-                    goto finish;
-
-                if (dstOffs > 0)
-                    dstBuf[--dstOffs] = data;
-                else
-                    goto finish;
+                data = psrc->data[srcOffs + n];
+                dstBuf[dstOffs + n] = data;
             }
-            getByte = FALSE;
         }
     }
 
 finish:
 
-    dmGrowBufConstCreateFrom(&tmp, dstBuf, 0x3fff);
+    dmGrowBufConstCreateFrom(&tmp, dstBuf, dstSize);
     res = dmC64DecodeGenericBMP(img, &tmp, fmt);
 
 out:
-    dmGrowBufFree(&src);
     dmFree(dstBuf);
     return res;
 }