# HG changeset patch # User Matti Hamalainen # Date 1589500013 -10800 # Node ID 4dbb6572622db51efe7ab2d168beecbd94d8856b # Parent 470631c00c9797ef8ed9b93a75b09562fe286e30 Add preliminary decoder for SupeRes hires and multicolor files. The decoder is pretty horrible at the moment, should be cleaned up. diff -r 470631c00c97 -r 4dbb6572622d tools/lib64fmts.c --- a/tools/lib64fmts.c Tue May 12 20:49:12 2020 +0300 +++ b/tools/lib64fmts.c Fri May 15 02:46:53 2020 +0300 @@ -63,6 +63,213 @@ } +static const Uint8 fmtSupeRes_MagicID_1[] = +{ + 0x40, 0x5c, 0x2a, +}; + + +static int fmtProbeSupeRes(const DMGrowBuf *buf, const DMC64ImageFormat *fmt) +{ + if (buf->len > 12 && + DM_MEMCMP_SIZE(buf->data, fmtSupeRes_MagicID_1) == 0) + { + if (buf->data[3] == fmt->size) + return DM_PROBE_SCORE_MAX; + } + + return DM_PROBE_SCORE_FALSE; +} + + +typedef struct +{ + DMGrowBuf src; + Uint8 *dstBuf; + size_t dstSize; + + Uint8 dbyte, repcount; + + size_t offs, end_offs; +} DMSupeResCtx; + + +static int fmtSupeResGetByte(DMSupeResCtx *ctx, Uint8 *data, const int mode) +{ + if (!dmGrowBufGetU8(&ctx->src, data)) + { + return dmError(DMERR_INVALID_DATA, + "SupeRes: Out of input data (N=%d).\n", + mode); + } + else + { + return DMERR_OK; + } +} + + +static int fmtDecodeSupeResByte(DMSupeResCtx *ctx) +{ + Uint8 tmp; + int res; + +lcont: + + if ((res = fmtSupeResGetByte(ctx, &tmp, 1)) != DMERR_OK) + goto out; + + if (tmp == 0x21) + { + // ???? + ctx->offs = 0xffff; + return DMERR_OK; + } + else + if (tmp == 0x24) + { + ctx->dbyte = 0xff; + return DMERR_OK; + } + else + if (tmp == 0x20) + { + if ((res = fmtSupeResGetByte(ctx, &tmp, 2)) != DMERR_OK) + goto out; + + ctx->repcount = tmp - 0x26; + + if ((res = fmtSupeResGetByte(ctx, &tmp, 3)) != DMERR_OK) + goto out; + + if (tmp == 0x24) + { + ctx->dbyte = 0xff; + } + else + { + if (tmp == 0x25) + { + if ((res = fmtSupeResGetByte(ctx, &tmp, 4)) != DMERR_OK) + goto out; + + tmp = (0x26 + tmp) & 0xff; + } + + ctx->dbyte = tmp - 0x26; + } + + for (int cnt = 0; cnt < ctx->repcount; cnt++) + { + ctx->dstBuf[ctx->offs++] = ctx->dbyte; + if (ctx->offs >= ctx->end_offs) + goto out; + } + + if (ctx->offs < ctx->end_offs) + goto lcont; + + ctx->offs--; + + goto out; + } + else + { + if (tmp == 0x25) + { + if ((res = fmtSupeResGetByte(ctx, &tmp, 9)) != DMERR_OK) + goto out; + + tmp = (0x26 + tmp) & 0xff; + } + + ctx->dbyte = tmp - 0x26; + + return DMERR_OK; + } + + goto lcont; + +out: + return res; +} + + +static int fmtDecodeSupeResSection(DMSupeResCtx *ctx, const size_t offs, const size_t size) +{ + int res = DMERR_OK; + + ctx->offs = offs; + ctx->end_offs = offs + size; + + do + { + if ((res = fmtDecodeSupeResByte(ctx)) != DMERR_OK) + goto out; + + if (ctx->offs < ctx->end_offs) + ctx->dstBuf[ctx->offs++] = ctx->dbyte; + + } while (ctx->offs < ctx->end_offs); + +out: + return res; +} + + +static int fmtDecodeSupeRes(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt) +{ + DMSupeResCtx ctx; + DMGrowBuf tmp; + int res; + + memset(&ctx, 0, sizeof(ctx)); + ctx.dstSize = 0x4000; + + // As we need to modify the offs, etc. but not the data, + // we will just make a shallow copy of the DMGrowBuf struct + dmGrowBufConstCopyOffs(&ctx.src, psrc, 4); + + // Allocate output buffer + if ((ctx.dstBuf = dmMalloc0(ctx.dstSize)) == NULL) + { + return dmError(DMERR_MALLOC, + "Could not allocate memory for decoding buffer.\n"); + } + + switch (fmt->size) + { + case 0x23: + case 0x25: + if ((res = fmtDecodeSupeResSection(&ctx, 0x0000, 0x03e8)) != DMERR_OK || + (res = fmtDecodeSupeResSection(&ctx, 0x0400, 0x1f40)) != DMERR_OK) + goto out; + break; + + case 0x24: + case 0x26: + if ((res = fmtDecodeSupeResByte (&ctx)) != DMERR_OK) + goto out; + + ctx.dstBuf[0x2710] = ctx.dbyte; + + if ((res = fmtDecodeSupeResSection(&ctx, 0x1f40, 0x03e8)) != DMERR_OK || + (res = fmtDecodeSupeResSection(&ctx, 0x2328, 0x03e8)) != DMERR_OK || + (res = fmtDecodeSupeResSection(&ctx, 0x0000, 0x1f40)) != DMERR_OK) + goto out; + + break; + } + + res = dmC64DecodeGenericBMP(img, + dmGrowBufConstCreateFrom(&tmp, ctx.dstBuf, ctx.dstSize), fmt); + +out: + dmFree(ctx.dstBuf); + return res; +} + + static const Uint8 fmtMarqPETSCII_ID1[] = { 0x01, 0x08, 0x0b, 0x08, 0xef, 0x00, 0x9e, 0x32, 0x30, 0x36, @@ -2874,6 +3081,33 @@ NULL }, + { + "suphi1", "SupeRes hires [clear] (packed)", -1, 0x23, DM_FMT_RD, + fmtProbeSupeRes, + fmtDecodeSupeRes, NULL, + { }, &dmC64CommonFormats[10] + }, + + { + "suphi2", "SupeRes hires [no-clear] (packed)", -1, 0x25, DM_FMT_RD, + fmtProbeSupeRes, + fmtDecodeSupeRes, NULL, + { }, &dmC64CommonFormats[10] + }, + + { + "supmc1", "SupeRes multicolor [clear] (packed)", -1, 0x24, DM_FMT_RD, + fmtProbeSupeRes, + fmtDecodeSupeRes, NULL, + { }, &dmC64CommonFormats[0] + }, + + { + "supmc2", "SupeRes multicolor [no-clear] (packed)", -1, 0x26, DM_FMT_RD, + fmtProbeSupeRes, + fmtDecodeSupeRes, NULL, + { }, &dmC64CommonFormats[0] + }, }; const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]);