diff tools/lib64fmts.c @ 1707:a0986cfd6f9d

More consistently use DMGrowBuf in the lib64gfx APIs, and implement "backwards" RLE decoding and encoding (optionally regards input/output). Not tested very much yet, there may be bugs.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 05 Jun 2018 21:58:10 +0300
parents 1036b0dcccb5
children 4fd94bf558b3
line wrap: on
line diff
--- a/tools/lib64fmts.c	Tue Jun 05 19:57:08 2018 +0300
+++ b/tools/lib64fmts.c	Tue Jun 05 21:58:10 2018 +0300
@@ -31,7 +31,6 @@
 };
 
 
-
 static int fmtProbeKoalaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
 {
     // Attempt to prevent misprobes of unpacked Koala and Run Paint
@@ -45,7 +44,7 @@
 }
 
 
-static int fmtDecodeKoalaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeKoalaPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
     DMGrowBuf mem;
@@ -54,10 +53,11 @@
     cfg.type        = DM_COMP_RLE_MARKER;
     cfg.flags       = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_2;
     cfg.rleMarkerB  = 0xfe;
-    if ((res = dmDecodeGenericRLEAlloc(&mem, buf, buf + len, &cfg)) != DMERR_OK)
+
+    if ((res = dmDecodeGenericRLEAlloc(&mem, buf, &cfg)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
+    res = dmC64DecodeGenericBMP(img, &mem, fmt);
 
 out:
     dmGrowBufFree(&mem);
@@ -81,7 +81,7 @@
     cfg.rleMarkerB   = 0xfe;
     cfg.rleMinCountB = 3;
     cfg.rleMaxCountB = 255;
-    res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg);
+    res = dmEncodeGenericRLE(buf, &tmp, &cfg);
 
 out:
     dmGrowBufFree(&tmp);
@@ -105,20 +105,21 @@
 }
 
 
-static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeDrazPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf mem;
+    DMGrowBuf mem, tmp;
     DMCompParams cfg;
 
     cfg.type        = DM_COMP_RLE_MARKER;
     cfg.flags       = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1;
-    cfg.rleMarkerB  = buf[0x0d];
+    cfg.rleMarkerB  = buf->data[0x0d];
 
-    if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 0x0e, buf + len, &cfg)) != DMERR_OK)
+    if ((res = dmDecodeGenericRLEAlloc(&mem,
+        dmGrowBufCreateFromOffs(&tmp, buf, 0x0e), &cfg)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
+    res = dmC64DecodeGenericBMP(img, &mem, fmt);
 
 out:
     dmGrowBufFree(&mem);
@@ -143,7 +144,7 @@
     cfg.rleMinCountB = 3;
     cfg.rleMaxCountB = 255;
 
-    dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
+    dmGenericRLEAnalyze(&tmp, &cfg);
 
     // Add the header bits
     if (!dmGrowBufPut(buf, (Uint8 *) magicID, strlen(magicID)) ||
@@ -154,7 +155,7 @@
     }
 
     // And now RLE compress the data to the existing buffer
-    res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg);
+    res = dmEncodeGenericRLE(buf, &tmp, &cfg);
 
 out:
     dmGrowBufFree(&tmp);
@@ -174,11 +175,10 @@
 
 
 static BOOL fmtDrazLaceGetLaceType(DMC64Image *img, const DMC64EncDecOp *op,
-    const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+    const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
-    (void) len;
     (void) fmt;
-    img->laceType = buf[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR;
+    img->laceType = buf->data[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR;
     return TRUE;
 }
 
@@ -205,21 +205,22 @@
 }
 
 
-static int fmtDecodeBDP5Packed(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeBDP5Packed(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf mem;
+    DMGrowBuf mem, tmp;
     DMCompParams cfg;
 
     cfg.type        = DM_COMP_RLE_MARKER;
     cfg.flags       = DM_RLE_BYTE_RUNS | DM_RLE_WORD_RUNS | DM_RLE_ORDER_1;
-    cfg.rleMarkerB  = buf[8];
-    cfg.rleMarkerW  = buf[9];
+    cfg.rleMarkerB  = buf->data[8];
+    cfg.rleMarkerW  = buf->data[9];
 
-    if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 10, buf + len, &cfg)) != DMERR_OK)
+    if ((res = dmDecodeGenericRLEAlloc(&mem,
+        dmGrowBufCreateFromOffs(&tmp, buf, 10), &cfg)) != DMERR_OK)
         goto out;
 
-    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
+    res = dmC64DecodeGenericBMP(img, &mem, fmt);
 
 out:
     dmGrowBufFree(&mem);
@@ -230,11 +231,11 @@
 static int fmtEncodeBDP5Packed(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf tmp;
+    DMGrowBuf mem;
     DMCompParams cfg;
 
     // Encode the data to temp buffer
-    if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK)
+    if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK)
         goto out;
 
     // Analyze and setup RLE
