changeset 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 7f74073813c6
children fb7318b952c0
files tools/gfxconv.c tools/lib64fmts.c tools/lib64gfx.c tools/lib64gfx.h
diffstat 4 files changed, 388 insertions(+), 289 deletions(-) [+]
line wrap: on
line diff
--- a/tools/gfxconv.c	Wed May 30 21:10:57 2018 +0300
+++ b/tools/gfxconv.c	Thu May 31 00:04:01 2018 +0300
@@ -1027,7 +1027,7 @@
             size_t size;
 
             // Check for last operator
-            if (op->type == DT_LAST)
+            if (op->type == DO_LAST)
                 break;
 
             // Check size
@@ -1037,8 +1037,13 @@
             // Perform operation
             switch (op->type)
             {
-                case DT_EXTRA_DATA:
-                    dmC64MemBlockAlloc(&dst->extraData[op->bank], size);
+                case DO_COPY:
+                    switch (op->subject)
+                    {
+                        case DS_EXTRA_DATA:
+                            dmC64MemBlockAlloc(&dst->extraData[op->bank], size);
+                            break;
+                    }
                     break;
             }
         }
--- a/tools/lib64fmts.c	Wed May 30 21:10:57 2018 +0300
+++ b/tools/lib64fmts.c	Thu May 31 00:04:01 2018 +0300
@@ -528,7 +528,12 @@
 }
 
 
