diff tools/lib64gfx.c @ 1668:1741717b1ae5

Big overhaul to the enc/dec operator system to be more flexible.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 31 May 2018 00:04:01 +0300
parents 7555c8803529
children 09adf5328510
line wrap: on
line diff
--- a/tools/lib64gfx.c	Wed May 30 21:10:57 2018 +0300
+++ b/tools/lib64gfx.c	Thu May 31 00:04:01 2018 +0300
@@ -89,7 +89,7 @@
     for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
     {
         const DMC64EncDecOp *op = fmtGetEncDecOp(fmt, i);
-        if (op->type == DT_LAST)
+        if (op->type == DO_LAST)
             break;
 
         if (op->bank > nbanks)
@@ -603,33 +603,46 @@
 {
     switch (op->type)
     {
-        case DT_COLOR_RAM:
-        case DT_BITMAP_RAM:
-        case DT_SCREEN_RAM:
-        case DT_CHAR_DATA:
-            if (op->bank < 0 || op->bank > img->nbanks)
+        case DO_COPY:
+        case DO_SET_MEM:
+        case DO_SET_OP:
+            switch (op->subject)
             {
-                return dmError(DMERR_INTERNAL,
-                    "Invalid bank %d / %d definition in generic encode/decode operator %d @ #%d.\n",
-                    op->bank, img->nbanks, op->type, i);
+                case DS_COLOR_RAM:
+                case DS_BITMAP_RAM:
+                case DS_SCREEN_RAM:
+                case DS_CHAR_DATA:
+                    if (op->bank < 0 || op->bank > img->nbanks)
+                    {
+                        return dmError(DMERR_INTERNAL,
+                            "Invalid bank %d / %d definition in generic encode/decode operator %d @ #%d.\n",
+                            op->bank, img->nbanks, op->type, i);
+                    }
+                    break;
+
+                case DS_EXTRA_DATA:
+                    if (op->bank < 0 || op->bank >= C64_MAX_EXTRA_DATA)
+                    {
+                        return dmError(DMERR_INTERNAL,
+                            "Invalid bank %d definition in generic encode/decode operator %d @ #%d.\n",
+                            op->bank, op->type, i);
+                    }
+                    break;
             }
             break;
 
-        case DT_EXTRA_DATA:
-            if (op->bank < 0 || op->bank >= C64_MAX_EXTRA_DATA)
-            {
-                return dmError(DMERR_INTERNAL,
-                    "Invalid bank %d definition in generic encode/decode operator %d @ #%d.\n",
-                    op->bank, op->type, i);
-            }
+        // Just list the allowed ops here
+        case DO_DEC_FUNC:
+        case DO_ENC_FUNC:
+        case DO_CHAR_CFG:
+        case DO_LAST:
             break;
-    }
 
-    if (op->type < 0 || op->type >= DT_LAST)
-    {
-        return dmError(DMERR_INTERNAL,
-            "Invalid encode/decode operator type %d @ #%d.\n",
-            op->type, i);
+        default:
+            return dmError(DMERR_INTERNAL,
+                "Invalid op type %d in generic encode/decode operator @ #%d.\n",
+                op->type, i);
+            break;
     }
 
     return DMERR_OK;
@@ -638,33 +651,38 @@
 
 BOOL dmC64GetOpSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt, size_t *size)
 {
+    // Default to size of 0
+    *size = 0;
+
     switch (op->type)
     {
-        case DT_SCREEN_RAM:
-        case DT_COLOR_RAM:
-            *size = fmt->chHeight * fmt->chWidth;
-            break;
+        case DO_COPY:
+        case DO_SET_MEM:
+        case DO_SET_OP:
+            switch (op->subject)
+            {
+                case DS_SCREEN_RAM:
+                case DS_COLOR_RAM:
+                    *size = fmt->chHeight * fmt->chWidth;
+                    break;
 
-        case DT_BITMAP_RAM:
-            *size = fmt->chHeight * fmt->chWidth * 8;
-            break;
-
-        case DT_CHAR_DATA:
-            *size = C64_MAX_CHARS * C64_CHR_SIZE;
-            break;
+                case DS_BITMAP_RAM:
+                    *size = fmt->chHeight * fmt->chWidth * 8;
+                    break;
 
-        case DT_COLOR_REG:
-            *size = 1;
-            break;
+                case DS_CHAR_DATA:
+                    *size = C64_MAX_CHARS * C64_CHR_SIZE;
+                    break;
 
-        case DT_DEC_FUNCTION:
-        case DT_ENC_FUNCTION:
-        case DT_EXTRA_DATA:
-            *size = op->size;
-            break;
-
-        default:
-            *size = 0;
+                case DS_D020:
+                case DS_BGCOL:
+                case DS_D021:
+                case DS_D022:
+                case DS_D023:
+                case DS_D024:
+                    *size = 1;
+                    break;
+            }
     }
 
     // If the operator specified size is larger, use it.
@@ -675,6 +693,20 @@
 }
 
 
+void dmC64GetOpMemBlockAndName(const DMC64Image *img, const int subject, const int bank, const DMC64MemBlock **blk, char **blkname)
+{
+    switch (subject)
+    {
+        case DS_COLOR_RAM  : *blk = &img->color[bank]; *blkname = "Color RAM"; break;
+        case DS_SCREEN_RAM : *blk = &img->screen[bank]; *blkname = "Screen RAM"; break;
+        case DS_BITMAP_RAM : *blk = &img->bitmap[bank]; *blkname = "Bitmap RAM"; break;
+        case DS_CHAR_DATA  : *blk = &img->charData[bank]; *blkname = "Character data"; break;
+        case DS_EXTRA_DATA : *blk = &img->extraData[bank]; *blkname = "Extra data"; break;
+        default: *blk = NULL; *blkname = NULL; break;
+    }
+}
+
+
 int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf,
     const size_t len, const DMC64ImageFormat *fmt)
 {
@@ -699,9 +731,10 @@
         DMC64MemBlock *blk = NULL;
         char *blkname = NULL;
         size_t size;
+        Uint8 value;
 
         // Check for last operator
-        if (op->type == DT_LAST)
+        if (op->type == DO_LAST)
             break;
 
         // Check operation validity
@@ -712,18 +745,18 @@
         if (!dmC64GetOpSize(op, fmt, &size))
         {
             return dmError(DMERR_INVALID_DATA,
-                "Decode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), "
+                "Decode op SIZE out of bounds, op #%d type=%d, subj=%d, offs=%d ($%04x), "
                 "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n",
-                i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size);
+                i, op->type, op->subject, op->offs, op->offs, op->bank, size, size, op->size, op->size);
         }
 
         // Is the operation inside the bounds?
         if (op->offs + size > len + 1)
         {
             return dmError(DMERR_INVALID_DATA,
-                "Decode DATA out of bounds, op #%d type=%d, offs=%d ($%04x), "
+                "Decode DATA out of bounds, op #%d type=%d, subj=%d, offs=%d ($%04x), "
                 "bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                i, op->type, op->offs, op->offs, op->bank, size, size, len, len);
+                i, op->type, op->subject, op->offs, op->offs, op->bank, size, size, len, len);
         }
 
         src = buf + op->offs;
