Mercurial > hg > dmlib
changeset 1707:a0986cfd6f9d
More consistently use DMGrowBuf in the lib64gfx APIs, and implement
"backwards" RLE decoding and encoding (optionally regards input/output).
Not tested very much yet, there may be bugs.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2018 21:58:10 +0300 |
parents | 311b14855a1e |
children | 55db8d6dffa5 |
files | src/dmgrowbuf.c tools/64vw.c tools/gfxconv.c tools/lib64fmts.c tools/lib64gfx.c tools/lib64gfx.h |
diffstat | 6 files changed, 201 insertions(+), 170 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dmgrowbuf.c Tue Jun 05 19:57:08 2018 +0300 +++ b/src/dmgrowbuf.c Tue Jun 05 21:58:10 2018 +0300 @@ -218,7 +218,9 @@ return FALSE; } - buf->len = nsize; + if (nsize > buf->len) + buf->len = nsize; + return TRUE; }
--- a/tools/64vw.c Tue Jun 05 19:57:08 2018 +0300 +++ b/tools/64vw.c Tue Jun 05 21:58:10 2018 +0300 @@ -180,12 +180,13 @@ { Uint8 *dataBuf = NULL; size_t dataSize; + DMGrowBuf tmp; int ret; if ((ret = dmReadDataFile(NULL, filename, &dataBuf, &dataSize)) != DMERR_OK) goto exit; - ret = dmC64DecodeBMP(cimage, dataBuf, dataSize, 0, 2, fmt, forced); + ret = dmC64DecodeBMP(cimage, dmGrowBufCreateFrom(&tmp, dataBuf, dataSize), 0, 2, fmt, forced); exit: dmFree(dataBuf);
--- a/tools/gfxconv.c Tue Jun 05 19:57:08 2018 +0300 +++ b/tools/gfxconv.c Tue Jun 05 21:58:10 2018 +0300 @@ -1686,7 +1686,7 @@ // Check and compute the input skip if (optInSkip > dataSizeOrig) { - dmErrorMsg("Input skip value %d is larger than input size %d.\n", + dmErrorMsg("Input skip value %d is larger than input size %" DM_PRIu_SIZE_T ".\n", optInSkip, dataSizeOrig); goto error; } @@ -1694,12 +1694,12 @@ dataBuf = dataBufOrig + optInSkip; dataSize = dataSizeOrig - optInSkip; - // Perform probing, if required if (optInFormat == FFMT_AUTO || optInFormat == FFMT_BITMAP) { // Probe for format const DMC64ImageFormat *forced = NULL; + DMGrowBuf tbuf; int res; if (optForcedFormat >= 0) @@ -1709,7 +1709,7 @@ forced->name, forced->type, forced->fext); } - res = dmC64DecodeBMP(&inC64Image, dataBuf, dataSize, optInSkip, optInSkip + 2, &inC64Fmt, forced); + res = dmC64DecodeBMP(&inC64Image, dmGrowBufCreateFrom(&tbuf, dataBuf, dataSize), 0, 2, &inC64Fmt, forced); if (forced == NULL && inC64Fmt != NULL && res == DMERR_OK) { dmMsg(1, "Probed '%s' format image, type %d, %s\n",
--- a/tools/lib64fmts.c Tue Jun 05 19:57:08 2018 +0300 +++ b/tools/lib64fmts.c Tue Jun 05 21:58:10 2018 +0300 @@ -31,7 +31,6 @@ }; - static int fmtProbeKoalaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) { // Attempt to prevent misprobes of unpacked Koala and Run Paint @@ -45,7 +44,7 @@ } -static int fmtDecodeKoalaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeKoalaPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; DMGrowBuf mem; @@ -54,10 +53,11 @@ cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_2; cfg.rleMarkerB = 0xfe; - if ((res = dmDecodeGenericRLEAlloc(&mem, buf, buf + len, &cfg)) != DMERR_OK) + + if ((res = dmDecodeGenericRLEAlloc(&mem, buf, &cfg)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); + res = dmC64DecodeGenericBMP(img, &mem, fmt); out: dmGrowBufFree(&mem); @@ -81,7 +81,7 @@ cfg.rleMarkerB = 0xfe; cfg.rleMinCountB = 3; cfg.rleMaxCountB = 255; - res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg); + res = dmEncodeGenericRLE(buf, &tmp, &cfg); out: dmGrowBufFree(&tmp); @@ -105,20 +105,21 @@ } -static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeDrazPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; - DMGrowBuf mem; + DMGrowBuf mem, tmp; DMCompParams cfg; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; - cfg.rleMarkerB = buf[0x0d]; + cfg.rleMarkerB = buf->data[0x0d]; - if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 0x0e, buf + len, &cfg)) != DMERR_OK) + if ((res = dmDecodeGenericRLEAlloc(&mem, + dmGrowBufCreateFromOffs(&tmp, buf, 0x0e), &cfg)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); + res = dmC64DecodeGenericBMP(img, &mem, fmt); out: dmGrowBufFree(&mem); @@ -143,7 +144,7 @@ cfg.rleMinCountB = 3; cfg.rleMaxCountB = 255; - dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg); + dmGenericRLEAnalyze(&tmp, &cfg); // Add the header bits if (!dmGrowBufPut(buf, (Uint8 *) magicID, strlen(magicID)) || @@ -154,7 +155,7 @@ } // And now RLE compress the data to the existing buffer - res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg); + res = dmEncodeGenericRLE(buf, &tmp, &cfg); out: dmGrowBufFree(&tmp); @@ -174,11 +175,10 @@ static BOOL fmtDrazLaceGetLaceType(DMC64Image *img, const DMC64EncDecOp *op, - const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) + const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { - (void) len; (void) fmt; - img->laceType = buf[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR; + img->laceType = buf->data[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR; return TRUE; } @@ -205,21 +205,22 @@ } -static int fmtDecodeBDP5Packed(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeBDP5Packed(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; - DMGrowBuf mem; + DMGrowBuf mem, tmp; DMCompParams cfg; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_WORD_RUNS | DM_RLE_ORDER_1; - cfg.rleMarkerB = buf[8]; - cfg.rleMarkerW = buf[9]; + cfg.rleMarkerB = buf->data[8]; + cfg.rleMarkerW = buf->data[9]; - if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 10, buf + len, &cfg)) != DMERR_OK) + if ((res = dmDecodeGenericRLEAlloc(&mem, + dmGrowBufCreateFromOffs(&tmp, buf, 10), &cfg)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); + res = dmC64DecodeGenericBMP(img, &mem, fmt); out: dmGrowBufFree(&mem); @@ -230,11 +231,11 @@ static int fmtEncodeBDP5Packed(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt) { int res; - DMGrowBuf tmp; + DMGrowBuf mem; DMCompParams cfg; // Encode the data to temp buffer - if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK) + if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK) goto out; // Analyze and setup RLE @@ -245,7 +246,7 @@ cfg.rleMinCountW = 256; cfg.rleMaxCountW = 1024; - dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg); + dmGenericRLEAnalyze(&mem, &cfg); // Add the header bits if (!dmGrowBufPut(buf, (Uint8 *) fmtBDP5MagicID, strlen(fmtBDP5MagicID)) || @@ -257,10 +258,10 @@ } // And now RLE compress the data to the existing buffer - res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg); + res = dmEncodeGenericRLE(buf, &mem, &cfg); out: - dmGrowBufFree(&tmp); + dmGrowBufFree(&mem); return res; } @@ -302,7 +303,7 @@ } -static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; DMGrowBuf mem, tmp; @@ -310,22 +311,22 @@ // Amica Paint apparently is broken and stores one byte less than it should // so we need to do some crappy buffer expansion here .. - if ((res = dmGrowBufAlloc(&tmp, len + 4, 4)) != DMERR_OK) + if ((res = dmGrowBufAlloc(&tmp, buf->len + 4, 4)) != DMERR_OK) return res; - memcpy(tmp.data, buf, len); - tmp.len = len + 1; + memcpy(tmp.data, buf->data, buf->len); + tmp.len = buf->len + 1; // Now do an RLE decode on the enlarged buffer cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; cfg.rleMarkerB = 0xC2; - if ((res = dmDecodeGenericRLEAlloc(&mem, tmp.data, tmp.data + tmp.len, &cfg)) != DMERR_OK) + if ((res = dmDecodeGenericRLEAlloc(&mem, &tmp, &cfg)) != DMERR_OK) goto out; // And finally decode to bitmap struct - res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); + res = dmC64DecodeGenericBMP(img, &mem, fmt); out: dmGrowBufFree(&tmp); @@ -337,11 +338,11 @@ static int fmtEncodeAmicaPaintPacked(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt) { int res; - DMGrowBuf tmp; + DMGrowBuf mem; DMCompParams cfg; // Encode the data to temp buffer - if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK) + if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK) goto out; // And now RLE compress the data to the existing buffer @@ -351,10 +352,10 @@ cfg.rleMinCountB = 3; cfg.rleMaxCountB = 255; - res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg); + res = dmEncodeGenericRLE(buf, &mem, &cfg); out: - dmGrowBufFree(&tmp); + dmGrowBufFree(&mem); return res; } @@ -370,11 +371,10 @@ static BOOL fmtTruePaintGetLaceType(DMC64Image *img, const DMC64EncDecOp *op, - const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) + const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { (void) op; (void) buf; - (void) len; (void) fmt; img->laceType = D64_ILACE_RES; return TRUE; @@ -427,10 +427,11 @@ } -static int fmtDecodeTruePaintPacked(DMC64Image *img, const Uint8 *src, const size_t srcLen, const DMC64ImageFormat *fmt) +static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *src, const DMC64ImageFormat *fmt) { int res = DMERR_OK; Uint8 *dst = NULL; + DMGrowBuf dstTmp; const Uint8 *codeBook1, *codeBook2; size_t srcOffs, dstOffs, @@ -439,8 +440,8 @@ // 1c00-67e8 is the actual area used tho // Codebooks: #1 is trampoline table markers, #2 is RLE data table - codeBook1 = src + 0x81 - 2; - codeBook2 = src + 0x85 - 2; + codeBook1 = src->data + 0x81 - 2; + codeBook2 = src->data + 0x85 - 2; // Allocate output buffer if ((dst = dmMalloc0(dstLen)) == NULL) @@ -451,7 +452,7 @@ } // Begin decompression - srcOffs = srcLen; + srcOffs = src->len; dstOffs = dstLen; while (srcOffs > 0 && dstOffs > 0) @@ -460,7 +461,7 @@ int count = 1, scount; BOOL found = FALSE; - if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, -1)) + if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, -1)) goto out; for (int n = 0; n < 8; n++) @@ -470,7 +471,7 @@ switch (n) { case 4: // Y = 4, JTO = $0B - if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n)) + if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) goto out; count = data; @@ -484,12 +485,12 @@ // fallthrough case 0: // Y = 0, JTO = $19 - if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n)) + if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) goto out; break; case 2: // Y = 2, JTO = $07 - if (!fmtTruePaintGetByte(src, &srcOffs, &data, &res, n)) + if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) goto out; count = data; @@ -520,7 +521,7 @@ } finish: - res = dmC64DecodeGenericBMP(img, dst, dstLen, fmt); + res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&dstTmp, dst, dstLen), fmt); out: dmFree(dst); @@ -545,20 +546,21 @@ } -static int fmtDecodeFormatXX2(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeFormatXX2(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; + DMGrowBuf tmp; // If there is only data for less than XX2_MIN_SIZE bytes, // allocate a buffer of that size and copy data there. // Otherwise allocate len bytes. - size_t nlen = len < XX2_MIN_SIZE ? XX2_MIN_SIZE : len; + size_t nlen = buf->len < XX2_MIN_SIZE ? XX2_MIN_SIZE : buf->len; Uint8 *mem = dmMalloc0(nlen); if (mem == NULL) return DMERR_MALLOC; - memcpy(mem, buf, len); - res = dmC64DecodeGenericBMP(img, mem, nlen, fmt); + memcpy(mem, buf->data, buf->len); + res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&tmp, mem, nlen), fmt); dmFree(mem); return res; @@ -580,29 +582,30 @@ } -static int fmtDecodeFunPaint2(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +static int fmtDecodeFunPaint2(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res; + DMGrowBuf tmp; // Check if the data is compressed - if (buf[14]) + if (buf->data[14]) { DMGrowBuf mem; DMCompParams cfg; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; - cfg.rleMarkerB = buf[15]; + cfg.rleMarkerB = buf->data[15]; if ((res = dmDecodeGenericRLEAlloc( - &mem, buf + FUNPAINT2_HEADER_SIZE, buf + len, &cfg)) == DMERR_OK) - res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); + &mem, dmGrowBufCreateFromOffs(&tmp, buf, FUNPAINT2_HEADER_SIZE), &cfg)) == DMERR_OK) + res = dmC64DecodeGenericBMP(img, &mem, fmt); dmGrowBufFree(&mem); } else { - res = dmC64DecodeGenericBMP(img, buf + FUNPAINT2_HEADER_SIZE, len - FUNPAINT2_HEADER_SIZE, fmt); + res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFromOffs(&tmp, buf, FUNPAINT2_HEADER_SIZE), fmt); } return res; @@ -623,11 +626,11 @@ static int fmtEncodeFunPaint2Packed(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt) { int res; - DMGrowBuf tmp; + DMGrowBuf mem; DMCompParams cfg; // Encode the data to temp buffer - if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK) + if ((res = dmC64EncodeGenericBMP(TRUE, &mem, img, fmt)) != DMERR_OK) goto out; // Analyze and setup RLE @@ -636,7 +639,7 @@ cfg.rleMinCountB = 3; cfg.rleMaxCountB = 255; - dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg); + dmGenericRLEAnalyze(&mem, &cfg); // Add the header bits if (!dmGrowBufPut(buf, (Uint8 *) fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) || @@ -647,10 +650,10 @@ } // And now RLE compress the data to the existing buffer - res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len, &cfg); + res = dmEncodeGenericRLE(buf, &mem, &cfg); out: - dmGrowBufFree(&tmp); + dmGrowBufFree(&mem); return res; } @@ -1173,6 +1176,7 @@ { DO_COPY , DS_SCREEN_RAM , 0x2000, 0, 0, NULL, NULL }, { DO_COPY , DS_COLOR_RAM , 0x2400, 0, 0, NULL, NULL }, { DO_SET_OP , DS_BGCOL , 0x00 , 0, 0, NULL, NULL }, + { DO_SET_OP , DS_EXTRA_DATA , 10240 , 0, 0, NULL, NULL }, { DO_LAST , 0 , 0 , 0, 0, NULL, NULL }, }, NULL
--- a/tools/lib64gfx.c Tue Jun 05 19:57:08 2018 +0300 +++ b/tools/lib64gfx.c Tue Jun 05 21:58:10 2018 +0300 @@ -282,7 +282,7 @@ } -void dmGenericRLEAnalyze(const Uint8 *buf, const size_t len, DMCompParams *cfg) +void dmGenericRLEAnalyze(const DMGrowBuf *buf, DMCompParams *cfg) { #define DM_STAT_MAX 256 size_t *stats; @@ -292,8 +292,8 @@ return; // Get statistics on the data - for (size_t offs = 0; offs < len; offs++) - stats[buf[offs]]++; + for (size_t offs = 0; offs < buf->len; offs++) + stats[buf->data[offs]]++; // According to compression type .. switch (cfg->type) @@ -301,7 +301,7 @@ case DM_COMP_RLE_MARKER: { size_t selected = 0, - smallest = len; + smallest = buf->len; // Find least used byte value for (size_t n = 0; n < DM_STAT_MAX; n++) @@ -327,63 +327,83 @@ } -int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg) +static void dmSetupRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg) +{ + if (cfg->flags & DM_RLE_BACKWARDS_INPUT) + { + src->offs = src->len - 1; + src->backwards = TRUE; + } + + if (cfg->flags & DM_RLE_BACKWARDS_OUTPUT) + { + dst->backwards = TRUE; + dst->offs = dst->size - 1; + } +} + + +int dmDecodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *psrc, const DMCompParams *cfg) { int res; + Uint8 tmp1, tmp2, tmp3, data; + DMGrowBuf src; - // Perform RLE decode - while (src < srcEnd) + // As we need to modify the offs, etc. but not the data, + // we will just make a shallow copy of the DMGrowBuf struct + dmGrowBufConstCopy(&src, psrc); + dmSetupRLEBuffers(dst, &src, cfg); + + while (dmGrowBufGetU8(&src, &data)) { - Uint8 data = *src++; - int count = 1; + unsigned int count = 1; if (cfg->type == DM_COMP_RLE_MARKER) { // A simple marker byte RLE variant: [Marker] [count] [data] if (data == cfg->rleMarkerB && (cfg->flags & DM_RLE_BYTE_RUNS)) { - if (srcEnd - src + 1 < 2) + if (!dmGrowBufGetU8(&src, &tmp1) || + !dmGrowBufGetU8(&src, &tmp2)) { res = DMERR_INVALID_DATA; - goto err; + goto out; } - switch (cfg->flags & DM_RLE_ORDER_MASK) { case DM_RLE_ORDER_1: - count = src[0]; - data = src[1]; + count = tmp1; + data = tmp2; break; case DM_RLE_ORDER_2: - data = src[0]; - count = src[1]; + data = tmp1; + count = tmp2; break; } - src += 2; } else if (data == cfg->rleMarkerW && (cfg->flags & DM_RLE_WORD_RUNS)) { - if (srcEnd - src + 1 < 3) + if (!dmGrowBufGetU8(&src, &tmp1) || + !dmGrowBufGetU8(&src, &tmp2) || + !dmGrowBufGetU8(&src, &tmp3)) { res = DMERR_INVALID_DATA; - goto err; + goto out; } - switch (cfg->flags & DM_RLE_ORDER_MASK) { case DM_RLE_ORDER_1: - count = (src[1] << 8) | src[0]; - data = src[2]; + count = (tmp2 << 8) | tmp1; + data = tmp3; break; case DM_RLE_ORDER_2: - data = src[0]; - count = (src[2] << 8) | src[1]; + data = tmp1; + count = (tmp3 << 8) | tmp2; break; } - src += 3; } } else @@ -393,14 +413,14 @@ // and the lower bits contain the count: [Mask + count] [data] if ((data & cfg->rleMarkerMask) == cfg->rleMarkerBits) { - if (srcEnd - src + 1 < 1) + if (!dmGrowBufGetU8(&src, &tmp1)) { res = DMERR_INVALID_DATA; - goto err; + goto out; } count = data & cfg->rleCountMask; - data = *src++; + data = tmp1; } } @@ -409,29 +429,29 @@ if (!dmGrowBufPutU8(dst, data)) { res = DMERR_MALLOC; - goto err; + goto out; } } } res = DMERR_OK; -err: +out: return res; } -int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg) +int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg) { int res; if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) return res; - return dmDecodeGenericRLE(dst, src, srcEnd, cfg); + return dmDecodeGenericRLE(dst, src, cfg); } -static BOOL dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, int count, const DMCompParams *cfg) +static BOOL dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, unsigned int count, const DMCompParams *cfg) { BOOL copyOnly = FALSE; @@ -514,14 +534,20 @@ } -int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg) +int dmEncodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *psrc, const DMCompParams *cfg) { - // Perform RLE encoding - int count = 0, prev = -1; - while (src < srcEnd) + DMGrowBuf src; + unsigned int count = 0; + int prev = -1; + Uint8 data; + + // As we need to modify the offs, etc. but not the data, + // we will just make a shallow copy of the DMGrowBuf struct + dmGrowBufConstCopy(&src, psrc); + dmSetupRLEBuffers(dst, &src, cfg); + + while (dmGrowBufGetU8(&src, &data)) { - Uint8 data = *src++; - // If new data byte is different, or we exceed the rleMaxCount // for the active runs mode(s) .. then encode the run. if (data != prev || @@ -546,17 +572,17 @@ err: return dmError(DMERR_MALLOC, - "Could reallocate memory for RLE encoding buffer.\n"); + "Could not reallocate memory for RLE encoding buffer.\n"); } -int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg) +int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg) { int res; if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) return res; - return dmEncodeGenericRLE(dst, src, srcEnd, cfg); + return dmEncodeGenericRLE(dst, src, cfg); } @@ -707,12 +733,11 @@ } -int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, - const size_t len, const DMC64ImageFormat *fmt) +int dmC64DecodeGenericBMP(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { int res = DMERR_OK; - if (buf == NULL || img == NULL || fmt == NULL) + if (buf == NULL || buf->data == NULL || img == NULL || fmt == NULL) return DMERR_NULLPTR; // Clear the image structure, set basics @@ -751,15 +776,16 @@ } // Is the operation inside the bounds? - if (op->offs + size > len + 1) + if (op->offs + size > buf->len + 1) { return dmError(DMERR_INVALID_DATA, "Decode DATA out of bounds, op #%d type=%d, subj=%d, offs=%d ($%04x), " "bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->type, op->subject, op->offs, op->offs, op->bank, size, size, len, len); + i, op->type, op->subject, op->offs, op->offs, op->bank, + size, size, buf->len, buf->len); } - src = buf + op->offs; + src = buf->data + op->offs; // Perform operation switch (op->type) @@ -781,7 +807,7 @@ return dmError(DMERR_MALLOC, "Could not allocate '%s' block! " "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - blkname, i, op->offs, op->offs, op->bank, size, size, len, len); + blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); } switch (op->type) { @@ -832,7 +858,7 @@ return dmError(DMERR_INTERNAL, "Unhandled subject %d in " "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - op->subject, i, op->offs, op->offs, op->bank, size, size, len, len); + op->subject, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); } break; @@ -854,7 +880,7 @@ return dmError(DMERR_INTERNAL, "Unhandled DO_CHAR_CFG mode %d in ", "op #%d, bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - op->subject, i, op->bank, size, size, len, len); + op->subject, i, op->bank, size, size, buf->len, buf->len); } break; @@ -864,14 +890,14 @@ return dmError(DMERR_INTERNAL, "Decode op is a function, but function ptr is NULL: " "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, len, len); + i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); } - if (!op->decFunction(img, op, buf, len, fmt)) + if (!op->decFunction(img, op, buf, fmt)) { return dmError(DMERR_INTERNAL, "Decode op custom function failed: op #%d, " "offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, len, len); + i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); } break; } @@ -935,7 +961,7 @@ res = dmError(DMERR_INVALID_DATA, "Encode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), " "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n", - i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size); + i, op->type, op->offs, op->offs, op->bank, size, size, buf->size, buf->size); goto err; } @@ -949,9 +975,6 @@ goto err; } - if (chksize > buf->len) - buf->len = chksize; - // Perform operation Uint8 *dst = buf->data + buf->offs + op->offs; switch (op->type) @@ -967,35 +990,31 @@ case DS_CHAR_DATA: case DS_EXTRA_DATA: dmC64GetOpMemBlockAndName(img, op->subject, op->bank, &blk, &blkname); - if (blk->data == NULL) - { - res = dmError(DMERR_NULLPTR, - "'%s' block is NULL in " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); - goto err; - } - if (size > blk->size) - { - res = dmError(DMERR_INTERNAL, - "'%s' size mismatch %d <> %d in " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); - goto err; - } switch (op->type) { case DO_COPY: + if (blk->data == NULL) + { + res = dmError(DMERR_NULLPTR, + "'%s' block is NULL in " + "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); + goto err; + } + if (size > blk->size) + { + res = dmError(DMERR_INTERNAL, + "'%s' size mismatch %d <> %d in " + "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); + goto err; + } memcpy(dst, blk->data, size); break; case DO_SET_MEM: - // This operation makes no sense - res = dmError(DMERR_INTERNAL, - "'%s' block DO_SET_MEM (which makes no sense) in " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); - goto err; + // This operation makes no sense, so do nothing + break; case DO_SET_OP: memset(dst, op->offs, size); @@ -1026,12 +1045,8 @@ break; case DO_SET_OP: - // This operation makes no sense - res = dmError(DMERR_INTERNAL, - "'%s' block DO_SET_OP (which makes no sense) in " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); - goto err; + // Do nothing in this case + break; } break; @@ -1234,11 +1249,13 @@ } -int dmC64DecodeBMP(DMC64Image **img, const Uint8 *buf, const size_t len, +int dmC64DecodeBMP(DMC64Image **img, const DMGrowBuf *buf, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced) { - if (img == NULL) + DMGrowBuf tmp; + + if (img == NULL || buf == NULL) return DMERR_NULLPTR; // Check for forced format @@ -1247,19 +1264,21 @@ else { // Nope, perform a generic probe - if (probeOffs >= len) + if (probeOffs >= buf->len) return DMERR_OUT_OF_DATA; - if (dmC64ProbeBMP(buf + probeOffs, len - probeOffs, fmt) == DM_PROBE_SCORE_FALSE) + dmGrowBufCreateFromOffs(&tmp, buf, probeOffs); + if (dmC64ProbeBMP(tmp.data, tmp.len, fmt) == DM_PROBE_SCORE_FALSE) return DMERR_NOT_SUPPORTED; } - if (loadOffs >= len) + if (loadOffs >= tmp.len) return DMERR_INVALID_ARGS; if (*fmt == NULL) return DMERR_NOT_SUPPORTED; + // Format supports only reading? if (((*fmt)->flags & DM_FMT_RD) == 0) return DMERR_NOT_SUPPORTED; @@ -1267,11 +1286,13 @@ if ((*img = dmC64ImageAlloc(*fmt)) == NULL) return DMERR_MALLOC; + dmGrowBufCreateFromOffs(&tmp, buf, loadOffs); + // Decode the bitmap to memory layout if ((*fmt)->decode != NULL) - return (*fmt)->decode(*img, buf + loadOffs, len - loadOffs, *fmt); + return (*fmt)->decode(*img, &tmp, *fmt); else - return dmC64DecodeGenericBMP(*img, buf + loadOffs, len - loadOffs, *fmt); + return dmC64DecodeGenericBMP(*img, &tmp, *fmt); }
--- a/tools/lib64gfx.h Tue Jun 05 19:57:08 2018 +0300 +++ b/tools/lib64gfx.h Tue Jun 05 21:58:10 2018 +0300 @@ -175,7 +175,7 @@ int bank; size_t size; - BOOL (*decFunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt); + BOOL (*decFunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const DMGrowBuf *buf, const DMC64ImageFormat *fmt); BOOL (*encFunction)(const struct _DMC64EncDecOp *op, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt); } DMC64EncDecOp; @@ -199,7 +199,7 @@ int (*probe)(const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); - int (*decode)(DMC64Image *img, const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); + int (*decode)(DMC64Image *img, const DMGrowBuf *buf, const struct _DMC64ImageFormat *fmt); int (*encode)(DMGrowBuf *buf, const DMC64Image *img, const struct _DMC64ImageFormat *fmt); int (*convertFrom)(DMImage *, const DMC64Image *, const struct _DMC64ImageFormat *fmt); @@ -229,6 +229,9 @@ DM_RLE_ORDER_1 = 0x0000, // Order: <marker>, <count/run length>, <data> DM_RLE_ORDER_2 = 0x0010, // Order: <marker>, <data>, <count/run length> DM_RLE_ORDER_MASK = 0x00f0, + + DM_RLE_BACKWARDS_INPUT = 0x1000, + DM_RLE_BACKWARDS_OUTPUT = 0x2000, }; @@ -246,7 +249,7 @@ rleMarkerMask, // Mask bits for marker: data & rleMarkerMask == rleMarkerBits rleCountMask; // Mask bits for length: count = data & rleCountMask - int + unsigned int // Minimum and maximum run lengths rleMinCountB, rleMinCountW, @@ -292,25 +295,25 @@ int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **fmt); -int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt); +int dmC64DecodeGenericBMP(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt); int dmC64EncodeGenericBMP(const BOOL allocate, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt); int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt); int dmC64ConvertImage2BMP(DMC64Image **pdst, const DMImage *src, const DMC64ImageFormat *fmt); -int dmC64DecodeBMP(DMC64Image **img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); +int dmC64DecodeBMP(DMC64Image **img, const DMGrowBuf *buf, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); int dmC64EncodeBMP(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt); int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const DMC64ImageFormat *fmt); int dmC64ConvertGenericImage2BMP(DMC64Image *dst, const DMImage *src, const DMC64ImageFormat *fmt); -void dmGenericRLEAnalyze(const Uint8 *buf, const size_t len, DMCompParams *cfg); +void dmGenericRLEAnalyze(const DMGrowBuf *buf, DMCompParams *cfg); -int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg); -int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg); +int dmDecodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); +int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); -int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg); -int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const DMCompParams *cfg); +int dmEncodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); +int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); //