comparison tools/lib64fmts.c @ 2141:009ee261704c

Add somewhat broken support for decoding packed Cosmos Designs Hires Manager files. This format has a particularly buggy RLE+literal encoder.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 01 Jun 2019 03:56:05 +0300
parents 84780a9d8d17
children 810fc98d9003
comparison
equal deleted inserted replaced
2140:b8491ee3cf24 2141:009ee261704c
973 if (fmt->size != 0 && fmt->size == buf->len) 973 if (fmt->size != 0 && fmt->size == buf->len)
974 return DM_PROBE_SCORE_GOOD; 974 return DM_PROBE_SCORE_GOOD;
975 } 975 }
976 976
977 return DM_PROBE_SCORE_FALSE; 977 return DM_PROBE_SCORE_FALSE;
978 }
979
980
981 static int fmtDecodeCosmosDesignsHiresManagerPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt)
982 {
983 int res;
984 DMGrowBuf src, tmp;
985 DMCompParams cfg;
986 Uint8 data, count;
987 const size_t dstSize = 0x7ff2 - 0x4000;
988 size_t dstOffs;
989 Uint8 *dstBuf;
990 BOOL getByte = TRUE;
991
992 if ((dstBuf = dmMalloc0(dstSize)) == NULL)
993 {
994 return dmError(DMERR_MALLOC,
995 "Could not allocate memory for RLE decoding buffer.\n");
996 }
997
998 cfg.func = fmt->name;
999 cfg.type = DM_COMP_RLE_MARKER;
1000 cfg.flags = DM_RLE_BACKWARDS_INPUT;
1001
1002 dmGrowBufConstCopy(&src, psrc);
1003 dmSetupRLEBuffers(NULL, &src, &cfg);
1004 dstOffs = dstSize;
1005
1006 while (dstOffs > 0 && src.offs > 0)
1007 {
1008 if (getByte && !dmGrowBufGetU8(&src, &data))
1009 {
1010 res = dmError(DMERR_INVALID_DATA,
1011 "%s: RLE: Invalid data/out of data for literal sequence.\n",
1012 cfg.func);
1013 goto out;
1014 }
1015
1016 // A simple marker byte RLE variant: [Marker] [count] [data]
1017 if (data == 0)
1018 {
1019 if (!dmGrowBufGetU8(&src, &count) ||
1020 !dmGrowBufGetU8(&src, &data))
1021 {
1022 res = dmError(DMERR_INVALID_DATA,
1023 "%s: RLE: Invalid data/out of data for run sequence.\n",
1024 cfg.func);
1025 goto out;
1026 }
1027
1028 int ncount = (int) count;
1029 for (int n = 1; n < ncount && dstOffs > 0; n++)
1030 dstBuf[--dstOffs] = data;
1031
1032 getByte = TRUE;
1033 }
1034 else
1035 // Literal run of data bytes
1036 {
1037 int ncount = (int) data;
1038 for (int n = 0; n < ncount; n++)
1039 {
1040 if (!dmGrowBufGetU8(&src, &data))
1041 break;
1042
1043 if (dstOffs > 0)
1044 dstBuf[--dstOffs] = data;
1045 else
1046 break;
1047 }
1048 getByte = FALSE;
1049 }
1050 }
1051
1052 dmGrowBufConstCreateFrom(&tmp, dstBuf, 0x3fff);
1053 res = dmC64DecodeGenericBMP(img, &tmp, fmt);
1054
1055 out:
1056 dmGrowBufFree(&src);
1057 dmFree(dstBuf);
1058 return res;
978 } 1059 }
979 1060
980 1061
981 #define FUNPAINT2_HEADER_SIZE (0x10) 1062 #define FUNPAINT2_HEADER_SIZE (0x10)
982 static const char *fmtFunPaint2MagicID = "FUNPAINT (MT) "; 1063 static const char *fmtFunPaint2MagicID = "FUNPAINT (MT) ";
2182 NULL, NULL, 2263 NULL, NULL,
2183 { }, &dmC64CommonFormats[8] 2264 { }, &dmC64CommonFormats[8]
2184 }, 2265 },
2185 2266
2186 { 2267 {
2268 "cdhp", "Cosmos Designs Hires Manager (packed)", 0x4000, 0, DM_FMT_RD | DM_FMT_BROKEN,
2269 fmtProbeCosmosDesignsHiresManager,
2270 fmtDecodeCosmosDesignsHiresManagerPacked, NULL,
2271 { }, &dmC64CommonFormats[8]
2272 },
2273
2274 {
2187 "mrqp", "Marq's PETSCII editor (unpacked)", 0x0801, 0, DM_FMT_RD, 2275 "mrqp", "Marq's PETSCII editor (unpacked)", 0x0801, 0, DM_FMT_RD,
2188 fmtProbeMarqPETSCII, 2276 fmtProbeMarqPETSCII,
2189 NULL, NULL, 2277 NULL, NULL,
2190 { 2278 {
2191 D64_FMT_HIRES | D64_FMT_CHAR, 2279 D64_FMT_HIRES | D64_FMT_CHAR,