Mercurial > hg > dmlib
changeset 2189:83391646ff16
Add read support for packed version of Crest Super Hires FLI format.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 13 Jun 2019 07:49:45 +0300 |
parents | 9b7d5e219d4b |
children | 0447f4c6c32b |
files | tools/lib64fmts.c |
diffstat | 1 files changed, 179 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/tools/lib64fmts.c Thu Jun 13 00:01:54 2019 +0300 +++ b/tools/lib64fmts.c Thu Jun 13 07:49:45 2019 +0300 @@ -1236,6 +1236,12 @@ }; +static const Uint8 fmtCrestSHFLI_MagicID_Packed[] = +{ + 0x83, 0x92, 0x85, 0x93, 0x94, +}; + + static int fmtProbeCrestSHFLI(const DMGrowBuf *buf, const DMC64ImageFormat *fmt) { // Unpacked variant @@ -1252,10 +1258,158 @@ return score; } + // Packed variant + if (dmCompareAddr16(buf, 0, fmt->addr) && + buf->len > sizeof(fmtCrestSHFLI_MagicID_Packed) && + DM_MEMCMP_SIZE(buf->data + buf->len - sizeof(fmtCrestSHFLI_MagicID_Packed), fmtCrestSHFLI_MagicID_Packed) == 0) + return DM_PROBE_SCORE_MAX; + return DM_PROBE_SCORE_FALSE; } +static int fmtDecodeCrestSHFLIPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt) +{ + int res; + DMGrowBuf tmp, mem; + DMCompParams cfg; + + // Compression is typical RLE, with first byte being the RLE marker byte etc. + // However, as a difference to the uncompressed files, only the data of the + // 96 pixels wide area (4 sprite widths) x 168 tall is saved. + cfg.func = fmt->name; + cfg.type = DM_COMP_RLE_MARKER; + cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1 | DM_RLE_ZERO_COUNT_MAX; + cfg.rleMarkerB = buf->data[0]; + + if ((res = dmDecodeGenericRLEAlloc( + &mem, dmGrowBufConstCopyOffs(&tmp, buf, 1), &cfg)) == DMERR_OK) + { + const size_t fmtUncompSize = 0x1ff0; + const size_t dstSize = 16 * 1024; + const int imgXOffs = 14; + const int imgWidth = 4 * D64_SPR_WIDTH_UT; + Uint8 *dstBuf, *sptr, *dptr; + + // Check uncompressed size? + if (mem.len != fmtUncompSize) + { + res = dmError(DMERR_INVALID_DATA, + "%s: Unexpected uncompressed data size %d bytes (should be %d).\n", + cfg.func, mem.len, fmtUncompSize); + goto out; + } + + // Allocate output buffer + if ((dstBuf = dmMalloc0(dstSize)) == NULL) + { + res = dmError(DMERR_MALLOC, + "%s: Could not allocate temporary memory buffer of %d bytes.\n", + cfg.func, dstSize); + goto out; + } + + // Now that we have the uncompressed data (0x1ff0 bytes), we need to + // re-arrange it. The data is as follows .. + // + // 0x0000 - sprite data for 64 sprites + // 0x1000 - bitmap (12 * 21 bytes) + // 0x1800 - screen RAMs (12 * 21 bytes) x 8 banks + // 0x1fe8 - sprite color #1 + // 0x1fe9 - sprite color #2 + // + + // Copy sprite colors + sptr = mem.data + 0x1fe8; + dptr = dstBuf + 0x03e8; + dptr[0] = sptr[0]; + dptr[1] = sptr[1]; + + // First, clear and set some defaults that are not saved in the file + for (int nbank = 0; nbank < DM_CREST_SHFLI_BANKS; nbank++) + { + dptr = dstBuf + nbank * 0x0400; + + // Set preset screen RAM for other area + memset(dptr, 0xff, fmt->format->chWidth * fmt->format->chHeight); + + // Copy sprite data points + memcpy(dptr + 0x03f8, &fmtCrestSHFLI_Sprite_pointers[nbank], DM_CREST_SHFLI_PTRS); + } + + // Now we copy and transform the bitmap and screen RAM data. + for (int yc = 0; yc < fmt->format->chHeight * 8; yc++) + { + const int syy = yc / 8; + const int syd = yc & 7; + + // In the image the first visible scanline is unused, but in + // the compressed version data starts right away, so we offset + // the destination Y coordinate by one. + const int dyc = yc + 1; + const int dyy = dyc / 8; + const int dyd = dyc & 7; + + // Format of the bitmap data is one horizontal pixel row (12 bytes) + // times 21*8 rows, e.g. the data is "linear" rows of bytes and not + // arranged in usual c64 bitmap "char" order. Thus we reorder it. + sptr = mem.data + 0x1000 + imgWidth * (syd + 8 * syy); + dptr = dstBuf + 0x2000 + imgXOffs * 8 + (fmt->format->chWidth * dyy * 8) + dyd; + + for (int xc = 0; xc < imgWidth; xc++) + { + dptr[xc * 8] = sptr[xc]; + sptr[xc] = 0xaa; + } + + // A bit similar arrangement is used for the screen RAM data. + // Each row of 12 bytes of data is for a bank. Next row is for + // next bank, etc. + sptr = mem.data + 0x1800 + imgWidth * syd + imgWidth * 8 * syy; + dptr = dstBuf + imgXOffs + 0x0400 * dyd + fmt->format->chWidth * dyy; + + for (int xc = 0; xc < imgWidth; xc++) + { + dptr[xc] = sptr[xc]; + sptr[xc] = 0xaa; + } + } + + // The sprite data is also transformed similarly, data is + // in same scanline format as the bitmap. Thus we need to + // place it where it belongs based on the sprite pointers. + for (int yc = 0; yc < fmt->format->chHeight * 8; yc++) + { + const int yd = yc % 21; + Uint8 *sp1, *sp2, *dp, *sprPtrs = fmtCrestSHFLI_Sprite_pointers[yc % 8]; + + dptr = dstBuf + 3 * yd; + sp1 = mem.data + imgWidth * yc; + sp2 = sp1 + 0x800; + + for (int xc = 0; xc < 4; xc++) + { + dp = dptr + D64_SPR_SIZE * sprPtrs[xc]; + for (int xd = 0; xd < D64_SPR_WIDTH_UT; xd++) + dp[xd] = *sp1++; + + dp = dptr + D64_SPR_SIZE * sprPtrs[xc + 4]; + for (int xd = 0; xd < D64_SPR_WIDTH_UT; xd++) + dp[xd] = *sp2++; + } + } + + res = dmC64DecodeGenericBMP(img, dmGrowBufConstCreateFrom(&tmp, dstBuf, dstSize), fmt); + dmFree(dstBuf); + } + +out: + dmGrowBufFree(&mem); + + return res; +} + + static int fmtGetSpritePixelCrestSHFLI(Uint8 *col, const DMC64Image *img, const int sindex, const int cindex, const int spr_xd, const int spr_yd, const int mask) @@ -1681,6 +1835,23 @@ { DO_LAST , 0 , 0 , 0, 0, 0, NULL, NULL }, } }, + + { // #11: Crest Super Hires FLI Editor 1.0 (SHF) + D64_FMT_HIRES | D64_FMT_FLI, + D64_SCR_WIDTH, D64_SCR_HEIGHT, + D64_SCR_CH_WIDTH, 21, + 1, 1, + NULL, NULL, + fmtGetPixelCrestSHFLI, + { + DEF_REPEAT_BLOCK_8(DS_SCREEN_RAM, 0x0000, 0 , 0x0400, 0), + DEF_REPEAT_BLOCK_8(DS_EXTRA_DATA, 0x03f8, 0 , 0x0400, 8), // Sprite pointers for each bank + { DO_COPY , DS_EXTRA_DATA , 0x03e8, 15, 2 , 0, NULL, NULL }, // 2 sprite colors + { DO_COPY , DS_EXTRA_DATA , 0x0000, 14, 0x3e00, 0, NULL, NULL }, // Lazily copy whole data for sprite data + { DO_COPY , DS_BITMAP_RAM , 0x2000, 0 , 0 , 0, NULL, NULL }, + { DO_LAST , 0 , 0 , 0 , 0 , 0, NULL, NULL }, + } + }, }; @@ -2359,23 +2530,14 @@ "cshf", "Crest Super Hires FLI Editor v1.0 (unpacked)", 0x4000, 15874, DM_FMT_RD, fmtProbeCrestSHFLI, NULL, NULL, - { - D64_FMT_HIRES | D64_FMT_FLI, - D64_SCR_WIDTH, D64_SCR_HEIGHT, - D64_SCR_CH_WIDTH, 21, - 1, 1, - NULL, NULL, - fmtGetPixelCrestSHFLI, - { - DEF_REPEAT_BLOCK_8(DS_SCREEN_RAM, 0x0000, 0, 0x400, 0), - DEF_REPEAT_BLOCK_8(DS_EXTRA_DATA, 0x03f8, 0, 0x400, 8), // Sprite pointers for each bank - { DO_COPY , DS_EXTRA_DATA , 0x03e8, 15, 2 , 0, NULL, NULL }, // 2 sprite colors - { DO_COPY , DS_EXTRA_DATA , 0x0000, 14, 0x3e00, 0, NULL, NULL }, // Lazily copy whole data for sprite data - { DO_COPY , DS_BITMAP_RAM , 0x2000, 0, 0, 0, NULL, NULL }, - { DO_LAST , 0 , 0 , 0, 0, 0, NULL, NULL }, - } - }, - NULL + { }, &dmC64CommonFormats[11] + }, + + { + "cshfp", "Crest Super Hires FLI Editor v1.0 (packed)", 0xa000, 0, DM_FMT_RD, + fmtProbeCrestSHFLI, + fmtDecodeCrestSHFLIPacked, NULL, + { }, &dmC64CommonFormats[11] }, {