@@ -245,7 +246,7 @@
     cfg.rleMinCountW = 256;
     cfg.rleMaxCountW = 1024;
 
-    dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
+    dmGenericRLEAnalyze(&mem, &cfg);
 
     // Add the header bits
     if (!dmGrowBufPut(buf, (Uint8 *) fmtBDP5MagicID, strlen(fmtBDP5MagicID)) ||
@@ -257,10 +258,10 @@
     }
 
     // And now RLE compress the data to the existing buffer
-    res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg);
+    res = dmEncodeGenericRLE(buf, &mem, &cfg);
 
 out:
-    dmGrowBufFree(&tmp);
+    dmGrowBufFree(&mem);
     return res;
 }
 
@@ -302,7 +303,7 @@
 }
 
 
-static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
     DMGrowBuf mem, tmp;
@@ -310,22 +311,22 @@
 
     // 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)
+    if ((res = dmGrowBufAlloc(&tmp, buf->len + 4, 4)) != DMERR_OK)
         return res;
 
-    memcpy(tmp.data, buf, len);
-    tmp.len = len + 1;
+    memcpy(tmp.data, buf->data, buf->len);
+    tmp.len = buf->len + 1;
 
     // Now do an RLE decode on the enlarged buffer
     cfg.type        = DM_COMP_RLE_MARKER;
     cfg.flags       = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1;
     cfg.rleMarkerB  = 0xC2;
 
-    if ((res = dmDecodeGenericRLEAlloc(&mem, tmp.data, tmp.data + tmp.len, &cfg)) != DMERR_OK)
+    if ((res = dmDecodeGenericRLEAlloc(&mem, &tmp, &cfg)) != DMERR_OK)
         goto out;
 
     // And finally decode to bitmap struct
-    res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
+    res = dmC64DecodeGenericBMP(img, &mem, fmt);
 
 out:
     dmGrowBufFree(&tmp);
@@ -337,11 +338,11 @@
 static int fmtEncodeAmicaPaintPacked(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf tmp;
+    DMGrowBuf mem;
     DMCompParams cfg;
 
     // Encode the data to temp buffer
-    if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK)
+    if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK)
         goto out;
 
     // And now RLE compress the data to the existing buffer
@@ -351,10 +352,10 @@
     cfg.rleMinCountB = 3;
     cfg.rleMaxCountB = 255;
 
-    res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg);
+    res = dmEncodeGenericRLE(buf, &mem, &cfg);
 
 out:
-    dmGrowBufFree(&tmp);
+    dmGrowBufFree(&mem);
     return res;
 }
 
@@ -370,11 +371,10 @@
 
 
 static BOOL fmtTruePaintGetLaceType(DMC64Image *img, const DMC64EncDecOp *op,
-    const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+    const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     (void) op;
     (void) buf;
-    (void) len;
     (void) fmt;
     img->laceType = D64_ILACE_RES;
     return TRUE;
@@ -427,10 +427,11 @@
 }
 
 
-static int fmtDecodeTruePaintPacked(DMC64Image *img, const Uint8 *src, const size_t srcLen, const DMC64ImageFormat *fmt)
+static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *src, const DMC64ImageFormat *fmt)
 {
     int res = DMERR_OK;
     Uint8 *dst = NULL;
+    DMGrowBuf dstTmp;
     const Uint8 *codeBook1, *codeBook2;
     size_t
         srcOffs, dstOffs,
@@ -439,8 +440,8 @@
         // 1c00-67e8 is the actual area used tho
 
     // Codebooks: #1 is trampoline table markers, #2 is RLE data table
-    codeBook1 = src + 0x81 - 2;
-    codeBook2 = src + 0x85 - 2;
+    codeBook1 = src->data + 0x81 - 2;
+    codeBook2 = src->data + 0x85 - 2;
 
     // Allocate output buffer
     if ((dst = dmMalloc0(dstLen)) == NULL)
@@ -451,7 +452,7 @@
     }
 
     // Begin decompression
-    srcOffs = srcLen;
+    srcOffs = src->len;
     dstOffs = dstLen;
 
     while (srcOffs > 0 && dstOffs > 0)
@@ -460,7 +461,7 @@
         int count = 1, scount;
         BOOL found = FALSE;
 
-        if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, -1))
+        if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, -1))
             goto out;
 
         for (int n = 0; n < 8; n++)
