changeset 2525:19b0ca169361

Implement SupeRes encoding.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 15 May 2020 07:44:12 +0300
parents 5a7e2aa8fef5
children 4deb8da6c901
files tools/lib64fmts.c
diffstat 1 files changed, 128 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64fmts.c	Fri May 15 04:04:57 2020 +0300
+++ b/tools/lib64fmts.c	Fri May 15 07:44:12 2020 +0300
@@ -261,6 +261,126 @@
 }
 
 
+typedef struct
+{
+    DMGrowBuf *buf;
+
+    int cnt1, cnt2, dbyte;
+} DMSupeResEncCtx;
+
+
+static BOOL fmtEncodeSupeResRun(DMSupeResEncCtx *ctx)
+{
+    if (ctx->cnt2 == 255)
+        ctx->cnt2 = 0x24;
+    else
+    if (ctx->cnt2 > 216)
+    {
+        if (!dmGrowBufPutU8(ctx->buf, 0x25))
+            return FALSE;
+    }
+    else
+        ctx->cnt2 += 0x26;
+
+    if (!dmGrowBufPutU8(ctx->buf, ctx->cnt2))
+        return FALSE;
+
+    ctx->cnt1 = ctx->cnt2 = 0;
+
+    return TRUE;
+}
+
+
+static BOOL fmtEncodeSupeResFlush(DMSupeResEncCtx *ctx)
+{
+    ctx->cnt1 += 0x26;
+
+    if (!dmGrowBufPutU8(ctx->buf, 0x20) ||
+        !dmGrowBufPutU8(ctx->buf, ctx->cnt1))
+        return FALSE;
+
+    return fmtEncodeSupeResRun(ctx);
+}
+
+
+static BOOL fmtEncodeSupeResSection(DMSupeResEncCtx *ctx, const DMC64MemBlock *blk)
+{
+    for (size_t offs = 0; offs < blk->size; offs++)
+    {
+        ctx->dbyte = blk->data[offs];
+
+        if ((ctx->cnt1 == 0 && offs + 1 < blk->size && ctx->dbyte == blk->data[offs + 1]) ||
+            (ctx->cnt1 != 0 && ctx->dbyte == ctx->cnt2))
+        {
+            ctx->cnt1++;
+            ctx->cnt2 = ctx->dbyte;
+
+            if (ctx->cnt1 >= 215 &&
+                !fmtEncodeSupeResFlush(ctx))
+                return FALSE;
+
+            continue;
+        }
+        else
+        if (ctx->cnt1 != 0 && ctx->dbyte != ctx->cnt2)
+        {
+            if (!fmtEncodeSupeResFlush(ctx))
+                return FALSE;
+        }
+
+        ctx->cnt2 = ctx->dbyte;
+
+        if (!fmtEncodeSupeResRun(ctx))
+            return FALSE;
+    }
+
+    if (ctx->cnt1 > 0)
+        return fmtEncodeSupeResFlush(ctx);
+
+    return TRUE;
+}
+
+
+static int fmtEncodeSupeRes(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
+{
+    DMSupeResEncCtx ctx;
+    BOOL bres;
+
+    // Output magic header and data type
+    if (!dmGrowBufPut(buf, fmtSupeRes_MagicID_1, sizeof(fmtSupeRes_MagicID_1)) ||
+        !dmGrowBufPutU8(buf, fmt->extra))
+    {
+        return dmError(DMERR_MALLOC,
+            "Error outputting SupeRes magic header.\n");
+    }
+
+    memset(&ctx, 0, sizeof(ctx));
+    ctx.buf = buf;
+
+    switch (fmt->extra)
+    {
+        case 0x23:
+        case 0x25:
+            bres =
+                fmtEncodeSupeResSection(&ctx, &img->screen[0]) &&
+                fmtEncodeSupeResSection(&ctx, &img->bitmap[0]);
+            break;
+
+        case 0x24:
+        case 0x26:
+            ctx.cnt2 = img->bgcolor;
+            bres =
+                fmtEncodeSupeResRun(&ctx) &&
+                fmtEncodeSupeResSection(&ctx, &img->screen[0]) &&
+                fmtEncodeSupeResSection(&ctx, &img->color[0]) &&
+                fmtEncodeSupeResSection(&ctx, &img->bitmap[0]);
+            break;
+    }
+
+    return bres ? DMERR_OK : DMERR_MALLOC;
+}
+
+
 static const Uint8 fmtMarqPETSCII_ID1[] =
 {
     0x01, 0x08, 0x0b, 0x08, 0xef, 0x00, 0x9e, 0x32, 0x30, 0x36,
@@ -3072,30 +3192,30 @@
     },
 
     {
-        "suphi1", "SupeRes hires [clear] (packed)", -1, 0, 0x23, DM_FMT_RD,
+        "suphi1", "SupeRes hires [clear] (packed)", -1, 0, 0x23, DM_FMT_RDWR,
         fmtProbeSupeRes,
-        fmtDecodeSupeRes, NULL,
+        fmtDecodeSupeRes,fmtEncodeSupeRes,
         { }, &dmC64CommonFormats[10]
     },
 
     {
-        "suphi2", "SupeRes hires [no-clear] (packed)", -1, 0, 0x25, DM_FMT_RD,
+        "suphi2", "SupeRes hires [no-clear] (packed)", -1, 0, 0x25, DM_FMT_RDWR,
         fmtProbeSupeRes,
-        fmtDecodeSupeRes, NULL,
+        fmtDecodeSupeRes,fmtEncodeSupeRes,
         { }, &dmC64CommonFormats[10]
     },
 
     {
-        "supmc1", "SupeRes multicolor [clear] (packed)", -1, 0, 0x24, DM_FMT_RD,
+        "supmc1", "SupeRes multicolor [clear] (packed)", -1, 0, 0x24, DM_FMT_RDWR,
         fmtProbeSupeRes,
-        fmtDecodeSupeRes, NULL,
+        fmtDecodeSupeRes,fmtEncodeSupeRes,
         { }, &dmC64CommonFormats[0]
     },
 
     {
-        "supmc2", "SupeRes multicolor [no-clear] (packed)", -1, 0, 0x26, DM_FMT_RD,
+        "supmc2", "SupeRes multicolor [no-clear] (packed)", -1, 0, 0x26, DM_FMT_RDWR,
         fmtProbeSupeRes,
-        fmtDecodeSupeRes, NULL,
+        fmtDecodeSupeRes,fmtEncodeSupeRes,
         { }, &dmC64CommonFormats[0]
     },
 };