comparison tools/lib64fmts.c @ 1722:de8e0a404c06

Refactor fmtDecodeTruePaintPacked() to use more generic DMGrowBuf functions now that they support backwards growing buffers, and get rid of dmReverseGetByte() and dmReversePutByte() helpers.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 06 Jun 2018 15:22:15 +0300
parents 95317672ff00
children 13fe4010623f
comparison
equal deleted inserted replaced
1721:c9a6f1dae756 1722:de8e0a404c06
421 // 421 //
422 // Based on disassembly of the depacker routine. Encoding seems to be 422 // Based on disassembly of the depacker routine. Encoding seems to be
423 // some kind of "improved RLE" variant with different modes and a 423 // some kind of "improved RLE" variant with different modes and a
424 // simplistic "codebook". 424 // simplistic "codebook".
425 // 425 //
426 static BOOL fmtTruePaintGetByte(const Uint8 *src, size_t *srcOffs, Uint8 *data, int *res, const int mode) 426 static int fmtTruePaintGetByte(DMGrowBuf *src, Uint8 *data, const int mode)
427 { 427 {
428 if (!dmReverseGetByte(src, srcOffs, data)) 428 if (!dmGrowBufGetU8(src, data))
429 { 429 {
430 *res = dmError(DMERR_INVALID_DATA, 430 return dmError(DMERR_INVALID_DATA,
431 "TruePaintRLE: Out of input data (N=%d)\n", mode); 431 "TruePaintRLE: Out of input data (N=%d)\n", mode);
432 return FALSE;
433 } 432 }
434 else 433 else
435 return TRUE; 434 return DMERR_OK;
436 } 435 }
437 436
438 437
439 static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *src, const DMC64ImageFormat *fmt) 438 static int fmtDecodeTruePaintPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt)
440 { 439 {
441 int res = DMERR_OK; 440 int res = DMERR_OK;
442 Uint8 *dst = NULL;
443 DMGrowBuf dstTmp;
444 const Uint8 *codeBook1, *codeBook2; 441 const Uint8 *codeBook1, *codeBook2;
445 size_t 442 DMGrowBuf dst, src;
446 srcOffs, dstOffs, 443 DMCompParams cfg;
447 dstLen = 0x4be8; 444 Uint8 data;
448 // 1b7e-67e8 decoded by original depacker 445
449 // 1c00-67e8 is the actual area used tho 446 cfg.func = fmt->name;
447 cfg.type = DM_COMP_RLE_MARKER;
448 cfg.flags = DM_RLE_BACKWARDS_OUTPUT | DM_RLE_BACKWARDS_INPUT;
449 cfg.rleMarkerB = 0xfe;
450
451 // 1b7e-67e8 decoded by original depacker
452 // 1c00-67e8 is the actual area used tho
453 cfg.flags |= DM_OUT_CROP_END;
454 cfg.cropOutLen = 0x67e8 - 0x1c00;
450 455
451 // Codebooks: #1 is trampoline table markers, #2 is RLE data table 456 // Codebooks: #1 is trampoline table markers, #2 is RLE data table
452 codeBook1 = src->data + 0x81 - 2; 457 codeBook1 = psrc->data + 0x81 - 2;
453 codeBook2 = src->data + 0x85 - 2; 458 codeBook2 = psrc->data + 0x85 - 2;
454 459
455 // Allocate output buffer 460 // Allocate output buffer
456 if ((dst = dmMalloc0(dstLen)) == NULL) 461 if ((res = dmGrowBufAlloc(&dst, 64*1024, 4*1024)) != DMERR_OK)
457 {
458 res = dmError(DMERR_MALLOC,
459 "Could not allocate memory for temporary decompression buffer.\n");
460 goto out; 462 goto out;
461 } 463
462 464 // As we need to modify the offs, etc. but not the data,
463 // Begin decompression 465 // we will just make a shallow copy of the DMGrowBuf struct
464 srcOffs = src->len; 466 dmGrowBufConstCopy(&src, psrc);
465 dstOffs = dstLen; 467 dmSetupRLEBuffers(&dst, &src, &cfg);
466 468
467 while (srcOffs > 0 && dstOffs > 0) 469 while ((res = fmtTruePaintGetByte(&src, &data, -1)) == DMERR_OK)
468 { 470 {
469 Uint8 data; 471 unsigned int count = 1;
470 int count = 1, scount;
471 BOOL found = FALSE; 472 BOOL found = FALSE;
472
473 if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, -1))
474 goto out;
475 473
476 for (int n = 0; n < 8; n++) 474 for (int n = 0; n < 8; n++)
477 if (codeBook1[n] == data && !found) 475 if (codeBook1[n] == data && !found)
478 { 476 {
479 found = TRUE; 477 found = TRUE;
480 switch (n) 478 switch (n)
481 { 479 {
482 case 4: // Y = 4, JTO = $0B 480 case 4: // Y = 4, JTO = $0B
483 if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) 481 if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK)
484 goto out; 482 goto out;
485 483
486 count = data; 484 count = data;
487 if (data == 0) 485 if (data == 0)
488 goto finish; 486 goto finish;
492 case 1: // Y = 1, JTO = $17 490 case 1: // Y = 1, JTO = $17
493 count += 2; 491 count += 2;
494 // fallthrough 492 // fallthrough
495 493
496 case 0: // Y = 0, JTO = $19 494 case 0: // Y = 0, JTO = $19
497 if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) 495 if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK)
498 goto out; 496 goto out;
499 break; 497 break;
500 498
501 case 2: // Y = 2, JTO = $07 499 case 2: // Y = 2, JTO = $07
502 if (!fmtTruePaintGetByte(src->data, &srcOffs, &data, &res, n)) 500 if ((res = fmtTruePaintGetByte(&src, &data, n)) != DMERR_OK)
503 goto out; 501 goto out;
504 502
505 count = data; 503 count = data;
506 // fallthrough 504 // fallthrough
507 505
515 data = codeBook2[n]; 513 data = codeBook2[n];
516 break; 514 break;
517 } 515 }
518 } 516 }
519 517
520 for (scount = count; count; count--) 518 if ((res = dmGenericRLEOutputRun(&dst, &cfg, data, count)) != DMERR_OK)
521 { 519 goto out;
522 if (!dmReversePutByte(dst, &dstOffs, data))
523 {
524 res = dmError(DMERR_INVALID_DATA,
525 "TruePaintRLE: Out of output space for run: %d x $%02x!\n",
526 scount, data);
527 goto out;
528 }
529 }
530 } 520 }
531 521
532 finish: 522 finish:
533 res = dmC64DecodeGenericBMP(img, dmGrowBufCreateFrom(&dstTmp, dst, dstLen), fmt); 523 dmFinishRLEBuffers(&dst, &src, &cfg);
524 res = dmC64DecodeGenericBMP(img, &dst, fmt);
534 525
535 out: 526 out:
536 dmFree(dst); 527 dmGrowBufFree(&dst);
537 return res; 528 return res;
538 } 529 }
539 530
540 531
541 #define XX2_MIN_SIZE 4000 532 #define XX2_MIN_SIZE 4000