changeset 2139:84780a9d8d17

Improve and fix charmap format decoding.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 29 May 2019 13:11:00 +0300
parents fdd0fd7dc0e6
children b8491ee3cf24
files tools/lib64fmts.c tools/lib64gfx.h
diffstat 2 files changed, 111 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64fmts.c	Wed May 29 11:31:38 2019 +0300
+++ b/tools/lib64fmts.c	Wed May 29 13:11:00 2019 +0300
@@ -89,52 +89,64 @@
 }
 
 
+static int fmtSetMarqPETSCIIData(const DMC64EncDecOp *op, DMC64Image *img,
+    const DMGrowBuf *buf, const DMC64ImageCommonFormat *fmt)
+{
+    (void) op;
+    (void) buf;
+    (void) fmt;
+
+    switch (img->extraData[0].data[0])
+    {
+        case 20: img->extraInfo[D64_EI_CHAR_CASE] = 0; break; // upper case
+        case 23: img->extraInfo[D64_EI_CHAR_CASE] = 1; break; // lower case
+        default:
+            return DMERR_INVALID_DATA;
+    }
+
+    img->extraInfo[D64_EI_CHAR_MODE] = D64_FMT_HIRES;
+    img->extraInfo[D64_EI_CHAR_CUSTOM] = 0;
+
+    return DMERR_OK;
+}
+
+
 static int fmtGetPixelPETSCII(Uint8 *col,
     const DMC64Image *img, const int rasterX, const int rasterY)
 {
     DM_C64_GENERIC_CHAR_PIXEL(img)
     int chr = img->screen[0].data[scroffs];
 
-    if (img->extraData[0].data != NULL)
+    if (!img->extraInfo[D64_EI_CHAR_CUSTOM] &&
+        img->extraInfo[D64_EI_CHAR_CASE])
+        chr += 256; // lower case, so add 256 to char ROM offset
+
+    switch (img->extraInfo[D64_EI_CHAR_MODE])
     {
-        // Marq's PETSCII editor
-        // d018 has been copied to extraData[0].data[0]
-        switch (img->extraData[0].data[0])
-        {
-            case 23: chr += 256; break; // lower case, so add 256 to char ROM offset
-            case 20: break; // upper case
-            default:
-                return DMERR_INVALID_DATA;
-        }
-    }
-    else
-    if (img->extraData[1].data != NULL)
-    {
-        // petscii.krissz.hu editor
-        if (img->extraData[1].data[0x0028 - 2] == 0xd8)
-        {
+        case D64_FMT_HIRES:
+            return dmC64GetGenericCharSCPixel(
+                col, img,
+                scroffs, rasterX,
+                0, (chr * D64_CHR_SIZE) + (rasterY & 7), chr,
+                0, img->bgcolor);
+
+        case D64_FMT_MC:
             return dmC64GetGenericCharMCPixel(
                 col, img,
                 scroffs, rasterX,
                 0, (chr * D64_CHR_SIZE) + (rasterY & 7), chr,
                 0, img->bgcolor, img->d022, img->d023);
-        }
-        else
-        if (img->extraData[1].data[0x0028 - 2] == 0x01)
-        {
+
+        case D64_FMT_ECM:
             return dmC64GetGenericCharECMPixel(
                 col, img,
                 scroffs, rasterX,
                 0, ((chr & 0x3f) * D64_CHR_SIZE) + (rasterY & 7), chr,
                 0, img->bgcolor, img->d022, img->d023, img->d024);
-        }
+
+        default:
+            return DMERR_INVALID_DATA;
     }
-
-    return dmC64GetGenericCharSCPixel(
-        col, img,
-        scroffs, rasterX,
-        0, (chr * D64_CHR_SIZE) + (rasterY & 7), chr,
-        0, img->bgcolor);
 }
 
 
@@ -164,6 +176,54 @@
 }
 
 
