History

avcodec/sanm: codec4/5/33/34 decoder

This codec works on 4x4 pixel tiles, which can be generated and read from the datastream. They're both identical, codec5 misses a tile index to skip the current tile. Codecs33/34 are the same as 4/5 but with a different tileset generator. Used only in Rebel Assault 1.

Manuel Lauss committed 1 year ago

Commit fb951b21 parent e1fd6bc1 file · +229 −0Browse files

Unified · Split

libavcodec/sanm.c+229−0
@@ -293,6 +293,8 @@ typedef struct SANMVideoContext { · 292 unmodified lines
293 int8_t p8x8glyphs[NGLYPHS][64];293 int8_t p8x8glyphs[NGLYPHS][64];
294 uint8_t c47itbl[0x10000];294 uint8_t c47itbl[0x10000];
295 uint8_t c23lut[256];295 uint8_t c23lut[256];
296 uint8_t c4tbl[2][256][16];
297 uint16_t c4param;
296} SANMVideoContext;298} SANMVideoContext;
297 299
298typedef struct SANMFrameHeader {300typedef struct SANMFrameHeader {
@@ -480,6 +482,142 @@ static av_cold int init_buffers(SANMVideoContext *ctx) · 181 unmodified lines
480 return 0;482 return 0;
481}483}
482 484
485static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
486{
487 uint8_t *dst = &(ctx->c4tbl[0][0][0]);
488 int i, j, k, l, m, n, o, p;
489
490 for (i = 0; i < 8; i++) {
491 for (k = 0; k < 8; k++) {
492 j = i + param1;
493 l = k + param1;
494 p = (j + k) / 2;
495 j = (j + p) / 2;
496 m = l / 2;
497 n = (i + param1);
498 o = (k + param1);
499
500 *dst++ = p; *dst++ = p; *dst++ = j; *dst++ = n;
501 *dst++ = p; *dst++ = p; *dst++ = j; *dst++ = i;
502 *dst++ = m; *dst++ = m; *dst++ = p; *dst++ = j;
503 *dst++ = l; *dst++ = l; *dst++ = m; *dst++ = p;
504 }
505 }
506
507 for (i = 0; i < 8; i++) {
508 for (k = 0; k < 8; k++) {
509 j = i + param1;
510 l = k + param1;
511 n = ((j + l) / 2);
512 m = ((l + n) / 2);
513
514 *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = j;
515 *dst++ = n; *dst++ = n; *dst++ = n; *dst++ = n;
516 *dst++ = m; *dst++ = m; *dst++ = m; *dst++ = m;
517 *dst++ = l; *dst++ = l; *dst++ = l; *dst++ = l;
518 }
519 }
520
521 for (i = 0; i < 8; i++) {
522 for (k = 0; k < 8; k++) {
523 j = i + param1;
524 l = k + param1;
525 m = (j + l) / 2;
526 n = (j + m) / 2;
527 o = m / 2;
528 p = j & 0xff;
529
530 *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = m;
531 *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = m;
532 *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
533 *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
534 }
535 }
536
537 for (i = 0; i < 8; i++) {
538 for (k = 0; k < 8; k++) {
539 j = i + param1;
540 l = k + param1;
541 m = (j + l) / 2;
542 n = m / 2;
543
544 *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
545 *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
546 *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
547 *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
548 }
549 }
550}
551
552static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
553{
554 uint8_t *dst = &(ctx->c4tbl[0][0][0]);
555 int i, j, k, l, m, n, o;
556
557 for (i = 1; i < 16; i += 2) {
558 for (k = 0; k < 16; k++) {
559 j = i + param1;
560 l = k + param1;
561 m = (j + l) / 2;
562 n = (j + m) / 2;
563 o = (l + m) / 2;
564 if (j == m || l == m) {
565 *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
566 *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = j;
567 *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
568 *dst++ = l; *dst++ = l; *dst++ = j; *dst++ = l;
569 } else {
570 *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
571 *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
572 *dst++ = o; *dst++ = o; *dst++ = m; *dst++ = n;
573 *dst++ = l; *dst++ = l; *dst++ = o; *dst++ = m;
574 }
575 }
576 }
577
578 for (i = 0; i < 16; i += 2) {
579 for (k = 0; k < 16; k++) {
580 j = i + param1;
581 l = k + param1;
582 m = (j + l) / 2;
583 n = (j + m) / 2;
584 o = (l + m) / 2;
585 if (m == j || m == l) {
586 *dst++ = j; *dst++ = j; *dst++ = l; *dst++ = j;
587 *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = l;
588 *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = l;
589 *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = l;
590 } else {
591 *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
592 *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
593 *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
594 *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
595 }
596 }
597 }
598}
599
600
601static int codec4_load_tiles(SANMVideoContext *ctx, uint16_t param2, uint8_t clr)
602{
603 uint8_t c, *dst = (uint8_t *)&(ctx->c4tbl[1][0][0]);
604 uint32_t loop = param2 * 8;
605
606 if (param2 > 256)
607 return AVERROR_INVALIDDATA;
608
609 if (bytestream2_get_bytes_left(&ctx->gb) < loop)
610 return AVERROR_INVALIDDATA;
611
612 while (loop--) {
613 c = bytestream2_get_byteu(&ctx->gb);
614 *dst++ = (c >> 4) + clr;
615 *dst++ = (c & 0xf) + clr;
616 }
617
618 return 0;
619}
620
483static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)621static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
484{622{
485 if (rotate_code == 2)623 if (rotate_code == 2)
@@ -519,6 +657,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 33 unmodified lines
519 if (ctx->subversion < 2)657 if (ctx->subversion < 2)
520 ctx->pal[0] = 0xFFU << 24;658 ctx->pal[0] = 0xFFU << 24;
521 }659 }
660 ctx->c4param = 0xffff;
522 661
523 return 0;662 return 0;
524}663}
@@ -532,6 +671,91 @@ static av_cold int decode_end(AVCodecContext *avctx) · 7 unmodified lines
532 return 0;671 return 0;
533}672}
534 673
674static int old_codec4(SANMVideoContext *ctx, int top, int left, int w, int h,
675 uint8_t param, uint16_t param2, int codec)
676{
677 const uint16_t p = ctx->pitch;
678 const uint32_t maxpxo = ctx->height * p;
679 uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->frm0;
680 int i, j, k, l, bit, ret;
681 int32_t pxoff, pxo2;
682
683 if (ctx->c4param != param) {
684 if (codec > 32)
685 codec33_gen_tiles(ctx, param);
686 else
687 codec4_gen_tiles(ctx, param);
688 ctx->c4param = param;
689 }
690 if (param2 > 0) {
691 ret = codec4_load_tiles(ctx, param2, param);
692 if (ret)
693 return ret;
694 }
695
696 if (codec > 32)
697 codec -= 29;
698
699 for (j = 0; j < w; j += 4) {
700 mask = bits = 0;
701 for (i = 0; i < h; i += 4) {
702 pxoff = j + left + ((top + i) * p);
703 if (param2 > 0) {
704 if (bits == 0) {
705 if (bytestream2_get_bytes_left(&ctx->gb) < 1)
706 return AVERROR_INVALIDDATA;
707 mask = bytestream2_get_byteu(&ctx->gb);
708 bits = 8;
709 }
710 bit = !!(mask & 0x80);
711 mask <<= 1;
712 bits--;
713 } else {
714 bit = 0;
715 }
716
717 if (bytestream2_get_bytes_left(&ctx->gb) < 1)
718 return AVERROR_INVALIDDATA;
719 idx = bytestream2_get_byteu(&ctx->gb);
720 if ((bit == 0) && (idx == 0x80) && (codec != 5))
721 continue;
722
723 gs = &(ctx->c4tbl[bit][idx][0]);
724 pxo2 = pxoff;
725 for (k = 0; k < 4; k++) {
726 for (l = 0; l < 4; l++) {
727 if (pxo2 >= 0 && pxo2 < maxpxo) {
728 *(dst + pxo2) = *gs;
729 }
730 gs++;
731 pxo2++;
732 }
733 pxo2 = pxo2 - 4 + p;
734 }
735
736 /* smooth top and left block borders with neighbours */
737 if (((pxoff - p + k) < 0) || ((pxoff - p + k) >= maxpxo)
738 || ((pxoff + 3 * p) < 0) || ((pxoff + 3 * p) >= maxpxo)
739 || (i == 0) || (j == 0))
740 continue;
741 if (param & 0x80) {
742 for (k = 0; k < 4; k++)
743 *(dst + pxoff + k) = ((*(dst + pxoff + k) + *(dst + pxoff - p + k)) >> 1) | 0x80;
744 *(dst + pxoff + 1 * p) = (*(dst + pxoff + 1 * p) + *(dst + pxoff + 1 * p - 1)) >> 1 | 0x80;
745 *(dst + pxoff + 2 * p) = (*(dst + pxoff + 2 * p) + *(dst + pxoff + 2 * p - 1)) >> 1 | 0x80;
746 *(dst + pxoff + 3 * p) = (*(dst + pxoff + 3 * p) + *(dst + pxoff + 3 * p - 1)) >> 1 | 0x80;
747 } else {
748 for (k = 0; k < 4; k++)
749 *(dst + pxoff + k) = ((*(dst + pxoff + k) + *(dst + pxoff - p + k)) >> 1) & 0x7f;
750 *(dst + pxoff + 1 * p) = (*(dst + pxoff + 1 * p) + *(dst + pxoff + 1 * p - 1)) >> 1;
751 *(dst + pxoff + 2 * p) = (*(dst + pxoff + 2 * p) + *(dst + pxoff + 2 * p - 1)) >> 1;
752 *(dst + pxoff + 3 * p) = (*(dst + pxoff + 3 * p) + *(dst + pxoff + 3 * p - 1)) >> 1;
753 }
754 }
755 }
756 return 0;
757}
758
535static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)759static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
536{760{
537 int opcode, color, run_len, left = out_size;761 int opcode, color, run_len, left = out_size;
@@ -1436,6 +1660,11 @@ static int process_frame_obj(SANMVideoContext *ctx) · 898 unmodified lines
1436 return old_codec1(ctx, top, left, w, h, codec == 3);1660 return old_codec1(ctx, top, left, w, h, codec == 3);
1437 case 2:1661 case 2:
1438 return old_codec2(ctx, top, left, w, h);1662 return old_codec2(ctx, top, left, w, h);
1663 case 4:
1664 case 5:
1665 case 33:
1666 case 34:
1667 return old_codec4(ctx, top, left, w, h, param, parm2, codec);
1439 case 21:1668 case 21:
1440 return old_codec21(ctx, top, left, w, h);1669 return old_codec21(ctx, top, left, w, h);
1441 case 23:1670 case 23:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t