Subversion Repositories ipe_artfile_utils

Rev

Blame | Last modification | View Log | RSS feed

  1. /**
  2.  * LZW Decoder for Imagination Pilots Entertainment 16-bit games (IPE16)
  3.  * - Blown Away - The Interactive Game by Imagination Pilots (BA)
  4.  * - Panic in the Park - The Interactive Game by Imagination Pilots (PiP)
  5.  * - Where's Waldo? At the Circus (Waldo1)
  6.  * ART file packer and unpacker by Daniel Marschall, ViaThinkSoft (C) 2014-2018
  7.  * Revision: 2018-02-15
  8.  *
  9.  * The code is based on "Cross platform GIF source code" (c) L. Patrick
  10.  * http://www.cs.usyd.edu.au/~graphapp/package/src/libgif/gif.c
  11.  * It was simplified and modified to encode IPE16-LZW instead of GIF-LZW.
  12.  * The game uses exactly the compressed stream as defined in the GIF standard,
  13.  * but the compressed stream is not divided into chunks.
  14.  **/
  15.  
  16. #include "ipe16_lzw_decoder.h"
  17. #include "utils.h"
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <stdbool.h>
  22.  
  23. Ipe16LZWDecoder* new_ipe16lzw_decoder(void) {
  24.         return (Ipe16LZWDecoder*)app_zero_alloc(sizeof(Ipe16LZWDecoder));
  25. }
  26.  
  27. void del_ipe16lzw_decoder(Ipe16LZWDecoder* decoder) {
  28.         free(decoder);
  29. }
  30.  
  31. void ipe16lzw_init_decoder(Ipe16LZWDecoder* decoder) {
  32.         decoder->running_code = FIRST_CODE;
  33.         decoder->running_bits = LZ_MIN_BITS;
  34.         decoder->max_code_plus_one = 1 << decoder->running_bits;
  35.         decoder->shift_state  = 0;
  36.         decoder->shift_data   = 0;
  37.  
  38.         int i;
  39.         for (i = 0; i <= LZ_MAX_CODE; i++) {
  40.                 decoder->prefix[i] = NO_SUCH_CODE;
  41.         }
  42. }
  43.  
  44. int ipe16lzw_read_code(FILE* inFile, Ipe16LZWDecoder* decoder) {
  45.         int code;
  46.         unsigned char next_byte;
  47.         static int code_masks[] = {
  48.                 0x0000, 0x0001, 0x0003, 0x0007,
  49.                 0x000f, 0x001f, 0x003f, 0x007f,
  50.                 0x00ff, 0x01ff, 0x03ff, 0x07ff,
  51.                 0x0fff
  52.         };
  53.  
  54.         while (decoder->shift_state < decoder->running_bits) {
  55.                 next_byte = read_byte(inFile);
  56.                 decoder->shift_data |=
  57.                   ((unsigned long) next_byte) << decoder->shift_state;
  58.                 decoder->shift_state += 8;
  59.         }
  60.  
  61.         code = decoder->shift_data & code_masks[decoder->running_bits];
  62.  
  63.         decoder->shift_data >>= decoder->running_bits;
  64.         decoder->shift_state -= decoder->running_bits;
  65.  
  66.         if (++decoder->running_code > decoder->max_code_plus_one
  67.                 && decoder->running_bits < LZ_MAX_BITS) {
  68.                 decoder->max_code_plus_one <<= 1;
  69.                 decoder->running_bits++;
  70.         }
  71.  
  72.         return code;
  73. }
  74.  
  75. static int ipe16lzw_trace_prefix(unsigned int* prefix, int code, int clear_code) {
  76.         int i = 0;
  77.  
  78.         while (code > clear_code && i++ <= LZ_MAX_CODE) {
  79.                 code = prefix[code];
  80.         }
  81.         return code;
  82. }
  83.  
  84. // We don't do unsigned, because we want to have <0 as error result
  85. /*unsigned*/ int ipe16lzw_decode(FILE* inFile, Ipe16LZWDecoder* decoder, unsigned char* output, int outputLength) {
  86.         int i = 0, j;
  87.         int current_code;
  88.         int current_prefix;
  89.         int stack_ptr = 0;
  90.         int prev_code = NO_SUCH_CODE;
  91.         unsigned char* stack;
  92.         unsigned int* prefix;
  93.         unsigned int* suffix;
  94.         unsigned int bytes_written = 0;
  95.  
  96.         ipe16lzw_init_decoder(decoder);
  97.  
  98.         prefix          = decoder->prefix;
  99.         suffix          = decoder->suffix;
  100.         stack           = decoder->stack;
  101.  
  102.         /* Pop the stack */
  103.         while (stack_ptr != 0 && i < outputLength) {
  104.                 output[i++] = stack[--stack_ptr];
  105.                 //if (i > bytes_written) bytes_written = i;
  106.                 ++bytes_written;
  107.         }
  108.  
  109.         while (i < outputLength) {
  110.                 current_code = ipe16lzw_read_code(inFile, decoder);
  111.  
  112.                 if (current_code == END_CODE) {
  113.                         if (i != outputLength - 1) //  || decoder->pixel_count != 0
  114.                                 return -1; /* unexpected eof */
  115.                         i++;
  116.                 } else if (current_code == CLEAR_CODE) {
  117.                         for (j = 0; j <= LZ_MAX_CODE; j++) {
  118.                                 prefix[j] = NO_SUCH_CODE;
  119.                         }
  120.                         decoder->running_code = FIRST_CODE;
  121.                         decoder->running_bits = LZ_MIN_BITS;
  122.                         decoder->max_code_plus_one = 1 << decoder->running_bits;
  123.                         prev_code = NO_SUCH_CODE;
  124.                 } else {
  125.                         if (current_code < CLEAR_CODE) {
  126.                                 output[i++] = current_code;
  127.                                 //if (i > bytes_written) bytes_written = i;
  128.                                 ++bytes_written;
  129.                         } else {
  130.                                 if ((current_code < 0) || (current_code > LZ_MAX_CODE))
  131.                                         return -2; /* image defect */
  132.                                 if (prefix[current_code] == NO_SUCH_CODE) {
  133.                                         if (current_code == decoder->running_code - 2) {
  134.                                                 current_prefix = prev_code;
  135.                                                 suffix[decoder->running_code - 2]
  136.                                                         = stack[stack_ptr++]
  137.                                                         = ipe16lzw_trace_prefix(prefix, prev_code, CLEAR_CODE);
  138.                                         } else {
  139.                                                 return -3; /* image defect */
  140.                                         }
  141.                                 } else {
  142.                                         current_prefix = current_code;
  143.                                 }
  144.                                 j = 0;
  145.                                 while (j++ <= LZ_MAX_CODE && current_prefix > CLEAR_CODE && current_prefix <= LZ_MAX_CODE) {
  146.                                         stack[stack_ptr++] = suffix[current_prefix];
  147.                                         current_prefix = prefix[current_prefix];
  148.                                 }
  149.                                 if (j >= LZ_MAX_CODE || current_prefix > LZ_MAX_CODE)
  150.                                         return -4; /* image defect */
  151.  
  152.                                 stack[stack_ptr++] = current_prefix;
  153.  
  154.                                 while (stack_ptr != 0 && i < outputLength) {
  155.                                         output[i++] = stack[--stack_ptr];
  156.                                         //if (i > bytes_written) bytes_written = i;
  157.                                         ++bytes_written;
  158.                                 }
  159.                         }
  160.                         if (prev_code != NO_SUCH_CODE) {
  161.                                 if ((decoder->running_code < 2) ||
  162.                                    (decoder->running_code > LZ_MAX_CODE+2))
  163.                                         return -5; /* image defect */
  164.                                 prefix[decoder->running_code - 2] = prev_code;
  165.  
  166.                                 if (current_code == decoder->running_code - 2) {
  167.                                         suffix[decoder->running_code - 2]
  168.                                                 = ipe16lzw_trace_prefix(prefix, prev_code, CLEAR_CODE);
  169.                                 } else {
  170.                                         suffix[decoder->running_code - 2]
  171.                                                 = ipe16lzw_trace_prefix(prefix, current_code, CLEAR_CODE);
  172.                                 }
  173.                         }
  174.                         prev_code = current_code;
  175.                 }
  176.         }
  177.  
  178.         return bytes_written;
  179. }
  180.