changeset 1823:02f604264bc4

Improve C64 image format up/down conversion. Might actually work for some formats now.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 22 Jun 2018 12:21:54 +0300
parents 9bec535956fd
children adf9f05c26e1
files tools/gfxconv.c
diffstat 1 files changed, 93 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/tools/gfxconv.c	Fri Jun 22 12:20:46 2018 +0300
+++ b/tools/gfxconv.c	Fri Jun 22 12:21:54 2018 +0300
@@ -981,58 +981,109 @@
     if (pdst == NULL || dstFmt == NULL || src == NULL || srcFmt == NULL)
         return DMERR_NULLPTR;
 
+    // Allocate the destination image
     if ((dst = *pdst = dmC64ImageAlloc(dstFmt)) == NULL)
         return DMERR_MALLOC;
 
-    if (src->type == dst->type)
+    // Copy rest of the structure ..
+    dst->d020    = src->d020;
+    dst->bgcolor = src->bgcolor;
+    dst->d022    = src->d022;
+    dst->d023    = src->d023;
+    dst->d024    = src->d024;
+
+    // Do per opcode copies
+    for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
     {
+        const DMC64EncDecOp *op = fmtGetEncDecOp(dstFmt, i);
+        DMC64MemBlock *srcBlk = NULL, *dstBlk = NULL;
+        char *blkname = NULL;
+        size_t size;
+
+        if (op->type == DO_LAST)
+            break;
+
+        dmC64GetOpSize(op, dstFmt, &size);
+        switch (op->type)
+        {
+            case DO_COPY:
+            case DO_SET_MEM:
+            case DO_SET_MEM_HI:
+            case DO_SET_MEM_LO:
+            case DO_SET_OP:
+                dmC64GetOpMemBlockAndName(src, op->subject, op->bank, (const DMC64MemBlock **) &srcBlk, &blkname);
+                dmC64GetOpMemBlockAndName(dst, op->subject, op->bank, (const DMC64MemBlock **) &dstBlk, &blkname);
+                if (srcBlk != NULL && srcBlk->data != NULL && srcBlk->size >= size)
+                {
+                    // The block exists in source and is of sufficient size, so copy it
+                    dmMsg(2, "Copying block '%s' op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x)\n",
+                        blkname, i, op->offs, op->offs, op->bank, size, size);
+                    dmC64MemBlockCopy(dstBlk, srcBlk);
+                }
+                else
+                switch (op->subject)
+                {
+                    case DS_COLOR_RAM:
+                    case DS_SCREEN_RAM:
+                    case DS_BITMAP_RAM:
+                    case DS_CHAR_DATA:
+                    case DS_EXTRA_DATA:
+                        if ((dmC64MemBlockAlloc(dstBlk, size)) != DMERR_OK)
+                        {
+                            return dmError(DMERR_MALLOC,
+                                "Could not allocate '%s' block! "
+                                "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x)\n",
+                                blkname, i, op->offs, op->offs, op->bank, size, size);
+                        }
+                        if (srcBlk->data == NULL)
+                        {
+                            dmMsg(2, "Creating block '%s' op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x)\n",
+                                blkname, i, op->offs, op->offs, op->bank, size, size);
+                        }
+                        switch (op->type)
+                        {
+                            case DO_COPY:
+                                // If some data exists, copy it. Rest is zero.
+                                // Otherwise just set to zero.
+                                if (srcBlk->data != NULL)
+                                    memcpy(dstBlk->data, srcBlk->data, srcBlk->size);
+                                break;
+
+                            case DO_SET_MEM:
+                                // Leave allocate data to zero.
+                                break;
+
+                            case DO_SET_OP:
+                                dmMemset(dstBlk->data, op->offs, size);
+                                break;
+
+                            default:
+                                return dmError(DMERR_INTERNAL,
+                                    "Unhandled op type %d in "
+                                    "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                    op->type, i, op->offs, op->offs, op->bank, size, size);
+                        }
+                        break;
+                }
+                break;
+        }
+    }
+
+    // Try to do some simple fixups
+    if ((dst->type & D64_FMT_FLI) && (src->type & D64_FMT_FLI) == 0)
+    {
+        dmMsg(1, "Upconverting multicolor to FLI.\n");
         for (int i = 0; i < dst->nbanks; i++)
         {
-            dmC64MemBlockCopy(&dst->color[i], &src->color[i]);
-            dmC64MemBlockCopy(&dst->screen[i], &src->screen[i]);
-            dmC64MemBlockCopy(&dst->bitmap[i], &src->bitmap[i]);
+            dmC64MemBlockCopy(&dst->color[i], &src->color[0]);
+            dmC64MemBlockCopy(&dst->screen[i], &src->screen[0]);
+            dmC64MemBlockCopy(&dst->bitmap[i], &src->bitmap[0]);
         }
     }
     else
+    if ((src->type & D64_FMT_FLI) && (dst->type & D64_FMT_FLI) == 0)
     {
-        // Try to do some simple fixups
-        if ((dst->type & D64_FMT_FLI) && (src->type & D64_FMT_FLI) == 0)
-        {
-            dmMsg(1, "Upconverting multicolor to FLI.\n");
-            for (int i = 0; i < dst->nbanks; i++)
-            {
-                dmC64MemBlockCopy(&dst->color[i], &src->color[0]);
-                dmC64MemBlockCopy(&dst->screen[i], &src->screen[0]);
-                dmC64MemBlockCopy(&dst->bitmap[i], &src->bitmap[0]);
-            }
-        }
-
-        for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
-        {
-            const DMC64EncDecOp *op = fmtGetEncDecOp(dstFmt, i);
-            size_t size;
-
-            // Check for last operator
-            if (op->type == DO_LAST)
-                break;
-
-            // Check size
-            if (!dmC64GetOpSize(op, dstFmt, &size))
-                return DMERR_INVALID_DATA;
-
-            // Perform operation
-            switch (op->type)
-            {
-                case DO_COPY:
-                    switch (op->subject)
-                    {
-                        case DS_EXTRA_DATA:
-                            dmC64MemBlockAlloc(&dst->extraData[op->bank], size);
-                            break;
-                    }
-                    break;
-            }
-        }
+        dmMsg(1, "Downconverting FLI to multicolor.\n");
     }
 
     return DMERR_OK;