+static int fmtSetPetsciiKrisszHuData(const DMC64EncDecOp *op, DMC64Image *img,
+    const DMGrowBuf *buf, const DMC64ImageCommonFormat *fmt)
+{
+    (void) op;
+    (void) buf;
+    (void) fmt;
+
+    const Uint8 *data = img->extraData[0].data;
+    switch (data[0x0028 - 2])
+    {
+        case 0x00:
+            img->extraInfo[D64_EI_CHAR_MODE] = D64_FMT_HIRES;
+            img->d020    = data[0x001e - 2];
+            img->bgcolor = data[0x0023 - 2];
+            break;
+
+        case 0xd8:
+            img->extraInfo[D64_EI_CHAR_MODE] = D64_FMT_MC;
+            img->d020    = data[0x001e - 2];
+            img->bgcolor = data[0x0023 - 2];
+            img->d022    = data[0x002d - 2];
+            img->d023    = data[0x0032 - 2];
+            break;
+
+        case 0x01:
+            img->extraInfo[D64_EI_CHAR_MODE] = D64_FMT_ECM;
+            img->d020    = data[0x001e - 2];
+            img->bgcolor = data[0x0023 - 2];
+            img->d022    = data[0x0028 - 2];
+            img->d023    = data[0x002d - 2];
+            img->d024    = data[0x0032 - 2];
+            break;
+
+        default:
+            return DMERR_INVALID_DATA;
+    }
+
+    // XXX TODO this format saves the charset data (for 256 chars)
+    // in the PRG and there is no direct indication whether it is
+    // a customized one or copy of C64 ROM charset .. we could
+    // implement a hash-based detection at some point.
+    img->extraInfo[D64_EI_CHAR_CASE] = 0;
+    img->extraInfo[D64_EI_CHAR_CUSTOM] = 1;
+
+    return DMERR_OK;
+}
+
+
 static int fmtProbeKoalaPainter(const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
 {
     int score = DM_PROBE_SCORE_FALSE;
@@ -2141,7 +2201,8 @@
                 // For offset values see petscii/m_c64.pde :: save_prg()
                 { DO_SET_MEM_LO , DS_D020        , 25 - 2, 0,  0,   0, NULL, NULL },
                 { DO_SET_MEM_LO , DS_BGCOL       , 30 - 2, 0,  0,   0, NULL, NULL },
-                { DO_COPY       , DS_EXTRA_DATA  , 20 - 2, 0,  1,   0, NULL, NULL }, // upper/lower
+                { DO_COPY       , DS_EXTRA_DATA  , 20 - 2, 0,  1,   0, NULL, NULL },
+                { DO_FUNC       , 0              , 0     , 0,  0,   0, fmtSetMarqPETSCIIData, NULL },
 
                 { DO_LAST       , 0              , 0     , 0,  0,   0, NULL, NULL },
             }
@@ -2154,7 +2215,7 @@
         fmtProbePetsciiKrisszHu,
         NULL, NULL,
         {
-            D64_FMT_HIRES | D64_FMT_CHAR,
+            D64_FMT_CHAR,
             D64_SCR_WIDTH   , D64_SCR_HEIGHT,
             D64_SCR_CH_WIDTH, D64_SCR_CH_HEIGHT,
             1, 1,
@@ -2164,16 +2225,9 @@
                 { DO_COPY       , DS_SCREEN_RAM  , 0x2001 - 2, 0, 0,   0, NULL, NULL },
                 { DO_COPY       , DS_COLOR_RAM   , 0x23e9 - 2, 0, 0,   0, NULL, NULL },
 
-                { DO_SET_MEM_LO , DS_D020        , 0x001e - 2, 0, 0,   0, NULL, NULL },
-                { DO_SET_MEM_LO , DS_BGCOL       , 0x0023 - 2, 0, 0,   0, NULL, NULL },
-
-                { DO_SET_MEM_LO , DS_D022        , 0x0028 - 2, 0, 0,   0, NULL, NULL },
-                { DO_SET_MEM_LO , DS_D023        , 0x002d - 2, 0, 0,   0, NULL, NULL },
-                { DO_SET_MEM_LO , DS_D024        , 0x0032 - 2, 0, 0,   0, NULL, NULL },
-
-                { DO_COPY       , DS_EXTRA_DATA  , 0x0000    , 1, 0x0100,   0, NULL, NULL },
-
-                { DO_COPY       , DS_CHAR_DATA   , 0x1801 - 2, 0, 0x0800,   0, NULL, NULL },
+                { DO_COPY       , DS_EXTRA_DATA  , 0x0000    , 0, 0x0100, 0, NULL, NULL },
+                { DO_COPY       , DS_CHAR_DATA   , 0x1801 - 2, 0, 0x0800, 0, NULL, NULL },
+                { DO_FUNC       , 0              , 0         , 0, 0     , 0, fmtSetPetsciiKrisszHuData, NULL },
 
                 { DO_LAST       , 0              , 0         , 0, 0,   0, NULL, NULL },
             }
--- a/tools/lib64gfx.h	Wed May 29 11:31:38 2019 +0300
+++ b/tools/lib64gfx.h	Wed May 29 13:11:00 2019 +0300
@@ -28,7 +28,8 @@
 #define D64_SCR_HEIGHT         200
 #define D64_SCR_CH_WIDTH       (D64_SCR_WIDTH/8)
 #define D64_SCR_CH_HEIGHT      (D64_SCR_HEIGHT/8)
-#define D64_MAX_EXTRA_DATA     64
+#define D64_MAX_EXTRA_DATA     16
+#define D64_MAX_EXTRA_INFO     64
 
 // C64 video screen pixel aspect ratio on PAL
 #define D64_SCR_PAR_XY         (0.9365f)
@@ -87,6 +88,15 @@
 };
 
 
+// Various extra settings (see DMC64Image::extraInfo[])
+enum
+{
+    D64_EI_CHAR_CASE = 0,
+    D64_EI_CHAR_MODE,
+    D64_EI_CHAR_CUSTOM,
+};
+
+
 // Image <-> bitmap conversion dithering
 enum
 {
@@ -179,6 +189,11 @@
     // for example raster colours might be stored
     DMC64MemBlock extraData[D64_MAX_EXTRA_DATA];
 
+    // Extra information / settings used by some formats,
+    // for example some PETSCII-type formats.
+    // See D64_EI_* constants.
+    Uint8 extraInfo[D64_MAX_EXTRA_INFO];
+
     //DMC64Sprite sprites[D64_MAX_SPRITES];
 } DMC64Image;
 
@@ -474,7 +489,7 @@
             case 0: *col = bgcolor; break;
             case 1: *col = bgd022; break;
             case 2: *col = bgd023; break;
-            case 3: *col = ccol & 15;
+            case 3: *col = ccol & 7;
         }
     }
     else