# HG changeset patch # User Matti Hamalainen # Date 1528486350 -10800 # Node ID 811b20de954cb5ba05c03b00b61277e0aa531e53 # Parent 245f45073f4c06e4594f9a33102ae39021ecc0cd# Parent eeb6a82b4654184ed0c34d12532f70b81ede812b Merge. diff -r 245f45073f4c -r 811b20de954c tools/64vw.c --- a/tools/64vw.c Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/64vw.c Fri Jun 08 22:32:30 2018 +0300 @@ -15,13 +15,14 @@ #define SET_SKIP_AMOUNT 10 -int optVFlags = 0; -int optScrWidth, optScrHeight; -int optForcedFormat = -1; -BOOL optProbeOnly = FALSE; -BOOL optListOnly = FALSE; -size_t noptFilenames1 = 0, noptFilenames2 = 0; -char **optFilenames = NULL; +int optVFlags = 0; +int optScrWidth, optScrHeight; +int optForcedFormat = -1; +BOOL optInfoOnly = FALSE, + optProbeOnly = FALSE, + optListOnly = FALSE; +size_t noptFilenames1 = 0, noptFilenames2 = 0; +char **optFilenames = NULL; static const DMOptArg optList[] = @@ -32,8 +33,9 @@ { 3, 'S', "scale", "Scale image by factor (1-10)", OPT_ARGREQ }, { 4, 'f', "format", "Force input format (see --formats)", OPT_ARGREQ }, { 5, 'F', "formats", "List supported input formats", OPT_NONE }, - { 6, 'p', "probe", "Probe only (no display)", OPT_NONE }, - { 7, 'l', "list", "Output list of files that were recognized (implies -p)", OPT_NONE }, + { 6, 'i', "info", "Print information only (no display)", OPT_NONE }, + { 7, 'l', "list", "Output list of files that were recognized (implies -i)", OPT_NONE }, + { 8, 'p', "probe", "Probe only (do not attempt to decode the image)", OPT_NONE }, }; const int optListN = sizeof(optList) / sizeof(optList[0]); @@ -143,6 +145,12 @@ case 6: if (dmVerbosity < 1) dmVerbosity = 1; + optInfoOnly = TRUE; + break; + + case 8: + if (dmVerbosity < 1) + dmVerbosity = 1; optProbeOnly = TRUE; break; @@ -186,7 +194,10 @@ if ((ret = dmReadDataFile(NULL, filename, &dataBuf, &dataSize)) != DMERR_OK) goto exit; - ret = dmC64DecodeBMP(cimage, dmGrowBufCreateFrom(&tmp, dataBuf, dataSize), 0, 2, fmt, forced); + if (optProbeOnly) + ret = dmC64ProbeBMP(dataBuf, dataSize, fmt) != DM_PROBE_SCORE_FALSE ? DMERR_OK : DMERR_NOT_SUPPORTED; + else + ret = dmC64DecodeBMP(cimage, dmGrowBufCreateFrom(&tmp, dataBuf, dataSize), 0, 2, fmt, forced); exit: dmFree(dataBuf); @@ -199,17 +210,23 @@ DMImage bmap; int ret; - bmap.size = surf->pitch * surf->h; - bmap.data = surf->pixels; - bmap.pitch = surf->pitch; - bmap.width = surf->w; - bmap.height = surf->h; + memset(&bmap, 0, sizeof(bmap)); + bmap.size = surf->pitch * surf->h; + bmap.data = surf->pixels; + bmap.pitch = surf->pitch; + bmap.width = surf->w; + bmap.height = surf->h; + bmap.ncolors = C64_NCOLORS; + bmap.constpal = TRUE; + bmap.pal = dmDefaultC64Palette; if (fmt->convertFrom != NULL) ret = fmt->convertFrom(&bmap, cimage, fmt); else ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt); + SDL_SetPaletteColors(surf->format->palette, (SDL_Color *) bmap.pal, 0, bmap.ncolors); + return ret; } @@ -262,8 +279,8 @@ else forced = NULL; - // If we are simply probing, no need to initialize SDL etc - if (optProbeOnly) + // If we are simply displaying file information, no need to initialize SDL etc + if (optInfoOnly || optProbeOnly) { for (size_t n = 0; n < noptFilenames2; n++) { @@ -474,7 +491,6 @@ goto exit; } - SDL_SetPaletteColors(surf->format->palette, (SDL_Color *)dmDefaultC64Palette, 0, C64_NCOLORS); if (texture != NULL) SDL_DestroyTexture(texture); diff -r 245f45073f4c -r 811b20de954c tools/gfxconv.c --- a/tools/gfxconv.c Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/gfxconv.c Fri Jun 08 22:32:30 2018 +0300 @@ -1791,7 +1791,6 @@ goto error; } - dmSetDefaultC64Palette(outImage); res = dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); break; @@ -1814,7 +1813,6 @@ goto error; } - dmSetDefaultC64Palette(outImage); res = dmWriteSpritesAndChars(optOutFilename, outImage, optOutFormat, optInMulticolor); break; diff -r 245f45073f4c -r 811b20de954c tools/lib64fmts.c --- a/tools/lib64fmts.c Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/lib64fmts.c Fri Jun 08 22:32:30 2018 +0300 @@ -9,27 +9,6 @@ #include "lib64gfx.h" -// Based on Pepto's palette, stolen from VICE -DMColor dmDefaultC64Palette[C64_NCOLORS] = -{ - { 0x00, 0x00, 0x00, 0xff }, - { 0xFF, 0xFF, 0xFF, 0xff }, - { 0x68, 0x37, 0x2B, 0xff }, - { 0x70, 0xA4, 0xB2, 0xff }, - { 0x6F, 0x3D, 0x86, 0xff }, - { 0x58, 0x8D, 0x43, 0xff }, - { 0x35, 0x28, 0x79, 0xff }, - { 0xB8, 0xC7, 0x6F, 0xff }, - { 0x6F, 0x4F, 0x25, 0xff }, - { 0x43, 0x39, 0x00, 0xff }, - { 0x9A, 0x67, 0x59, 0xff }, - { 0x44, 0x44, 0x44, 0xff }, - { 0x6C, 0x6C, 0x6C, 0xff }, - { 0x9A, 0xD2, 0x84, 0xff }, - { 0x6C, 0x5E, 0xB5, 0xff }, - { 0x95, 0x95, 0x95, 0xff }, -}; - static int fmtProbeKoalaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) { @@ -50,9 +29,10 @@ DMGrowBuf mem; DMCompParams cfg; - cfg.type = DM_COMP_RLE_MARKER; - cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_2; - cfg.rleMarkerB = 0xfe; + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_2; + cfg.rleMarkerB = 0xfe; if ((res = dmDecodeGenericRLEAlloc(&mem, buf, &cfg)) != DMERR_OK) goto out; @@ -76,6 +56,7 @@ goto out; // And now RLE compress the data to the existing buffer + cfg.func = fmt->name; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_2; cfg.rleMarkerB = 0xfe; @@ -111,9 +92,10 @@ DMGrowBuf mem, tmp; DMCompParams cfg; - cfg.type = DM_COMP_RLE_MARKER; - cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; - cfg.rleMarkerB = buf->data[0x0d]; + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; + cfg.rleMarkerB = buf->data[0x0d]; if ((res = dmDecodeGenericRLEAlloc(&mem, dmGrowBufCreateFromOffs(&tmp, buf, 0x0e), &cfg)) != DMERR_OK) @@ -139,6 +121,7 @@ goto out; // Analyze and setup RLE + cfg.func = fmt->name; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; cfg.rleMinCountB = 3; @@ -211,10 +194,11 @@ 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->data[8]; - cfg.rleMarkerW = buf->data[9]; + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_WORD_RUNS | DM_RLE_ORDER_1; + cfg.rleMarkerB = buf->data[8]; + cfg.rleMarkerW = buf->data[9]; if ((res = dmDecodeGenericRLEAlloc(&mem, dmGrowBufCreateFromOffs(&tmp, buf, 10), &cfg)) != DMERR_OK) @@ -239,6 +223,7 @@ goto out; // Analyze and setup RLE + cfg.func = fmt->name; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_WORD_RUNS | DM_RLE_ORDER_1; cfg.rleMinCountB = 3; @@ -318,9 +303,10 @@ 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; + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; + cfg.rleMarkerB = 0xC2; if ((res = dmDecodeGenericRLEAlloc(&mem, &tmp, &cfg)) != DMERR_OK) goto out; @@ -346,6 +332,7 @@ goto out; // And now RLE compress the data to the existing buffer + cfg.func = fmt->name; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; cfg.rleMarkerB = 0xC2; @@ -412,58 +399,55 @@ // // Based on disassembly of the depacker routine. Encoding seems to be -// some kind of "improved RLE" variant. +// some kind of "improved RLE" variant with different modes and a +// simplistic "codebook". // -static BOOL fmtTruePaintGetByte(const Uint8 *src, size_t *srcOffs, Uint8 *data, int *res, const int mode) +static int fmtTruePaintGetByte(DMGrowBuf *src, Uint8 *data, const int mode) { - if (!dmReverseGetByte(src, srcOffs, data)) + if (!dmGrowBufGetU8(src, data)) { - *res = dmError(DMERR_INVALID_DATA, + return dmError(DMERR_INVALID_DATA, "TruePaintRLE: Out of input data (N=%d)\n", mode); - return FALSE; } else - return TRUE; + return DMERR_OK; } -static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *src, const DMC64ImageFormat *fmt) +static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt) { int res = DMERR_OK; - Uint8 *dst = NULL; - DMGrowBuf dstTmp; const Uint8 *codeBook1, *codeBook2; - size_t - srcOffs, dstOffs, - dstLen = 0x4be8; - // 1b7e-67e8 decoded by original depacker - // 1c00-67e8 is the actual area used tho + DMGrowBuf dst, src; + DMCompParams cfg; + Uint8 data; + + // 1b7e-67e8 decoded by original depacker + // 1c00-67e8 is the actual area used tho + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BACKWARDS_OUTPUT | DM_RLE_BACKWARDS_INPUT | DM_OUT_CROP_END; + cfg.rleMarkerB = 0xfe; + cfg.cropOutLen = 0x67e8 - 0x1c00; // Codebooks: #1 is trampoline table markers, #2 is RLE data table - codeBook1 = src->data + 0x81 - 2; - codeBook2 = src->data + 0x85 - 2; + codeBook1 = psrc->data + 0x81 - 2; + codeBook2 = psrc->data + 0x85 - 2; // Allocate output buffer - if ((dst = dmMalloc0(dstLen)) == NULL) - { - res = dmError(DMERR_MALLOC, - "Could not allocate memory for temporary decompression buffer.\n"); + if ((res = dmGrowBufAlloc(&dst, 64*1024, 4*1024)) != DMERR_OK) goto out; - } - // Begin decompression - srcOffs = src->len; - dstOffs = dstLen; + // 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 (srcOffs > 0 && dstOffs > 0) + while ((res = fmtTruePaintGetByte(&src, &data, -1)) == DMERR_OK) { - Uint8 data; - int count = 1, scount; + unsigned int count = 1; BOOL found = FALSE; - if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, -1)) - goto out; - for (int n = 0; n < 8; n++) if (codeBook1[n] == data && !found) { @@ -471,7 +455,7 @@ switch (n) { case 4: // Y = 4, JTO = $0B - if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) + if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK) goto out; count = data; @@ -485,12 +469,12 @@ // fallthrough case 0: // Y = 0, JTO = $19 - if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) + if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK) goto out; break; case 2: // Y = 2, JTO = $07 - if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) + if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK) goto out; count = data; @@ -508,23 +492,16 @@ } } - for (scount = count; count; count--) - { - if (!dmReversePutByte(dst, &dstOffs, data)) - { - res = dmError(DMERR_INVALID_DATA, - "TruePaintRLE: Out of output space for run: %d x $%02x!\n", - scount, data); - goto out; - } - } + if ((res = dmGenericRLEOutputRun(&dst, &cfg, data, count)) != DMERR_OK) + goto out; } finish: - res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&dstTmp, dst, dstLen), fmt); + dmFinishRLEBuffers(&dst, &src, &cfg); + res = dmC64DecodeGenericBMP(img, &dst, fmt); out: - dmFree(dst); + dmGrowBufFree(&dst); return res; } @@ -593,9 +570,10 @@ DMGrowBuf mem; DMCompParams cfg; - cfg.type = DM_COMP_RLE_MARKER; - cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; - cfg.rleMarkerB = buf->data[15]; + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; + cfg.rleMarkerB = buf->data[15]; if ((res = dmDecodeGenericRLEAlloc( &mem, dmGrowBufCreateFromOffs(&tmp, buf, FUNPAINT2_HEADER_SIZE), &cfg)) == DMERR_OK) @@ -634,6 +612,7 @@ goto out; // Analyze and setup RLE + cfg.func = fmt->name; cfg.type = DM_COMP_RLE_MARKER; cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1; cfg.rleMinCountB = 3; @@ -757,6 +736,40 @@ } +static BOOL fmtECIGetLaceType(DMC64Image *img, const DMC64EncDecOp *op, + const DMGrowBuf *buf, const DMC64ImageFormat *fmt) +{ + (void) op; + (void) buf; + (void) fmt; + img->laceType = D64_ILACE_COLOR; + return TRUE; +} + + +static Uint8 fmtGetPixelECI( + const DMC64Image *img, const int bmoffs, const int scroffs, + const int shift, const int bitmap, const int raster) +{ + const int vbank = raster & 7; + Uint8 + c1 = dmC64GetGenericSCPixel(img, bmoffs, scroffs, shift, vbank , 0, 0), + c2 = dmC64GetGenericSCPixel(img, bmoffs, scroffs, shift, vbank + 8, 1, 0); + + (void) bitmap; + return (c1 * C64_NCOLORS) + c2; +} + + +static int fmtECIConvertBMP2Image(DMImage *dst, const DMC64Image *src, const DMC64ImageFormat *fmt) +{ + if (!dmSetMixedColorC64Palette(dst)) + return DMERR_MALLOC; + + return dmC64ConvertGenericBMP2Image(dst, src, fmt); +} + + // // Helper macros for defining screen ram layouts // common for FLI type foramts @@ -1164,7 +1177,27 @@ }, { - D64_FMT_MC, "xx1", "Unknown $2000 format (unpacked)", 0x2000, 10242, DM_FMT_RD, + D64_FMT_HIRES | D64_FMT_FLI, + "eci", "ECI Graphic Editor 1.0 (unpacked)", 0x4000, 32770, DM_FMT_RD, + C64_SCR_WIDTH, C64_SCR_HEIGHT, + C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT, + NULL, + NULL, NULL, + fmtECIConvertBMP2Image, NULL, + fmtGetPixelECI, + { + { DO_COPY , DS_BITMAP_RAM , 0x0000, 0, 0, NULL, NULL }, + DEF_SCREEN_RAMS_8(0x2000, 0, 0x400), + { DO_COPY , DS_BITMAP_RAM , 0x4000, 1, 0, NULL, NULL }, + DEF_SCREEN_RAMS_8(0x6000, 8, 0x400), + { DO_DEC_FUNC , 0 , 0 , 0, 0, fmtECIGetLaceType, NULL }, + { DO_LAST , 0 , 0 , 0, 0, NULL, NULL }, + }, + NULL + }, + + { + D64_FMT_MC, "xx1", "Unknown $2000 format (unpacked)", 0x2000, 10242, DM_FMT_RDWR, C64_SCR_WIDTH / 2, C64_SCR_HEIGHT, C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT, NULL, @@ -1183,7 +1216,7 @@ }, { - D64_FMT_MC, "xx2", "Unknown $2000 format (unpacked)", 0x2000, 0, DM_FMT_RD, + D64_FMT_MC, "xx2", "Unknown $2000 format (unpacked)", 0x2000, 0, DM_FMT_RDWR, XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8, XX2_WIDTH_CH , XX2_HEIGHT_CH, fmtProbeFormatXX2, diff -r 245f45073f4c -r 811b20de954c tools/lib64gfx.c --- a/tools/lib64gfx.c Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/lib64gfx.c Fri Jun 08 22:32:30 2018 +0300 @@ -12,6 +12,28 @@ #define BUF_SIZE_GROW (4*1024) +// Based on Pepto's palette, stolen from VICE +DMColor dmDefaultC64Palette[C64_NCOLORS] = +{ + { 0x00, 0x00, 0x00, 0xff }, + { 0xFF, 0xFF, 0xFF, 0xff }, + { 0x68, 0x37, 0x2B, 0xff }, + { 0x70, 0xA4, 0xB2, 0xff }, + { 0x6F, 0x3D, 0x86, 0xff }, + { 0x58, 0x8D, 0x43, 0xff }, + { 0x35, 0x28, 0x79, 0xff }, + { 0xB8, 0xC7, 0x6F, 0xff }, + { 0x6F, 0x4F, 0x25, 0xff }, + { 0x43, 0x39, 0x00, 0xff }, + { 0x9A, 0x67, 0x59, 0xff }, + { 0x44, 0x44, 0x44, 0xff }, + { 0x6C, 0x6C, 0x6C, 0xff }, + { 0x9A, 0xD2, 0x84, 0xff }, + { 0x6C, 0x5E, 0xB5, 0xff }, + { 0x95, 0x95, 0x95, 0xff }, +}; + + char * dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng) { snprintf(buf, len, @@ -28,9 +50,9 @@ void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt) { - char typeStr[64]; + char typeStr[64], typeStr2[64]; - dmC64GetImageTypeString(typeStr, sizeof(typeStr), img->type, TRUE); + dmC64GetImageTypeString(typeStr, sizeof(typeStr), fmt->type, TRUE); if (fmt != NULL) { @@ -39,31 +61,48 @@ fmt->name, fmt->fext); } - fprintf(fh, - "Type : %s\n" - "Banks : %d\n", - typeStr, - img->nbanks); + if (img != NULL) + { + dmC64GetImageTypeString(typeStr2, sizeof(typeStr2), img->type, TRUE); - if (img->type & D64_FMT_ILACE) - { - char *tmps; - switch (img->laceType) + fprintf(fh, + "Type : %s [%s]\n" + "Banks : %d\n", + typeStr, typeStr2, + img->nbanks); + + if (img->type & D64_FMT_ILACE) { - case D64_ILACE_COLOR: tmps = "color"; break; - case D64_ILACE_RES: tmps = "resolution"; break; - default: tmps = "ERROR"; break; + char *tmps; + switch (img->laceType) + { + case D64_ILACE_COLOR: tmps = "color"; break; + case D64_ILACE_RES: tmps = "resolution"; break; + default: tmps = "ERROR"; break; + } + fprintf(fh, + "Interlace type : %s\n", + tmps); } + fprintf(fh, - "Interlace type : %s\n", - tmps); + "Width x Height : %d x %d [%d x %d]\n" + "CHwidth x CHheight : %d x %d [%d x %d]\n", + img->width, img->height, + fmt->width, fmt->height, + img->chWidth, img->chHeight, + fmt->chWidth, fmt->chHeight); } - - fprintf(fh, - "Width x Height : %d x %d\n" - "CHwidth x CHheight : %d x %d\n", - img->width, img->height, - img->chWidth, img->chHeight); + else + { + fprintf(fh, + "Type : %s\n" + "Width x Height : %d x %d\n" + "CHwidth x CHheight : %d x %d\n", + typeStr, + fmt->width, fmt->height, + fmt->chWidth, fmt->chHeight); + } } @@ -76,6 +115,29 @@ } +BOOL dmSetMixedColorC64Palette(DMImage *img) +{ + if (!dmImagePaletteAlloc(img, C64_NCOLORS * C64_NCOLORS, -1)) + return FALSE; + + int n = 0; + for (int n1 = 0; n1 < C64_NCOLORS; n1++) + { + const DMColor *col1 = &dmDefaultC64Palette[n1]; + for (int n2 = 0; n2 < C64_NCOLORS; n2++) + { + const DMColor *col2 = &dmDefaultC64Palette[n2]; + img->pal[n].r = (col1->r + col2->r) / 2; + img->pal[n].g = (col1->g + col2->g) / 2; + img->pal[n].b = (col1->b + col2->b) / 2; + n++; + } + } + + return TRUE; +} + + BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr) { return buf[offs ] == DM_GET_ADDR_LO(addr) && @@ -100,30 +162,6 @@ } -BOOL dmReverseGetByte(const Uint8 *buf, size_t *offs, Uint8 *data) -{ - if (*offs > 0) - { - *data = buf[--(*offs)]; - return TRUE; - } - else - return FALSE; -} - - -BOOL dmReversePutByte(Uint8 *buf, size_t *offs, const Uint8 data) -{ - if (*offs > 0) - { - buf[--(*offs)] = data; - return TRUE; - } - else - return FALSE; -} - - int dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size) { if ((blk->data = dmMalloc0(size)) == NULL) @@ -327,7 +365,7 @@ } -static void dmSetupRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg) +void dmSetupRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg) { if (cfg->flags & DM_RLE_BACKWARDS_INPUT) { @@ -343,6 +381,49 @@ } +void dmFinishRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg) +{ + if (cfg->flags & DM_RLE_BACKWARDS_OUTPUT) + { + memmove(dst->data, dst->data + dst->offs, dst->len); + dst->offs = 0; + } + + switch (cfg->flags & DM_OUT_CROP_MASK) + { + case DM_OUT_CROP_END: + if (cfg->cropOutLen < dst->len) + { + memmove(dst->data, dst->data + dst->len - cfg->cropOutLen + 1, cfg->cropOutLen); + dst->len = cfg->cropOutLen; + } + break; + + case DM_OUT_CROP_START: + if (cfg->cropOutLen <= dst->len) + dst->len = cfg->cropOutLen; + break; + } +} + + +int dmGenericRLEOutputRun(DMGrowBuf *dst, const DMCompParams *cfg, const Uint8 data, const unsigned int count) +{ + unsigned int scount; + for (scount = count; scount; scount--) + { + if (!dmGrowBufPutU8(dst, data)) + { + return dmError(DMERR_MALLOC, + "%s: RLE: Could not output RLE run %d x 0x%02x @ " + "offs=0x%" DM_PRIx_SIZE_T ", size=0x%" DM_PRIx_SIZE_T ".\n", + cfg->func, count, data, dst->offs, dst->size); + } + } + return DMERR_OK; +} + + int dmDecodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *psrc, const DMCompParams *cfg) { int res; @@ -366,7 +447,9 @@ if (!dmGrowBufGetU8(&src, &tmp1) || !dmGrowBufGetU8(&src, &tmp2)) { - res = DMERR_INVALID_DATA; + res = dmError(DMERR_INVALID_DATA, + "%s: RLE: Invalid data/out of data for byte length run sequence.\n", + cfg->func); goto out; } switch (cfg->flags & DM_RLE_ORDER_MASK) @@ -389,7 +472,9 @@ !dmGrowBufGetU8(&src, &tmp2) || !dmGrowBufGetU8(&src, &tmp3)) { - res = DMERR_INVALID_DATA; + res = dmError(DMERR_INVALID_DATA, + "%s: RLE: Invalid data/out of data for word length run sequence.\n", + cfg->func); goto out; } switch (cfg->flags & DM_RLE_ORDER_MASK) @@ -415,7 +500,9 @@ { if (!dmGrowBufGetU8(&src, &tmp1)) { - res = DMERR_INVALID_DATA; + res = dmError(DMERR_INVALID_DATA, + "%s: RLE: Invalid data/out of data for byte length mask/run sequence.\n", + cfg->func); goto out; } @@ -424,16 +511,11 @@ } } - while (count--) - { - if (!dmGrowBufPutU8(dst, data)) - { - res = DMERR_MALLOC; - goto out; - } - } + if ((res = dmGenericRLEOutputRun(dst, cfg, data, count)) != DMERR_OK) + goto out; } + dmFinishRLEBuffers(dst, &src, cfg); res = DMERR_OK; out: @@ -451,9 +533,10 @@ } -static BOOL dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, unsigned int count, const DMCompParams *cfg) +int dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, const unsigned int count, const DMCompParams *cfg) { BOOL copyOnly = FALSE; + int res; switch (cfg->type) { @@ -463,20 +546,20 @@ { // A simple marker byte RLE variant: [Marker] [count] [data] if (!dmGrowBufPutU8(dst, cfg->rleMarkerW)) - return FALSE; + goto err; switch (cfg->flags & DM_RLE_ORDER_MASK) { case DM_RLE_ORDER_1: if (!dmGrowBufPutU16LE(dst, count) || !dmGrowBufPutU8(dst, data)) - return FALSE; + goto err; break; case DM_RLE_ORDER_2: if (!dmGrowBufPutU8(dst, data) || !dmGrowBufPutU16LE(dst, count)) - return FALSE; + goto err; break; } } @@ -486,20 +569,20 @@ { // A simple marker byte RLE variant: [Marker] [count] [data] if (!dmGrowBufPutU8(dst, cfg->rleMarkerB)) - return FALSE; + goto err; switch (cfg->flags & DM_RLE_ORDER_MASK) { case DM_RLE_ORDER_1: if (!dmGrowBufPutU8(dst, count) || !dmGrowBufPutU8(dst, data)) - return FALSE; + goto err; break; case DM_RLE_ORDER_2: if (!dmGrowBufPutU8(dst, data) || !dmGrowBufPutU8(dst, count)) - return FALSE; + goto err; break; } } @@ -514,23 +597,22 @@ // and the lower bits contain the count: [Mask + count] [data] if (!dmGrowBufPutU8(dst, cfg->rleMarkerBits | count) || !dmGrowBufPutU8(dst, data)) - return FALSE; + goto err; } else copyOnly = TRUE; break; } - if (copyOnly) - { - while (count--) - { - if (!dmGrowBufPutU8(dst, data)) - return FALSE; - } - } + if (copyOnly && (res = dmGenericRLEOutputRun(dst, cfg, data, count)) != DMERR_OK) + return res; + + return DMERR_OK; - return TRUE; +err: + return dmError(DMERR_MALLOC, + "%s: RLE: Could not output RLE sequence %d x 0x%02x.\n", + cfg->func, count, data); } @@ -538,7 +620,7 @@ { DMGrowBuf src; unsigned int count = 0; - int prev = -1; + int prev = -1, res = DMERR_OK; Uint8 data; // As we need to modify the offs, etc. but not the data, @@ -554,7 +636,7 @@ ((cfg->flags & DM_RLE_WORD_RUNS) && count >= cfg->rleMaxCountW) || (((cfg->flags & DM_RLE_RUNS_MASK) == DM_RLE_BYTE_RUNS) && count >= cfg->rleMaxCountB)) { - if (!dmEncodeGenericRLESequence(dst, prev, count, cfg)) + if ((res = dmEncodeGenericRLESequence(dst, prev, count, cfg)) != DMERR_OK) goto err; count = 1; @@ -565,14 +647,14 @@ prev = data; } - if (!dmEncodeGenericRLESequence(dst, prev, count, cfg)) + // If there is anything left in the output queue .. + if ((res = dmEncodeGenericRLESequence(dst, prev, count, cfg)) != DMERR_OK) goto err; - return DMERR_OK; + dmFinishRLEBuffers(dst, &src, cfg); err: - return dmError(DMERR_MALLOC, - "Could not reallocate memory for RLE encoding buffer.\n"); + return res; } @@ -631,6 +713,8 @@ { case DO_COPY: case DO_SET_MEM: + case DO_SET_MEM_HI: + case DO_SET_MEM_LO: case DO_SET_OP: switch (op->subject) { @@ -677,38 +761,34 @@ BOOL dmC64GetOpSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt, size_t *size) { - // Default to size of 0 - *size = 0; - - switch (op->type) + switch (op->subject) { - case DO_COPY: - case DO_SET_MEM: - case DO_SET_OP: - switch (op->subject) - { - case DS_SCREEN_RAM: - case DS_COLOR_RAM: - *size = fmt->chHeight * fmt->chWidth; - break; + case DS_SCREEN_RAM: + case DS_COLOR_RAM: + *size = fmt->chHeight * fmt->chWidth; + break; + + case DS_BITMAP_RAM: + *size = fmt->chHeight * fmt->chWidth * 8; + break; - case DS_BITMAP_RAM: - *size = fmt->chHeight * fmt->chWidth * 8; - break; - - case DS_CHAR_DATA: - *size = C64_MAX_CHARS * C64_CHR_SIZE; - break; + case DS_CHAR_DATA: + *size = C64_MAX_CHARS * C64_CHR_SIZE; + break; - case DS_D020: - case DS_BGCOL: - case DS_D021: - case DS_D022: - case DS_D023: - case DS_D024: - *size = 1; - break; - } + case DS_D020: + case DS_BGCOL: + case DS_D021: + case DS_D022: + case DS_D023: + case DS_D024: + *size = 1; + break; + + default: + // Default to size of 0 + *size = 0; + break; } // If the operator specified size is larger, use it. @@ -792,6 +872,8 @@ { case DO_COPY: case DO_SET_MEM: + case DO_SET_MEM_HI: + case DO_SET_MEM_LO: case DO_SET_OP: switch (op->subject) { @@ -822,6 +904,12 @@ case DO_SET_OP: memset(blk->data, op->offs, size); break; + + default: + return dmError(DMERR_INTERNAL, + "Unhandled op type %d in " + "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + op->type, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); } break; @@ -842,6 +930,13 @@ value = op->offs; break; + case DO_SET_MEM_HI: + value = (*src >> 4) & 0x0f; + break; + + case DO_SET_MEM_LO: + value = *src & 0x0f; + break; } switch (op->subject) { @@ -1044,6 +1139,14 @@ *dst = value; break; + case DO_SET_MEM_HI: + *dst |= (value & 0x0f) << 4; + break; + + case DO_SET_MEM_LO: + *dst |= value & 0x0f; + break; + case DO_SET_OP: // Do nothing in this case break; @@ -1238,6 +1341,7 @@ // Set partial palette information dst->ncolors = C64_NCOLORS; dst->constpal = TRUE; + dst->pal = dmDefaultC64Palette; // Convert if (fmt->convertFrom != NULL) diff -r 245f45073f4c -r 811b20de954c tools/lib64gfx.h --- a/tools/lib64gfx.h Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/lib64gfx.h Fri Jun 08 22:32:30 2018 +0300 @@ -86,6 +86,9 @@ DO_SET_MEM, // Set subject value or fill subject memory area to byte value from offset DO_SET_OP, // Like above but value from op->offs field instead + DO_SET_MEM_HI, // Copy one byte value like DO_SET_MEM, but high nibble only + DO_SET_MEM_LO, // Like above, but low nibble + DO_DEC_FUNC, // Execute specified decoding function (only for decoding operations) DO_ENC_FUNC, // Same, but for encoding @@ -230,15 +233,23 @@ DM_RLE_ORDER_2 = 0x0010, // Order: , , DM_RLE_ORDER_MASK = 0x00f0, - DM_RLE_BACKWARDS_INPUT = 0x1000, - DM_RLE_BACKWARDS_OUTPUT = 0x2000, + DM_RLE_BACKWARDS_INPUT = 0x0100, + DM_RLE_BACKWARDS_OUTPUT = 0x0200, + + DM_OUT_CROP_NONE = 0x0000, + DM_OUT_CROP_START = 0x1000, + DM_OUT_CROP_END = 0x2000, + DM_OUT_CROP_MASK = 0xf000, }; typedef struct { + char *func; int type; int flags; + size_t cropOutLen; + Uint8 // DM_COMP_RLE_MARKER mode rleMarkerB, // Marker byte for byte length runs (if DM_RLE_BYTE_RUNS used) @@ -273,10 +284,10 @@ void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt); void dmSetDefaultC64Palette(DMImage *img); +BOOL dmSetMixedColorC64Palette(DMImage *img); + BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr); int dmC64ImageGetNumBanks(const DMC64ImageFormat *fmt); -BOOL dmReverseGetByte(const Uint8 *buf, size_t *offs, Uint8 *data); -BOOL dmReversePutByte(Uint8 *buf, size_t *offs, const Uint8 data); // C64 bitmap image allocation/freeing int dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size); @@ -309,6 +320,11 @@ void dmGenericRLEAnalyze(const DMGrowBuf *buf, DMCompParams *cfg); +void dmSetupRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg); +void dmFinishRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg); +int dmGenericRLEOutputRun(DMGrowBuf *dst, const DMCompParams *cfg, const Uint8 data, const unsigned int count); +int dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, const unsigned int count, const DMCompParams *cfg); + int dmDecodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg); diff -r 245f45073f4c -r 811b20de954c tools/libgfx.c --- a/tools/libgfx.c Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/libgfx.c Fri Jun 08 22:32:30 2018 +0300 @@ -172,6 +172,8 @@ img->ncolors = ncolors; img->ctransp = ctransp; + img->constpal = FALSE; + return dmPaletteAlloc(&(img->pal), ncolors, ctransp); } diff -r 245f45073f4c -r 811b20de954c tools/libgfx.h --- a/tools/libgfx.h Fri Jun 08 22:32:11 2018 +0300 +++ b/tools/libgfx.h Fri Jun 08 22:32:30 2018 +0300 @@ -119,6 +119,8 @@ int dmImageProbeGeneric(const Uint8 *buf, const size_t len, const DMImageFormat **fmt, int *index); BOOL dmCompareColor(const DMColor *c1, const DMColor *c2, BOOL alpha); +BOOL dmPaletteAlloc(DMColor **ppal, int ncolors, int ctransp); +BOOL dmImagePaletteAlloc(DMImage *img, int ncolors, int ctransp); int dmWriteImageData(const DMImage *img, void *cbdata, int (*writeRowCB)(void *, const Uint8 *, const size_t), const DMImageConvSpec *spec);