@@ -470,7 +471,7 @@
             switch (n)
             {
                 case 4: // Y = 4, JTO = $0B
-                    if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n))
+                    if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n))
                         goto out;
 
                     count = data;
@@ -484,12 +485,12 @@
                     // fallthrough
 
                 case 0: // Y = 0, JTO = $19
-                    if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n))
+                    if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n))
                         goto out;
                     break;
 
                 case 2: // Y = 2, JTO = $07
-                    if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n))
+                    if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n))
                         goto out;
 
                     count = data;
@@ -520,7 +521,7 @@
     }
 
 finish:
-    res = dmC64DecodeGenericBMP(img, dst, dstLen, fmt);
+    res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&dstTmp, dst, dstLen), fmt);
 
 out:
     dmFree(dst);
@@ -545,20 +546,21 @@
 }
 
 
-static int fmtDecodeFormatXX2(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeFormatXX2(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
+    DMGrowBuf tmp;
 
     // If there is only data for less than XX2_MIN_SIZE bytes,
     // allocate a buffer of that size and copy data there.
     // Otherwise allocate len bytes.
-    size_t nlen = len < XX2_MIN_SIZE ? XX2_MIN_SIZE : len;
+    size_t nlen = buf->len < XX2_MIN_SIZE ? XX2_MIN_SIZE : buf->len;
     Uint8 *mem = dmMalloc0(nlen);
     if (mem == NULL)
         return DMERR_MALLOC;
 
-    memcpy(mem, buf, len);
-    res = dmC64DecodeGenericBMP(img, mem, nlen, fmt);
+    memcpy(mem, buf->data, buf->len);
+    res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&tmp, mem, nlen), fmt);
 
     dmFree(mem);
     return res;
@@ -580,29 +582,30 @@
 }
 
 
-static int fmtDecodeFunPaint2(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
+static int fmtDecodeFunPaint2(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int res;
+    DMGrowBuf tmp;
 
     // Check if the data is compressed
-    if (buf[14])
+    if (buf->data[14])
     {
         DMGrowBuf mem;
         DMCompParams cfg;
 
         cfg.type        = DM_COMP_RLE_MARKER;
         cfg.flags       = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1;
-        cfg.rleMarkerB  = buf[15];
+        cfg.rleMarkerB  = buf->data[15];
 
         if ((res = dmDecodeGenericRLEAlloc(
-            &mem, buf + FUNPAINT2_HEADER_SIZE, buf + len, &cfg)) == DMERR_OK)
-            res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
+            &mem, dmGrowBufCreateFromOffs(&tmp, buf, FUNPAINT2_HEADER_SIZE), &cfg)) == DMERR_OK)
+            res = dmC64DecodeGenericBMP(img, &mem, fmt);
 
         dmGrowBufFree(&mem);
     }
     else
     {
-        res = dmC64DecodeGenericBMP(img, buf + FUNPAINT2_HEADER_SIZE, len - FUNPAINT2_HEADER_SIZE, fmt);
+        res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFromOffs(&tmp, buf, FUNPAINT2_HEADER_SIZE), fmt);
     }
 
     return res;
@@ -623,11 +626,11 @@
 static int fmtEncodeFunPaint2Packed(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
 {
     int res;
-    DMGrowBuf tmp;
+    DMGrowBuf mem;
     DMCompParams cfg;
 
     // Encode the data to temp buffer
-    if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK)
+    if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK)
         goto out;
 
     // Analyze and setup RLE
@@ -636,7 +639,7 @@
     cfg.rleMinCountB = 3;
     cfg.rleMaxCountB = 255;
 
-    dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
+    dmGenericRLEAnalyze(&mem, &cfg);
 
     // Add the header bits
     if (!dmGrowBufPut(buf, (Uint8 *) fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) ||
@@ -647,10 +650,10 @@
     }
 
     // And now RLE compress the data to the existing buffer
-    res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg);
+    res = dmEncodeGenericRLE(buf, &mem, &cfg);
 
 out:
-    dmGrowBufFree(&tmp);
+    dmGrowBufFree(&mem);
     return res;
 }
 
@@ -1173,6 +1176,7 @@
             { DO_COPY     , DS_SCREEN_RAM  , 0x2000, 0,  0, NULL, NULL },
             { DO_COPY     , DS_COLOR_RAM   , 0x2400, 0,  0, NULL, NULL },
             { DO_SET_OP   , DS_BGCOL       , 0x00  , 0,  0, NULL, NULL },
+            { DO_SET_OP   , DS_EXTRA_DATA  , 10240 , 0,  0, NULL, NULL },
             { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL