# HG changeset patch # User Matti Hamalainen # Date 1559350565 -10800 # Node ID 009ee261704c08f153c54adc8e5402dd812a6846 # Parent b8491ee3cf24368caefb9c5ee211bb755fa77a72 Add somewhat broken support for decoding packed Cosmos Designs Hires Manager files. This format has a particularly buggy RLE+literal encoder. diff -r b8491ee3cf24 -r 009ee261704c tools/lib64fmts.c --- a/tools/lib64fmts.c Sat Jun 01 03:18:01 2019 +0300 +++ b/tools/lib64fmts.c Sat Jun 01 03:56:05 2019 +0300 @@ -978,6 +978,87 @@ } +static int fmtDecodeCosmosDesignsHiresManagerPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt) +{ + int res; + DMGrowBuf src, tmp; + DMCompParams cfg; + Uint8 data, count; + const size_t dstSize = 0x7ff2 - 0x4000; + size_t dstOffs; + Uint8 *dstBuf; + BOOL getByte = TRUE; + + if ((dstBuf = dmMalloc0(dstSize)) == NULL) + { + return dmError(DMERR_MALLOC, + "Could not allocate memory for RLE decoding buffer.\n"); + } + + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BACKWARDS_INPUT; + + dmGrowBufConstCopy(&src, psrc); + dmSetupRLEBuffers(NULL, &src, &cfg); + dstOffs = dstSize; + + while (dstOffs > 0 && src.offs > 0) + { + if (getByte && !dmGrowBufGetU8(&src, &data)) + { + res = dmError(DMERR_INVALID_DATA, + "%s: RLE: Invalid data/out of data for literal sequence.\n", + cfg.func); + goto out; + } + + // A simple marker byte RLE variant: [Marker] [count] [data] + if (data == 0) + { + if (!dmGrowBufGetU8(&src, &count) || + !dmGrowBufGetU8(&src, &data)) + { + res = dmError(DMERR_INVALID_DATA, + "%s: RLE: Invalid data/out of data for run sequence.\n", + cfg.func); + goto out; + } + + int ncount = (int) count; + for (int n = 1; n < ncount && dstOffs > 0; n++) + dstBuf[--dstOffs] = data; + + getByte = TRUE; + } + else + // Literal run of data bytes + { + int ncount = (int) data; + for (int n = 0; n < ncount; n++) + { + if (!dmGrowBufGetU8(&src, &data)) + break; + + if (dstOffs > 0) + dstBuf[--dstOffs] = data; + else + break; + } + getByte = FALSE; + } + } + + dmGrowBufConstCreateFrom(&tmp, dstBuf, 0x3fff); + res = dmC64DecodeGenericBMP(img, &tmp, fmt); + +out: + dmGrowBufFree(&src); + dmFree(dstBuf); + return res; +} + + #define FUNPAINT2_HEADER_SIZE (0x10) static const char *fmtFunPaint2MagicID = "FUNPAINT (MT) "; @@ -2184,6 +2265,13 @@ }, { + "cdhp", "Cosmos Designs Hires Manager (packed)", 0x4000, 0, DM_FMT_RD | DM_FMT_BROKEN, + fmtProbeCosmosDesignsHiresManager, + fmtDecodeCosmosDesignsHiresManagerPacked, NULL, + { }, &dmC64CommonFormats[8] + }, + + { "mrqp", "Marq's PETSCII editor (unpacked)", 0x0801, 0, DM_FMT_RD, fmtProbeMarqPETSCII, NULL, NULL,