changeset 1588:ca087c0cc9c4

Refactor the c64 format memory handling a bit for more flexibility.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 14 May 2018 04:27:53 +0300
parents e6a228b50bd6
children f741dc2d1479
files tools/gfxconv.c tools/lib64fmts.c tools/lib64gfx.c tools/lib64gfx.h
diffstat 4 files changed, 158 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/tools/gfxconv.c	Mon May 14 04:11:45 2018 +0300
+++ b/tools/gfxconv.c	Mon May 14 04:27:53 2018 +0300
@@ -1003,10 +1003,9 @@
     {
         for (int i = 0; i < dst->nbanks; i++)
         {
-            memcpy(dst->color[i], src->color[i], dst->screenSize);
-            memcpy(dst->bitmap[i], src->bitmap[i], dst->bitmapSize);
-            memcpy(dst->screen[i], src->screen[i], dst->screenSize);
-            memcpy(dst->charmem[i], src->charmem[i], dst->charmemSize);
+            dmC64MemBlockCopy(&dst->color[i], &src->color[i]);
+            dmC64MemBlockCopy(&dst->screen[i], &src->screen[i]);
+            dmC64MemBlockCopy(&dst->bitmap[i], &src->bitmap[i]);
         }
     }
     else
@@ -1017,33 +1016,31 @@
             dmMsg(1, "Upconverting multicolor to FLI.\n");
             for (int i = 0; i < dst->nbanks; i++)
             {
-                memcpy(dst->color[i], src->color[0], dst->screenSize);
-                memcpy(dst->screen[i], src->screen[0], dst->screenSize);
-                memcpy(dst->bitmap[i], src->bitmap[0], dst->bitmapSize);
-                memcpy(dst->charmem[i], src->charmem[0], dst->charmemSize);
+                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 = &dstFmt->encdecOps[i];
+            size_t size;
 
-            for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
+            // Check for last operator
+            if (op->type == DT_LAST)
+                break;
+
+            // Check size
+            if (!dmC64GetOpSize(op, dstFmt, &size))
+                return DMERR_INVALID_DATA;
+
+            // Perform operation
+            switch (op->type)
             {
-                const DMC64EncDecOp *op = &dstFmt->encdecOps[i];
-                size_t size;
-
-                // Check for last operator
-                if (op->type == DT_LAST)
+                case DT_EXTRA_DATA:
+                    dmC64MemBlockAlloc(&dst->extraData[op->bank], size);
                     break;
-
-                // Check size
-                if (!dmC64GetOpSize(op, dstFmt, &size))
-                    return DMERR_INVALID_DATA;
-
-                // Perform operation
-                switch (op->type)
-                {
-                    case DT_EXTRA_DATA:
-                        dst->extraData[op->bank] = dmMalloc0(size);
-                        dst->extraDataSizes[op->bank] = size;
-                        break;
-                }
             }
         }
     }
--- a/tools/lib64fmts.c	Mon May 14 04:11:45 2018 +0300
+++ b/tools/lib64fmts.c	Mon May 14 04:27:53 2018 +0300
@@ -436,7 +436,7 @@
     return dmC64GetGenericMCPixel(
         img, bmoffs, scroffs, vshift,
         vbank, vbitmap, 0,
-        img->extraData[vb][vr] & 15);
+        img->extraData[vb].data[vr] & 15);
 }
 
 
@@ -460,7 +460,7 @@
     return dmC64GetGenericMCPixel(
         img, bmoffs, scroffs, vshift,
         vbank, vbitmap, 0,
-        img->extraData[vb][vr] & 15);
+        img->extraData[vb].data[vr] & 15);
 }
 
 
@@ -491,7 +491,7 @@
     return dmC64GetGenericMCPixel(
         img, bmoffs, scroffs, vshift,
         vbank, vbitmap, 0,
-        img->extraData[0][raster] & 15);
+        img->extraData[0].data[raster] & 15);
 }
 
 
@@ -509,10 +509,10 @@
 {
     const int vbank = raster & 7;
 
-    if ((img->bitmap[vbitmap][bmoffs] >> vshift) & 1)
-        return img->screen[vbank][scroffs] >> 4;
+    if ((img->bitmap[vbitmap].data[bmoffs] >> vshift) & 1)
+        return img->screen[vbank].data[scroffs] >> 4;
     else
-        return img->screen[vbank][scroffs] & 15;
+        return img->screen[vbank].data[scroffs] & 15;
 }
 
 
