comparison tools/lib64fmts.c @ 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
comparison
equal deleted inserted replaced
2188:9b7d5e219d4b 2189:83391646ff16
1234 { 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6 }, 1234 { 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6 },
1235 { 0xF7, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E }, 1235 { 0xF7, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E },
1236 }; 1236 };
1237 1237
1238 1238
1239 static const Uint8 fmtCrestSHFLI_MagicID_Packed[] =
1240 {
1241 0x83, 0x92, 0x85, 0x93, 0x94,
1242 };
1243
1244
1239 static int fmtProbeCrestSHFLI(const DMGrowBuf *buf, const DMC64ImageFormat *fmt) 1245 static int fmtProbeCrestSHFLI(const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
1240 { 1246 {
1241 // Unpacked variant 1247 // Unpacked variant
1242 if (buf->len == fmt->size && 1248 if (buf->len == fmt->size &&
1243 dmCompareAddr16(buf, 0, fmt->addr)) 1249 dmCompareAddr16(buf, 0, fmt->addr))
1250 score += DM_PROBE_SCORE_GOOD; 1256 score += DM_PROBE_SCORE_GOOD;
1251 } 1257 }
1252 return score; 1258 return score;
1253 } 1259 }
1254 1260
1261 // Packed variant
1262 if (dmCompareAddr16(buf, 0, fmt->addr) &&
1263 buf->len > sizeof(fmtCrestSHFLI_MagicID_Packed) &&
1264 DM_MEMCMP_SIZE(buf->data + buf->len - sizeof(fmtCrestSHFLI_MagicID_Packed), fmtCrestSHFLI_MagicID_Packed) == 0)
1265 return DM_PROBE_SCORE_MAX;
1266
1255 return DM_PROBE_SCORE_FALSE; 1267 return DM_PROBE_SCORE_FALSE;
1268 }
1269
1270
1271 static int fmtDecodeCrestSHFLIPacked(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt)
1272 {
1273 int res;
1274 DMGrowBuf tmp, mem;
1275 DMCompParams cfg;
1276
1277 // Compression is typical RLE, with first byte being the RLE marker byte etc.
1278 // However, as a difference to the uncompressed files, only the data of the
1279 // 96 pixels wide area (4 sprite widths) x 168 tall is saved.
1280 cfg.func = fmt->name;
1281 cfg.type = DM_COMP_RLE_MARKER;
1282 cfg.flags = DM_RLE_BYTE_RUNS | DM_RLE_ORDER_1 | DM_RLE_ZERO_COUNT_MAX;
1283 cfg.rleMarkerB = buf->data[0];
1284
1285 if ((res = dmDecodeGenericRLEAlloc(
1286 &mem, dmGrowBufConstCopyOffs(&tmp, buf, 1), &cfg)) == DMERR_OK)
1287 {
1288 const size_t fmtUncompSize = 0x1ff0;
1289 const size_t dstSize = 16 * 1024;
1290 const int imgXOffs = 14;
1291 const int imgWidth = 4 * D64_SPR_WIDTH_UT;
1292 Uint8 *dstBuf, *sptr, *dptr;
1293
1294 // Check uncompressed size?
1295 if (mem.len != fmtUncompSize)
1296 {
1297 res = dmError(DMERR_INVALID_DATA,
1298 "%s: Unexpected uncompressed data size %d bytes (should be %d).\n",
1299 cfg.func, mem.len, fmtUncompSize);
1300 goto out;
1301 }
1302
1303 // Allocate output buffer
1304 if ((dstBuf = dmMalloc0(dstSize)) == NULL)
1305 {
1306 res = dmError(DMERR_MALLOC,
1307 "%s: Could not allocate temporary memory buffer of %d bytes.\n",
1308 cfg.func, dstSize);
1309 goto out;
1310 }
1311
1312 // Now that we have the uncompressed data (0x1ff0 bytes), we need to
1313 // re-arrange it. The data is as follows ..
1314 //
1315 // 0x0000 - sprite data for 64 sprites
1316 // 0x1000 - bitmap (12 * 21 bytes)
1317 // 0x1800 - screen RAMs (12 * 21 bytes) x 8 banks
1318 // 0x1fe8 - sprite color #1
1319 // 0x1fe9 - sprite color #2
1320 //
1321
1322 // Copy sprite colors
1323 sptr = mem.data + 0x1fe8;
1324 dptr = dstBuf + 0x03e8;
1325 dptr[0] = sptr[0];
1326 dptr[1] = sptr[1];
1327
1328 // First, clear and set some defaults that are not saved in the file
1329 for (int nbank = 0; nbank < DM_CREST_SHFLI_BANKS; nbank++)
1330 {
1331 dptr = dstBuf + nbank * 0x0400;
1332
1333 // Set preset screen RAM for other area
1334 memset(dptr, 0xff, fmt->format->chWidth * fmt->format->chHeight);
1335
1336 // Copy sprite data points
1337 memcpy(dptr + 0x03f8, &fmtCrestSHFLI_Sprite_pointers[nbank], DM_CREST_SHFLI_PTRS);
1338 }
1339
1340 // Now we copy and transform the bitmap and screen RAM data.
1341 for (int yc = 0; yc < fmt->format->chHeight * 8; yc++)
1342 {
1343 const int syy = yc / 8;
1344 const int syd = yc & 7;
1345
1346 // In the image the first visible scanline is unused, but in
1347 // the compressed version data starts right away, so we offset
1348 // the destination Y coordinate by one.
1349 const int dyc = yc + 1;
1350 const int dyy = dyc / 8;
1351 const int dyd = dyc & 7;
1352
1353 // Format of the bitmap data is one horizontal pixel row (12 bytes)
1354 // times 21*8 rows, e.g. the data is "linear" rows of bytes and not
1355 // arranged in usual c64 bitmap "char" order. Thus we reorder it.
1356 sptr = mem.data + 0x1000 + imgWidth * (syd + 8 * syy);
1357 dptr = dstBuf + 0x2000 + imgXOffs * 8 + (fmt->format->chWidth * dyy * 8) + dyd;
1358
1359 for (int xc = 0; xc < imgWidth; xc++)
1360 {
1361 dptr[xc * 8] = sptr[xc];
1362 sptr[xc] = 0xaa;
1363 }
1364
1365 // A bit similar arrangement is used for the screen RAM data.
1366 // Each row of 12 bytes of data is for a bank. Next row is for
1367 // next bank, etc.
1368 sptr = mem.data + 0x1800 + imgWidth * syd + imgWidth * 8 * syy;
1369 dptr = dstBuf + imgXOffs + 0x0400 * dyd + fmt->format->chWidth * dyy;
1370
1371 for (int xc = 0; xc < imgWidth; xc++)
1372 {
1373 dptr[xc] = sptr[xc];
1374 sptr[xc] = 0xaa;
1375 }
1376 }
1377
1378 // The sprite data is also transformed similarly, data is
1379 // in same scanline format as the bitmap. Thus we need to
1380 // place it where it belongs based on the sprite pointers.
1381 for (int yc = 0; yc < fmt->format->chHeight * 8; yc++)
1382 {
1383 const int yd = yc % 21;
1384 Uint8 *sp1, *sp2, *dp, *sprPtrs = fmtCrestSHFLI_Sprite_pointers[yc % 8];
1385
1386 dptr = dstBuf + 3 * yd;
1387 sp1 = mem.data + imgWidth * yc;
1388 sp2 = sp1 + 0x800;
1389
1390 for (int xc = 0; xc < 4; xc++)
1391 {
1392 dp = dptr + D64_SPR_SIZE * sprPtrs[xc];
1393 for (int xd = 0; xd < D64_SPR_WIDTH_UT; xd++)
1394 dp[xd] = *sp1++;
1395
1396 dp = dptr + D64_SPR_SIZE * sprPtrs[xc + 4];
1397 for (int xd = 0; xd < D64_SPR_WIDTH_UT; xd++)
1398 dp[xd] = *sp2++;
1399 }
1400 }
1401
1402 res = dmC64DecodeGenericBMP(img, dmGrowBufConstCreateFrom(&tmp, dstBuf, dstSize), fmt);
1403 dmFree(dstBuf);
1404 }
1405
1406 out:
1407 dmGrowBufFree(&mem);
1408
1409 return res;
1256 } 1410 }
1257 1411
1258 1412
1259 static int fmtGetSpritePixelCrestSHFLI(Uint8 *col, 1413 static int fmtGetSpritePixelCrestSHFLI(Uint8 *col,
1260 const DMC64Image *img, const int sindex, const int cindex, 1414 const DMC64Image *img, const int sindex, const int cindex,
1677 NULL, 1831 NULL,
1678 { 1832 {
1679 { DO_COPY , DS_SCREEN_RAM , 0x0000, 0, 0, 0, NULL, NULL }, 1833 { DO_COPY , DS_SCREEN_RAM , 0x0000, 0, 0, 0, NULL, NULL },
1680 { DO_COPY , DS_BITMAP_RAM , 0x0400, 0, 0, 0, NULL, NULL }, 1834 { DO_COPY , DS_BITMAP_RAM , 0x0400, 0, 0, 0, NULL, NULL },
1681 { DO_LAST , 0 , 0 , 0, 0, 0, NULL, NULL }, 1835 { DO_LAST , 0 , 0 , 0, 0, 0, NULL, NULL },
1836 }
1837 },
1838
1839 { // #11: Crest Super Hires FLI Editor 1.0 (SHF)
1840 D64_FMT_HIRES | D64_FMT_FLI,
1841 D64_SCR_WIDTH, D64_SCR_HEIGHT,
1842 D64_SCR_CH_WIDTH, 21,
1843 1, 1,
1844 NULL, NULL,
1845 fmtGetPixelCrestSHFLI,
1846 {
1847 DEF_REPEAT_BLOCK_8(DS_SCREEN_RAM, 0x0000, 0 , 0x0400, 0),
1848 DEF_REPEAT_BLOCK_8(DS_EXTRA_DATA, 0x03f8, 0 , 0x0400, 8), // Sprite pointers for each bank
1849 { DO_COPY , DS_EXTRA_DATA , 0x03e8, 15, 2 , 0, NULL, NULL }, // 2 sprite colors
1850 { DO_COPY , DS_EXTRA_DATA , 0x0000, 14, 0x3e00, 0, NULL, NULL }, // Lazily copy whole data for sprite data
1851 { DO_COPY , DS_BITMAP_RAM , 0x2000, 0 , 0 , 0, NULL, NULL },
1852 { DO_LAST , 0 , 0 , 0 , 0 , 0, NULL, NULL },
1682 } 1853 }
1683 }, 1854 },
1684 }; 1855 };
1685 1856
1686 1857
2357 2528
2358 { 2529 {
2359 "cshf", "Crest Super Hires FLI Editor v1.0 (unpacked)", 0x4000, 15874, DM_FMT_RD, 2530 "cshf", "Crest Super Hires FLI Editor v1.0 (unpacked)", 0x4000, 15874, DM_FMT_RD,
2360 fmtProbeCrestSHFLI, 2531 fmtProbeCrestSHFLI,
2361 NULL, NULL, 2532 NULL, NULL,
2362 { 2533 { }, &dmC64CommonFormats[11]
2363 D64_FMT_HIRES | D64_FMT_FLI, 2534 },
2364 D64_SCR_WIDTH, D64_SCR_HEIGHT, 2535
2365 D64_SCR_CH_WIDTH, 21, 2536 {
2366 1, 1, 2537 "cshfp", "Crest Super Hires FLI Editor v1.0 (packed)", 0xa000, 0, DM_FMT_RD,
2367 NULL, NULL, 2538 fmtProbeCrestSHFLI,
2368 fmtGetPixelCrestSHFLI, 2539 fmtDecodeCrestSHFLIPacked, NULL,
2369 { 2540 { }, &dmC64CommonFormats[11]
2370 DEF_REPEAT_BLOCK_8(DS_SCREEN_RAM, 0x0000, 0, 0x400, 0),
2371 DEF_REPEAT_BLOCK_8(DS_EXTRA_DATA, 0x03f8, 0, 0x400, 8), // Sprite pointers for each bank
2372 { DO_COPY , DS_EXTRA_DATA , 0x03e8, 15, 2 , 0, NULL, NULL }, // 2 sprite colors
2373 { DO_COPY , DS_EXTRA_DATA , 0x0000, 14, 0x3e00, 0, NULL, NULL }, // Lazily copy whole data for sprite data
2374 { DO_COPY , DS_BITMAP_RAM , 0x2000, 0, 0, 0, NULL, NULL },
2375 { DO_LAST , 0 , 0 , 0, 0, 0, NULL, NULL },
2376 }
2377 },
2378 NULL
2379 }, 2541 },
2380 2542
2381 { 2543 {
2382 "cdhm", "Cosmos Designs Hires Manager (unpacked)", 0x4000, 16385, DM_FMT_RDWR, 2544 "cdhm", "Cosmos Designs Hires Manager (unpacked)", 0x4000, 16385, DM_FMT_RDWR,
2383 fmtProbeCosmosDesignsHiresManager, 2545 fmtProbeCosmosDesignsHiresManager,