-#define XX2_MIN_SIZE 4000
+#define XX2_MIN_SIZE   4000
+#define XX2_WIDTH_CH   40
+#define XX2_HEIGHT_CH  10
+#define XX2_SIZE       (XX2_WIDTH_CH * XX2_HEIGHT_CH)
+#define XX2_BSIZE      (XX2_SIZE * 8)
+
 
 static int fmtProbeFormatXX2(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
 {
@@ -753,7 +758,7 @@
 // Helper macros for defining screen ram layouts
 // common for FLI type foramts
 //
-#define DEF_SCREEN_RAM(start, oindex, bindex, osize) { DT_SCREEN_RAM, (start) + ((osize) * (oindex)), (bindex), 0, NULL, NULL }
+#define DEF_SCREEN_RAM(start, oindex, bindex, osize) { DO_COPY, DS_SCREEN_RAM, (start) + ((osize) * (oindex)), (bindex), 0, NULL, NULL }
 #define DEF_SCREEN_RAMS_8(start, sindex, osize) \
     DEF_SCREEN_RAM((start), 0, (sindex + 0), (osize)), \
     DEF_SCREEN_RAM((start), 1, (sindex + 1), (osize)), \
@@ -774,68 +779,67 @@
 const DMC64EncDecOpList dmC64CommonFormatOps[] =
 {
         { // #0: Koala Paint type memory layout
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
-            { DT_COLOR_RAM,    0x2328, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x2710, 0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x1f40, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x2328, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x2710, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
         { // #1: Amica Paint, Run Paint, etc. layout
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
-            { DT_COLOR_RAM,    0x2328, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x2710, 0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x1f40, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x2328, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x2710, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
         { // #2: Art Studio etc. Hires
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x1f40, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
         { // #3: FunPaint II
-            DEF_SCREEN_RAMS_8( 0x0000, 0,  0x400),
-            { DT_BITMAP_RAM,   0x2000, 0,  0, NULL, NULL },
-            { DT_EXTRA_DATA,   0x3f40, 0,  100, NULL, NULL },
-            { DT_COLOR_RAM,    0x4000, 0,  0, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x43e8, 8,  0x400),
-            { DT_BITMAP_RAM,   0x63e8, 1,  0, NULL, NULL },
-            { DT_EXTRA_DATA,   0x8328, 1,  100, NULL, NULL },
-            { DT_DEC_FUNCTION, 0x2742, 0,  1, fmtTruePaintGetLaceType, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x0000, 0, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_EXTRA_DATA  , 0x3f40, 0,  100, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x4000, 0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x43e8, 8, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x63e8, 1,  0, NULL, NULL },
+            { DO_COPY     , DS_EXTRA_DATA  , 0x8328, 1,  100, NULL, NULL },
+            { DO_DEC_FUNC , 0              , 0x2742, 0,  1, fmtTruePaintGetLaceType, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
         { // #4: DrazPaint 1.x & 2
-            { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0800, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x2740, 0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0800, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x0400, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x2740, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
         { // #5: DrazLace 1.0
-            { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0800, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x2740, 0,  DC_BGCOL, NULL, NULL },
-            { DT_BITMAP_RAM,   0x2800, 1,  0, NULL, NULL },
-            { DT_DEC_FUNCTION, 0x2742, 0,  1, fmtDrazLaceGetLaceType, NULL },
-            { DT_ENC_FUNCTION, 0x2742, 0,  1, NULL, fmtDrazLaceSetLaceType },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0800, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x0400, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x2740, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2800, 1,  0, NULL, NULL },
+            { DO_DEC_FUNC , 0              , 0x2742, 0,  1, fmtDrazLaceGetLaceType, NULL },
+            { DO_ENC_FUNC , 0              , 0x2742, 0,  1, NULL, fmtDrazLaceSetLaceType },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 
-        {
-            // #6: TruePaint
-            { DT_SCREEN_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x03e8, 0,  DC_BGCOL, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_BITMAP_RAM,   0x2400, 1,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x4400, 1,  0, NULL, NULL },
-            { DT_COLOR_RAM,    0x4800, 0,  0, NULL, NULL },
-            { DT_DEC_FUNCTION, 0x0000, 0,  0, fmtTruePaintGetLaceType, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+        { // #6: TruePaint
+            { DO_COPY     , DS_SCREEN_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x03e8, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0400, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2400, 1,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x4400, 1,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x4800, 0,  0, NULL, NULL },
+            { DO_DEC_FUNC , 0              , 0x0000, 0,  0, fmtTruePaintGetLaceType, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
 };
 
@@ -909,11 +913,11 @@
         NULL, NULL,
         NULL,
         {
-            { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x07e8, 0,  DC_BGCOL, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0800, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x0000, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x07e8, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0800, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x0400, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
@@ -927,11 +931,11 @@
         NULL, NULL,
         NULL,
         {
-            { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x07fe, 0,  DC_BGCOL, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0800, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY  , DS_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x07fe, 0,  0, NULL, NULL },
+            { DO_COPY  , DS_BITMAP_RAM,   0x0800, 0,  0, NULL, NULL },
+            { DO_COPY  , DS_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
@@ -989,11 +993,11 @@
         NULL, NULL,
         NULL,
         {
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
-            { DT_COLOR_RAM,    0x2338, 0,  0, NULL, NULL },
-            { DT_COLOR_REG,    0x2329, 0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x1f40, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x2338, 0,  0, NULL, NULL },
+            { DO_SET_MEM  , DS_BGCOL       , 0x2329, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1062,9 +1066,9 @@
         NULL, NULL,
         NULL,
         {
-            { DT_SCREEN_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_BITMAP_RAM,   0x0400, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0400, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0,      0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1078,12 +1082,12 @@
         NULL, NULL,
         fmtGetPixelBFLI,
         {
-            { DT_COLOR_RAM,    0x0001, 0,  0, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x0401, 0,  0x400),
-            { DT_BITMAP_RAM,   0x2401, 0,  0x1fff, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x4401, 8,  0x400),
-            { DT_BITMAP_RAM,   0x6401, 1,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x0001, 0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x0401, 0, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2401, 0,  0x1fff, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x4401, 8, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x6401, 1,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0,      0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1098,11 +1102,11 @@
         NULL, NULL,
         fmtGetPixelBlackMailFLI,
         {
-            { DT_EXTRA_DATA,   0x0000, 0,  200, NULL, NULL },
-            { DT_COLOR_RAM,    0x0100, 0,  0, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x0500, 0,  0x400),
-            { DT_BITMAP_RAM,   0x2500, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_EXTRA_DATA  , 0x0000, 0,  200, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x0100, 0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x0500, 0, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2500, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0,      0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1116,10 +1120,10 @@
         NULL, NULL,
         fmtGetPixelFLIDesigner,
         {
-            { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
+            { DO_COPY  , DS_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             DEF_SCREEN_RAMS_8( 0x0400, 0,  0x400),
-            { DT_BITMAP_RAM,   0x2400, 0,  0, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY  , DS_BITMAP_RAM,   0x2400, 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0,      0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1133,20 +1137,15 @@
         NULL, NULL,
         NULL,
         {
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            { DT_SCREEN_RAM,   0x2000, 0,  0, NULL, NULL },
-            { DT_COLOR_RAM,    0x2400, 0,  0, NULL, NULL },
-            { DT_COLOR_SET,    0x00  , 0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            { 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_LAST     , 0              , 0,      0,  0, NULL, NULL },
         },
         NULL
     },
 
-#define XX2_WIDTH_CH   40
-#define XX2_HEIGHT_CH  10
-#define XX2_SIZE       (XX2_WIDTH_CH * XX2_HEIGHT_CH)
-#define XX2_BSIZE      (XX2_SIZE * 8)
-
     {
         D64_FMT_MC, "xx2", "Unknown $2000 format (unpacked)", 0x2000, 0, DM_FMT_RD,
         XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8,
@@ -1156,11 +1155,11 @@
         NULL, NULL,
         NULL,
         {
-            { DT_BITMAP_RAM,   0x0000, 0,  XX2_BSIZE, NULL, NULL },
-            { DT_SCREEN_RAM,   XX2_BSIZE, 0,  XX2_SIZE, NULL, NULL },
-            { DT_COLOR_RAM,    XX2_BSIZE + XX2_SIZE, 0,  XX2_SIZE, NULL, NULL },
-            { DT_COLOR_SET,    11,     0,  DC_BGCOL, NULL, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  XX2_BSIZE, NULL, NULL },
+            { DO_COPY     , DS_SCREEN_RAM  , XX2_BSIZE, 0,  XX2_SIZE, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , XX2_BSIZE + XX2_SIZE, 0,  XX2_SIZE, NULL, NULL },
+            { DO_SET_OP   , DS_BGCOL       , 11    , 0,  0, NULL, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1199,15 +1198,15 @@
         NULL, NULL,
         fmtGetPixelGunPaint,
         {
-            DEF_SCREEN_RAMS_8( 0x0000, 0,  0x400),
-            { DT_BITMAP_RAM,   0x2000, 0,  0, NULL, NULL },
-            { DT_EXTRA_DATA,   0x3f4f, 0,  177, NULL, NULL },
-            { DT_COLOR_RAM,    0x4000, 0,  0, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x4400, 8,  0x400),
-            { DT_BITMAP_RAM,   0x6400, 1,  0, NULL, NULL },
-            { DT_EXTRA_DATA,   0x47e8, 1,  20, NULL, NULL },
-            { DT_DEC_FUNCTION, 0x2742, 0,  1, fmtTruePaintGetLaceType, NULL },
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x0000, 0, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x2000, 0,  0, NULL, NULL },
+            { DO_COPY     , DS_EXTRA_DATA  , 0x3f4f, 0,  177, NULL, NULL },
+            { DO_COPY     , DS_COLOR_RAM   , 0x4000, 0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x4400, 8, 0x400),
+            { DO_COPY     , DS_BITMAP_RAM  , 0x6400, 1,  0, NULL, NULL },
+            { DO_COPY     , DS_EXTRA_DATA  , 0x47e8, 1,  20, NULL, NULL },
+            { DO_DEC_FUNC , 0              , 0x2742, 0,  1, fmtTruePaintGetLaceType, NULL },
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
@@ -1222,9 +1221,9 @@
         NULL, NULL,
         fmtGetPixelCHFLI,
         {
-            { DT_BITMAP_RAM,   0x0000, 0,  0, NULL, NULL },
-            DEF_SCREEN_RAMS_8( 0x2000, 0,  0x400),
-            { DT_LAST,         0,      0,  0, NULL, NULL },
+            { DO_COPY     , DS_BITMAP_RAM  , 0x0000, 0,  0, NULL, NULL },
+            DEF_SCREEN_RAMS_8(0x2000, 0, 0x400),
+            { DO_LAST     , 0              , 0     , 0,  0, NULL, NULL },
         },
         NULL
     },
--- 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,
--- a/tools/lib64gfx.h	Wed May 30 21:10:57 2018 +0300
+++ b/tools/lib64gfx.h	Thu May 31 00:04:01 2018 +0300
@@ -79,22 +79,37 @@
 };
 
 
-typedef struct
+// Different enc/dec operation types (op->type)
+enum
 {
-    BOOL multicolor, xexpand, yexpand;
-    int color, xc, yc;
-    Uint8 data[C64_SPR_HEIGHT][C64_SPR_WIDTH];
-} DMC64Sprite;
+    DO_COPY,               // Perform copy between memory (from/to offset) and subject
+    DO_SET_MEM,            // Set subject value or fill subject memory area to byte value from offset
+    DO_SET_OP,             // Like above but value from op->offs field instead
+
+    DO_DEC_FUNC,           // Execute specified decoding function (only for decoding operations)
+    DO_ENC_FUNC,           // Same, but for encoding
+
+    DO_CHAR_CFG,           // Set character mode configuration
+
+    DO_LAST,               // Last opcode, end processing
+};
 
 
+// "Subjects" of operations (op->subject)
 enum
 {
-    DC_D020,
-    DC_BGCOL,
-    DC_D021,
-    DC_D022,
-    DC_D023,
-    DC_D024,
+    DS_COLOR_RAM,
+    DS_BITMAP_RAM,
+    DS_SCREEN_RAM,
+    DS_EXTRA_DATA,
+    DS_CHAR_DATA,
+
+    DS_D020,
+    DS_BGCOL,
+    DS_D021,
+    DS_D022,
+    DS_D023,
+    DS_D024,
 };
 
 
@@ -105,6 +120,14 @@
 } DMC64MemBlock;
 
 
+typedef struct
+{
+    BOOL multicolor, xexpand, yexpand;
+    int color, xc, yc;
+    Uint8 data[C64_SPR_HEIGHT][C64_SPR_WIDTH];
+} DMC64Sprite;
+
+
 typedef struct _DMC64Image
 {
     int type,       // Image type (D64_FMT_*)
@@ -137,36 +160,21 @@
     const DMC64Image *img, const int bmoffs, const int scroffs,
     const int vshift, const int vbitmap, const int raster);
 
-enum
-{
-    DT_COLOR_RAM,
-    DT_BITMAP_RAM,
-    DT_SCREEN_RAM,
-    DT_COLOR_REG,
-    DT_COLOR_SET,
-    DT_EXTRA_DATA,
-
-    DT_DEC_FUNCTION,
-    DT_ENC_FUNCTION,
-
-    DT_CHAR_DATA,
-    DT_CHAR_CONFIG,
-
-    DT_LAST,
-};
-
-
 #define D64_MAX_ENCDEC_OPS 64
 
 
 typedef struct _DMC64ImageFormat DMC64ImageFormat;
 
+
 typedef struct _DMC64EncDecOp
 {
-    int    type;
+    int    type;     // Operation type (DO_*)
+    int    subject;  // Operation "subject" (DS_*)
+
     size_t offs;
     int    bank;
     size_t size;
+
     BOOL   (*decFunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt);
     BOOL   (*encFunction)(const struct _DMC64EncDecOp *op, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt);
 } DMC64EncDecOp;