# HG changeset patch # User Matti Hamalainen # Date 1589517852 -10800 # Node ID 19b0ca169361c18a6bd0f3088ef2c5a61dcae069 # Parent 5a7e2aa8fef564e2d593f9ec8c1c193721721001 Implement SupeRes encoding. diff -r 5a7e2aa8fef5 -r 19b0ca169361 tools/lib64fmts.c --- a/tools/lib64fmts.c Fri May 15 04:04:57 2020 +0300 +++ b/tools/lib64fmts.c Fri May 15 07:44:12 2020 +0300 @@ -261,6 +261,126 @@ } +typedef struct +{ + DMGrowBuf *buf; + + int cnt1, cnt2, dbyte; +} DMSupeResEncCtx; + + +static BOOL fmtEncodeSupeResRun(DMSupeResEncCtx *ctx) +{ + if (ctx->cnt2 == 255) + ctx->cnt2 = 0x24; + else + if (ctx->cnt2 > 216) + { + if (!dmGrowBufPutU8(ctx->buf, 0x25)) + return FALSE; + } + else + ctx->cnt2 += 0x26; + + if (!dmGrowBufPutU8(ctx->buf, ctx->cnt2)) + return FALSE; + + ctx->cnt1 = ctx->cnt2 = 0; + + return TRUE; +} + + +static BOOL fmtEncodeSupeResFlush(DMSupeResEncCtx *ctx) +{ + ctx->cnt1 += 0x26; + + if (!dmGrowBufPutU8(ctx->buf, 0x20) || + !dmGrowBufPutU8(ctx->buf, ctx->cnt1)) + return FALSE; + + return fmtEncodeSupeResRun(ctx); +} + + +static BOOL fmtEncodeSupeResSection(DMSupeResEncCtx *ctx, const DMC64MemBlock *blk) +{ + for (size_t offs = 0; offs < blk->size; offs++) + { + ctx->dbyte = blk->data[offs]; + + if ((ctx->cnt1 == 0 && offs + 1 < blk->size && ctx->dbyte == blk->data[offs + 1]) || + (ctx->cnt1 != 0 && ctx->dbyte == ctx->cnt2)) + { + ctx->cnt1++; + ctx->cnt2 = ctx->dbyte; + + if (ctx->cnt1 >= 215 && + !fmtEncodeSupeResFlush(ctx)) + return FALSE; + + continue; + } + else + if (ctx->cnt1 != 0 && ctx->dbyte != ctx->cnt2) + { + if (!fmtEncodeSupeResFlush(ctx)) + return FALSE; + } + + ctx->cnt2 = ctx->dbyte; + + if (!fmtEncodeSupeResRun(ctx)) + return FALSE; + } + + if (ctx->cnt1 > 0) + return fmtEncodeSupeResFlush(ctx); + + return TRUE; +} + + +static int fmtEncodeSupeRes(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt) +{ + DMSupeResEncCtx ctx; + BOOL bres; + + // Output magic header and data type + if (!dmGrowBufPut(buf, fmtSupeRes_MagicID_1, sizeof(fmtSupeRes_MagicID_1)) || + !dmGrowBufPutU8(buf, fmt->extra)) + { + return dmError(DMERR_MALLOC, + "Error outputting SupeRes magic header.\n"); + } + + memset(&ctx, 0, sizeof(ctx)); + ctx.buf = buf; + + switch (fmt->extra) + { + case 0x23: + case 0x25: + bres = + fmtEncodeSupeResSection(&ctx, &img->screen[0]) && + fmtEncodeSupeResSection(&ctx, &img->bitmap[0]); + break; + + case 0x24: + case 0x26: + ctx.cnt2 = img->bgcolor; + bres = + fmtEncodeSupeResRun(&ctx) && + fmtEncodeSupeResSection(&ctx, &img->screen[0]) && + fmtEncodeSupeResSection(&ctx, &img->color[0]) && + fmtEncodeSupeResSection(&ctx, &img->bitmap[0]); + break; + } + + return bres ? DMERR_OK : DMERR_MALLOC; +} + + static const Uint8 fmtMarqPETSCII_ID1[] = { 0x01, 0x08, 0x0b, 0x08, 0xef, 0x00, 0x9e, 0x32, 0x30, 0x36, @@ -3072,30 +3192,30 @@ }, { - "suphi1", "SupeRes hires [clear] (packed)", -1, 0, 0x23, DM_FMT_RD, + "suphi1", "SupeRes hires [clear] (packed)", -1, 0, 0x23, DM_FMT_RDWR, fmtProbeSupeRes, - fmtDecodeSupeRes, NULL, + fmtDecodeSupeRes,fmtEncodeSupeRes, { }, &dmC64CommonFormats[10] }, { - "suphi2", "SupeRes hires [no-clear] (packed)", -1, 0, 0x25, DM_FMT_RD, + "suphi2", "SupeRes hires [no-clear] (packed)", -1, 0, 0x25, DM_FMT_RDWR, fmtProbeSupeRes, - fmtDecodeSupeRes, NULL, + fmtDecodeSupeRes,fmtEncodeSupeRes, { }, &dmC64CommonFormats[10] }, { - "supmc1", "SupeRes multicolor [clear] (packed)", -1, 0, 0x24, DM_FMT_RD, + "supmc1", "SupeRes multicolor [clear] (packed)", -1, 0, 0x24, DM_FMT_RDWR, fmtProbeSupeRes, - fmtDecodeSupeRes, NULL, + fmtDecodeSupeRes,fmtEncodeSupeRes, { }, &dmC64CommonFormats[0] }, { - "supmc2", "SupeRes multicolor [no-clear] (packed)", -1, 0, 0x26, DM_FMT_RD, + "supmc2", "SupeRes multicolor [no-clear] (packed)", -1, 0, 0x26, DM_FMT_RDWR, fmtProbeSupeRes, - fmtDecodeSupeRes, NULL, + fmtDecodeSupeRes,fmtEncodeSupeRes, { }, &dmC64CommonFormats[0] }, };