Mercurial > hg > dmlib
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, |