--- a/tools/lib64gfx.c	Mon May 14 04:11:45 2018 +0300
+++ b/tools/lib64gfx.c	Mon May 14 04:27:53 2018 +0300
@@ -100,6 +100,41 @@
 }
 
 
+int dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size)
+{
+    if ((blk->data = dmMalloc0(size)) == NULL)
+        return DMERR_MALLOC;
+
+    blk->size = size;
+    return DMERR_OK;
+}
+
+
+int dmC64MemBlockCopy(DMC64MemBlock *dst, const DMC64MemBlock *src)
+{
+    if (src->data != NULL && src->size > 0)
+    {
+        dst->size = src->size;
+        if ((dst->data = dmMalloc(src->size)) == NULL)
+            return DMERR_MALLOC;
+
+        memcpy(dst->data, src->data, src->size);
+    }
+
+    return DMERR_OK;
+}
+
+
+void dmC64MemBlockFree(DMC64MemBlock *blk)
+{
+    if (blk != NULL)
+    {
+        dmFreeR(&blk->data);
+        blk->size = 0;
+    }
+}
+
+
 DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt)
 {
     DMC64Image *img = dmMalloc0(sizeof(DMC64Image));
@@ -115,32 +150,13 @@
     img->chHeight    = fmt->chHeight;
     img->nbanks      = dmC64ImageGetNumBanks(fmt);
 
-    img->screenSize  = img->chWidth * img->chHeight;
-    img->bitmapSize  = img->screenSize * 8;
-    img->charmemSize = C64_MAX_CHARS * C64_CHR_SIZE;
-
     // Allocate banks
-    if ((img->color = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL ||
-        (img->bitmap = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL ||
-        (img->screen = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL ||
-        (img->charmem = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL)
+    if ((img->color = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
+        (img->bitmap = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
+        (img->screen = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
+        (img->charData = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL)
         goto err;
 
-    for (int i = 0; i < img->nbanks; i++)
-    {
-        if ((img->color[i] = dmMalloc0(img->screenSize)) == NULL)
-            goto err;
-
-        if ((img->bitmap[i] = dmMalloc0(img->bitmapSize)) == NULL)
-            goto err;
-
-        if ((img->screen[i] = dmMalloc0(img->screenSize)) == NULL)
-            goto err;
-
-        if ((img->charmem[i] = dmMalloc0(img->charmemSize)) == NULL)
-            goto err;
-    }
-
     return img;
 
 err:
@@ -156,21 +172,21 @@
         // Free the allocated areas
         for (int i = 0; i < img->nbanks; i++)
         {
-            dmFree(img->color[i]);
-            dmFree(img->bitmap[i]);
-            dmFree(img->screen[i]);
-            dmFree(img->charmem[i]);
+            dmC64MemBlockFree(&img->color[i]);
+            dmC64MemBlockFree(&img->bitmap[i]);
+            dmC64MemBlockFree(&img->screen[i]);
+            dmC64MemBlockFree(&img->charData[i]);
         }
 
         // Free the pointers to the areas
         dmFree(img->color);
         dmFree(img->bitmap);
         dmFree(img->screen);
-        dmFree(img->charmem);
+        dmFree(img->charData);
 
         // Extra data ..
         for (int i = 0; i < C64_MAX_EXTRA_DATA; i++)
-            dmFree(img->extraData[i]);
+            dmC64MemBlockFree(&img->extraData[i]);
 
         dmMemset(img, 0, sizeof(DMC64Image));
         dmFree(img);
@@ -596,6 +612,8 @@
     {
         const DMC64EncDecOp *op = &fmt->encdecOps[i];
         const Uint8 *src;
+        DMC64MemBlock *blk;
+        char *blkname;
         size_t size;
 
         // Check for last operator
@@ -615,11 +633,11 @@
                 i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size);
         }
 
-        // Do we need to reallocate some more space?
+        // Is the operation inside the bounds?
         if (op->offs + size > len + 1)
         {
             return dmError(DMERR_INVALID_DATA,
-                "Decode out of bounds, op #%d type=%d, offs=%d ($%04x), "
+                "Decode DATA out of bounds, op #%d type=%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);
         }
@@ -629,27 +647,28 @@
         // Perform operation
         switch (op->type)
         {
-            case DT_COLOR_RAM:   memcpy(img->color[op->bank], src, size); break;
-            case DT_BITMAP_RAM:  memcpy(img->bitmap[op->bank], src, size); break;
-            case DT_SCREEN_RAM:  memcpy(img->screen[op->bank], src, size); break;
-            case DT_CHAR_DATA:   memcpy(img->charmem[op->bank], src, size); break;
+            case DT_COLOR_RAM:
+            case DT_SCREEN_RAM:
+            case DT_BITMAP_RAM:
+            case DT_CHAR_DATA:
             case DT_EXTRA_DATA:
-                if (img->extraData[op->bank] != NULL)
+                switch (op->type)
                 {
-                    return dmError(DMERR_INTERNAL,
-                        "Extra data block already allocated and used! "
-                        "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        i, op->offs, op->offs, op->bank, size, size, len, len);
+                    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 ((img->extraData[op->bank] = dmMalloc0(size)) == NULL)
+                if ((dmC64MemBlockAlloc(blk, size)) != DMERR_OK)
                 {
                     return dmError(DMERR_MALLOC,
-                        "Could not allocate extradata block! "
+                        "Could not allocate '%s' block! "
                         "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        i, op->offs, op->offs, op->bank, size, size, len, len);
+                        blkname, i, op->offs, op->offs, op->bank, size, size, len, len);
                 }
-                img->extraDataSizes[op->bank] = size;
-                memcpy(img->extraData[op->bank], src, size);
+                blk->size = size;
+                memcpy(blk->data, src, size);
                 break;
 
             case DT_COLOR_REG:
@@ -696,7 +715,7 @@
                         {
                             for (int bank = 0; bank < img->nbanks; bank++)
                             for (int offs = 0; offs < fmt->chHeight * fmt->chWidth; offs++)
-                                img->screen[bank][offs] = offs & 0xff;
+                                img->screen[bank].data[offs] = offs & 0xff;
                         }
                         break;
 
@@ -754,6 +773,8 @@
     {
         const DMC64EncDecOp *op = &fmt->encdecOps[i];
         size_t size, chksize;
+        const DMC64MemBlock *blk;
+        char *blkname;
 
         // Check for last operator
         if (op->type == DT_LAST)
@@ -790,28 +811,36 @@
         Uint8 *dst = buf->data + op->offs;
         switch (op->type)
         {
-            case DT_COLOR_RAM:   memcpy(dst, img->color[op->bank], size); break;
-            case DT_BITMAP_RAM:  memcpy(dst, img->bitmap[op->bank], size); break;
-            case DT_SCREEN_RAM:  memcpy(dst, img->screen[op->bank], size); break;
-            case DT_CHAR_DATA:   memcpy(dst, img->charmem[op->bank], size); break;
+            case DT_COLOR_RAM:
+            case DT_SCREEN_RAM:
+            case DT_BITMAP_RAM:
+            case DT_CHAR_DATA:
             case DT_EXTRA_DATA:
-                if (img->extraData[op->bank] == NULL)
+                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,
-                        "DT_EXTRA_DATA block is NULL in "
+                        "'%s' block is NULL in "
                         "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                        blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
                     goto err;
                 }
-                if (size > img->extraDataSizes[op->bank])
+                if (size > blk->size)
                 {
                     res = dmError(DMERR_INTERNAL,
-                        "DT_EXTRA_DATA size mismatch %d <> %d in "
+                        "'%s' size mismatch %d <> %d in "
                         "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
-                        op->size, img->extraDataSizes[op->bank], i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
+                        blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
                     goto err;
                 }
-                memcpy(dst, img->extraData[op->bank], size);
+                memcpy(dst, blk->data, size);
                 break;
 
             case DT_COLOR_REG:
@@ -910,11 +939,11 @@
             {
                 const int x = xc / 8;
                 const int scroffs = scroffsy + x;
-                const int chr = src->screen[0][scroffs];
+                const int chr = src->screen[0].data[scroffs];
                 const int v = 7 - (xc & 7);
 
-                if ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 1)
-                    *d++ = src->color[0][scroffs];
+                if ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 1)
+                    *d++ = src->color[0].data[scroffs];
                 else
                     *d++ = src->bgcolor;
             }
@@ -924,13 +953,13 @@
             {
                 const int x = xc / 4;
                 const int scroffs = scroffsy + x;
-                const int chr = src->screen[0][scroffs];
-                const int col = src->color[0][scroffs] & 15;
+                const int chr = src->screen[0].data[scroffs];
+                const int col = src->color[0].data[scroffs] & 15;
 
                 if (col & 8)
                 {
                     const int v = 6 - ((xc * 2) & 6);
-                    switch ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 3)
+                    switch ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 3)
                     {
                         case 0: *d++ = src->bgcolor; break;
                         case 1: *d++ = src->d022; break;
@@ -941,8 +970,8 @@
                 else
                 {
                     const int v = 7 - (xc & 7);
-                    if ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 1)
-                        *d++ = src->color[0][scroffs];
+                    if ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 1)
+                        *d++ = src->color[0].data[scroffs];
                     else
                         *d++ = src->bgcolor;
                 }
--- a/tools/lib64gfx.h	Mon May 14 04:11:45 2018 +0300
+++ b/tools/lib64gfx.h	Mon May 14 04:27:53 2018 +0300
@@ -98,6 +98,13 @@
 };
 
 
+typedef struct
+{
+    Uint8 *data;
+    size_t size;
+} DMC64MemBlock;
+
+
 typedef struct _DMC64Image
 {
     int type,       // Image type (D64_FMT_*)
@@ -107,20 +114,20 @@
     int width, height; // Width and height in pixels
     int chWidth, chHeight; // Width and height in charblocks
 
-    size_t
-        screenSize,
-        bitmapSize,
-        charmemSize;
+    // Bitmaps, color RAM, screen, etc. blocks * nbanks
+    // Not all of them may be allocated
+    DMC64MemBlock
+        *color,
+        *bitmap,
+        *screen,
+        *charData;
 
-    Uint8
-        **color,
-        **bitmap,
-        **screen,
-        **charmem,
-        *extraData[C64_MAX_EXTRA_DATA],
-        d020, bgcolor, d022, d023, d024;
+    // Other standard colours
+    Uint8 d020, bgcolor, d022, d023, d024;
 
-    size_t extraDataSizes[C64_MAX_EXTRA_DATA];
+    // Extra data areas used by some formats,
+    // for example raster colours might be stored
+    DMC64MemBlock extraData[C64_MAX_EXTRA_DATA];
 
     DMC64Sprite sprites[C64_MAX_SPRITES];
 } DMC64Image;
@@ -217,14 +224,20 @@
 // Miscellaneous functions
 //
 void      dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt);
+char *    dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng);
+
 void      dmSetDefaultC64Palette(DMImage *img);
-char *    dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng);
+int       dmC64ImageGetNumBanks(const DMC64ImageFormat *fmt);
 int       dmC64ConvertCSDataToImage(DMImage *img, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors);
-int       dmC64ImageGetNumBanks(const DMC64ImageFormat *fmt);
 BOOL      dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr);
+
 int       dmC64SanityCheckEncDecOp(const int i, const DMC64EncDecOp *op, const DMC64Image *img);
 BOOL      dmC64GetOpSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt, size_t *size);
 
+int       dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size);
+int       dmC64MemBlockCopy(DMC64MemBlock *dst, const DMC64MemBlock *src);
+void      dmC64MemBlockFree(DMC64MemBlock *blk);
+
 
 // C64 bitmap image allocation/freeing
 DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt);
@@ -263,10 +276,10 @@
     const int vshift, const int vbank, const int vbitmap, const int cbank)
 {
     (void) cbank;
-    if ((img->bitmap[vbitmap][bmoffs] >> vshift) & 1)
-        return img->screen[vbank][scroffs] >> 4;
+    if ((img->bitmap[vbitmap].data[bmoffs] >> vshift) & 1)
+        return img->screen[vbank].data[scroffs] >> 4;
     else
-        return img->screen[vbank][scroffs] & 15;
+        return img->screen[vbank].data[scroffs] & 15;
 }
 
 
@@ -275,12 +288,12 @@
     const int vshift, const int vbank, const int vbitmap, const int cbank,
     const int bgcolor)
 {
-    switch ((img->bitmap[vbitmap][bmoffs] >> vshift) & 3)
+    switch ((img->bitmap[vbitmap].data[bmoffs] >> vshift) & 3)
     {
         case  0: return bgcolor;
-        case  1: return img->screen[vbank][scroffs] >> 4;
-        case  2: return img->screen[vbank][scroffs] & 15;
-        default: return img->color[cbank][scroffs] & 15;
+        case  1: return img->screen[vbank].data[scroffs] >> 4;
+        case  2: return img->screen[vbank].data[scroffs] & 15;
+        default: return img->color[cbank].data[scroffs] & 15;
     }
 }