@@ -731,65 +764,80 @@
         // Perform operation
         switch (op->type)
         {
-            case DT_COLOR_RAM:
-            case DT_SCREEN_RAM:
-            case DT_BITMAP_RAM:
-            case DT_CHAR_DATA:
-            case DT_EXTRA_DATA:
-                switch (op->type)
-                {
-                    case DT_COLOR_RAM  : blk = &img->color[op->bank]; blkname = "Color RAM"; break;
-                    case DT_SCREEN_RAM : blk = &img->screen[op->bank]; blkname = "Screen RAM"; break;
-                    case DT_BITMAP_RAM : blk = &img->bitmap[op->bank]; blkname = "Bitmap RAM"; break;
-                    case DT_CHAR_DATA  : blk = &img->charData[op->bank]; blkname = "Character data"; break;
-                    case DT_EXTRA_DATA : blk = &img->extraData[op->bank]; blkname = "Extra data"; break;
-                }
-                if ((dmC64MemBlockAlloc(blk, size)) != DMERR_OK)
+            case DO_COPY:
+            case DO_SET_MEM:
+            case DO_SET_OP:
+                switch (op->subject)
                 {
-                    return dmError(DMERR_MALLOC,
-                        "Could not allocate '%s' block! "
-                        "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        blkname, i, op->offs, op->offs, op->bank, size, size, len, len);
-                }
-                memcpy(blk->data, src, size);
-                break;
+                    case DS_COLOR_RAM:
+                    case DS_SCREEN_RAM:
+                    case DS_BITMAP_RAM:
+                    case DS_CHAR_DATA:
+                    case DS_EXTRA_DATA:
+                        // XXX BZZZT .. a nasty cast here --v
+                        dmC64GetOpMemBlockAndName(img, op->subject, op->bank, (const DMC64MemBlock **) &blk, &blkname);
+                        if ((dmC64MemBlockAlloc(blk, size)) != DMERR_OK)
+                        {
+                            return dmError(DMERR_MALLOC,
+                                "Could not allocate '%s' block! "
+                                "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                blkname, i, op->offs, op->offs, op->bank, size, size, len, len);
+                        }
+                        switch (op->type)
+                        {
+                            case DO_COPY:
+                                memcpy(blk->data, src, size);
+                                break;
+
+                            case DO_SET_MEM:
+                                memset(blk->data, *src, size);
+                                break;
+
+                            case DO_SET_OP:
+                                memset(blk->data, op->offs, size);
+                                break;
+                        }
+                        break;
 
-            case DT_COLOR_REG:
-                switch (op->size)
-                {
-                    case DC_D020: img->d020 = *src; break;
-                    case DC_BGCOL:
-                    case DC_D021: img->bgcolor = *src; break;
-                    case DC_D022: img->d022 = *src; break;
-                    case DC_D023: img->d023 = *src; break;
-                    case DC_D024: img->d024 = *src; break;
+                    case DS_D020:
+                    case DS_BGCOL:
+                    case DS_D021:
+                    case DS_D022:
+                    case DS_D023:
+                    case DS_D024:
+                        switch (op->type)
+                        {
+                            case DO_COPY:
+                            case DO_SET_MEM:
+                                value = *src;
+                                break;
+
+                            case DO_SET_OP:
+                                value = op->offs;
+                                break;
+
+                        }
+                        switch (op->subject)
+                        {
+                            case DS_D020: img->d020 = value; break;
+                            case DS_BGCOL:
+                            case DS_D021: img->bgcolor = value; break;
+                            case DS_D022: img->d022 = value; break;
+                            case DS_D023: img->d023 = value; break;
+                            case DS_D024: img->d024 = value; break;
+                        }
+                        break;
+
                     default:
                         return dmError(DMERR_INTERNAL,
-                            "Unhandled DT_COLOR_REG mode %d in "
+                            "Unhandled subject %d in "
                             "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                            op->size, i, op->offs, op->offs, op->bank, size, size, len, len);
+                            op->subject, i, op->offs, op->offs, op->bank, size, size, len, len);
                 }
                 break;
 
-            case DT_COLOR_SET:
-                switch (op->size)
-                {
-                    case DC_D020: img->d020 = op->offs; break;
-                    case DC_BGCOL:
-                    case DC_D021: img->bgcolor = op->offs; break;
-                    case DC_D022: img->d022 = op->offs; break;
-                    case DC_D023: img->d023 = op->offs; break;
-                    case DC_D024: img->d024 = op->offs; break;
-                    default:
-                        return dmError(DMERR_INTERNAL,
-                            "Unhandled DT_COLOR_SET mode %d in "
-                            "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                            op->size, i, op->offs, op->offs, op->bank, size, size, len, len);
-                }
-                break;
-
-            case DT_CHAR_CONFIG:
-                switch (op->offs)
+            case DO_CHAR_CFG:
+                switch (op->subject)
                 {
                     case D64_CHCFG_SCREEN:
                         break;
@@ -804,13 +852,13 @@
 
                     default:
                         return dmError(DMERR_INTERNAL,
-                            "Unhandled DT_CHAR_CONFIG mode %d in ",
+                            "Unhandled DO_CHAR_CFG mode %d in ",
                             "op #%d, bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                            op->offs, i, op->bank, size, size, len, len);
+                            op->subject, i, op->bank, size, size, len, len);
                 }
                 break;
 
-            case DT_DEC_FUNCTION:
+            case DO_DEC_FUNC:
                 if (op->decFunction == NULL)
                 {
                     return dmError(DMERR_INTERNAL,
@@ -866,9 +914,10 @@
         size_t size, chksize;
         const DMC64MemBlock *blk = NULL;
         char *blkname = NULL;
+        Uint8 value;
 
         // Check for last operator
-        if (op->type == DT_LAST)
+        if (op->type == DO_LAST)
             break;
 
         // Check operation validity
@@ -899,60 +948,98 @@
             buf->len = chksize;
 
         // Perform operation
-        Uint8 *dst = buf->data + op->offs;
+        Uint8 *dst;
+        dst = buf->data + op->offs;
         switch (op->type)
         {
-            case DT_COLOR_RAM:
-            case DT_SCREEN_RAM:
-            case DT_BITMAP_RAM:
-            case DT_CHAR_DATA:
-            case DT_EXTRA_DATA:
-                switch (op->type)
-                {
-                    case DT_COLOR_RAM  : blk = &img->color[op->bank]; blkname = "Color RAM"; break;
-                    case DT_SCREEN_RAM : blk = &img->screen[op->bank]; blkname = "Screen RAM"; break;
-                    case DT_BITMAP_RAM : blk = &img->bitmap[op->bank]; blkname = "Bitmap RAM"; break;
-                    case DT_CHAR_DATA  : blk = &img->charData[op->bank]; blkname = "Character data"; break;
-                    case DT_EXTRA_DATA : blk = &img->extraData[op->bank]; blkname = "Extra data"; break;
-                }
-                if (blk->data == NULL)
-                {
-                    res = dmError(DMERR_NULLPTR,
-                        "'%s' block is NULL in "
-                        "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
-                    goto err;
-                }
-                if (size > blk->size)
+            case DO_COPY:
+            case DO_SET_MEM:
+            case DO_SET_OP:
+                switch (op->subject)
                 {
-                    res = dmError(DMERR_INTERNAL,
-                        "'%s' size mismatch %d <> %d in "
-                        "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
-                    goto err;
-                }
-                memcpy(dst, blk->data, size);
-                break;
+                    case DS_COLOR_RAM:
+                    case DS_SCREEN_RAM:
+                    case DS_BITMAP_RAM:
+                    case DS_CHAR_DATA:
+                    case DS_EXTRA_DATA:
+                        dmC64GetOpMemBlockAndName(img, op->subject, op->bank, &blk, &blkname);
+                        if (blk->data == NULL)
+                        {
+                            res = dmError(DMERR_NULLPTR,
+                                "'%s' block is NULL in "
+                                "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                            goto err;
+                        }
+                        if (size > blk->size)
+                        {
+                            res = dmError(DMERR_INTERNAL,
+                                "'%s' size mismatch %d <> %d in "
+                                "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                            goto err;
+                        }
+                        switch (op->type)
+                        {
+                            case DO_COPY:
+                                memcpy(dst, blk->data, size);
+                                break;
+
+                            case DO_SET_MEM:
+                                // This operation makes no sense
+                                res = dmError(DMERR_INTERNAL,
+                                    "'%s' block DO_SET_MEM (which makes no sense) in "
+                                    "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                    blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                                goto err;
 
-            case DT_COLOR_REG:
-                switch (op->size)
-                {
-                    case DC_D020: *dst = img->d020; break;
-                    case DC_BGCOL:
-                    case DC_D021: *dst = img->bgcolor; break;
-                    case DC_D022: *dst = img->d022; break;
-                    case DC_D023: *dst = img->d023; break;
-                    case DC_D024: *dst = img->d024; break;
+                            case DO_SET_OP:
+                                memset(dst, op->offs, size);
+                                break;
+                        }
+                        break;
+
+                    case DS_D020:
+                    case DS_BGCOL:
+                    case DS_D021:
+                    case DS_D022:
+                    case DS_D023:
+                    case DS_D024:
+                        switch (op->subject)
+                        {
+                            case DS_D020: value = img->d020; break;
+                            case DS_BGCOL:
+                            case DS_D021: value = img->bgcolor; break;
+                            case DS_D022: value = img->d022; break;
+                            case DS_D023: value = img->d023; break;
+                            case DS_D024: value = img->d024; break;
+                        }
+                        switch (op->type)
+                        {
+                            case DO_COPY:
+                            case DO_SET_MEM:
+                                *dst = value;
+                                break;
+
+                            case DO_SET_OP:
+                                // This operation makes no sense
+                                res = dmError(DMERR_INTERNAL,
+                                    "'%s' block DO_SET_OP (which makes no sense) in "
+                                    "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
+                                    blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                                goto err;
+                        }
+                        break;
+
                     default:
-                        res = dmError(DMERR_INTERNAL,
-                            "Unhandled DT_COLOR_REG mode %d in "
+                        return dmError(DMERR_INTERNAL,
+                            "Unhandled subject %d in "
                             "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                            op->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
-                        goto err;
+                            op->subject, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
                 }
                 break;
 
-            case DT_ENC_FUNCTION:
+            case DO_ENC_FUNC:
                 if (op->encFunction == NULL)
                 {
                     res = dmError(DMERR_INTERNAL,