Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/ipe_artfile_utils/trunk/ipe32_lzw_decoder.old
Revision: 2
Committed: Thu Nov 8 11:19:36 2018 UTC (16 months, 2 weeks ago) by daniel-marschall
Content type: application/x-trash
File size: 3020 byte(s)
Log Message:
Initial release to SVN

File Contents

# Content
1 /**
2 * LZW Decoder for Imagination Pilots Entertainment 32-bit games (IPE32)
3 * - Eraser Turnabout by Imagination Pilots
4 * ART file packer and unpacker by Daniel Marschall, ViaThinkSoft (C) 2018
5 * Revision: 2018-02-02
6 **/
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <stdbool.h>
12
13 #include "ipe32_lzw_decoder.h"
14
15 #define MIN_CODESIZE 9
16 #define MAX_CODESIZE 13
17
18 #define CLEAR_CODE 0x100
19 #define END_CODE 0x101
20 #define NEXT_FREE_CODE 0x102
21 #define MAX_CODE 0x1FF
22
23 // Returns: Bytes written
24 uint32_t ipe32lzw_decode(unsigned char* arg_lzwInputBuffer, const size_t arg_maxReadBytes, unsigned char* arg_outputBuffer) {
25 thread_local static int dict_X[9030]={0}; // TODO: size?
26 thread_local static int dict_Y[9030]={0}; // TODO: size?
27 thread_local static unsigned char dict_Z[16000]={0}; // TODO: size?
28
29 int currentCode, prevCode, prevCode2;
30 int bitsInBuffer = 0;
31 int gelesenesDWORD = 0;
32 unsigned char* outputBuffer = arg_outputBuffer;
33 unsigned char* lastCompleteInputBufferPos = arg_lzwInputBuffer;
34 unsigned char* inputBufferEndPos = arg_lzwInputBuffer + arg_maxReadBytes;
35
36 uint32_t dictionaryEmpty = 1;
37 uint32_t code_size = MIN_CODESIZE;
38 uint32_t nextFreeCode = NEXT_FREE_CODE;
39 uint32_t currentMaxCode = MAX_CODE;
40
41 while (1) {
42 if (bitsInBuffer <= 24) {
43 if (lastCompleteInputBufferPos < inputBufferEndPos) {
44 gelesenesDWORD |= (unsigned int)*lastCompleteInputBufferPos << (24-bitsInBuffer);
45 lastCompleteInputBufferPos++;
46 }
47 bitsInBuffer += 8;
48 } else {
49 currentCode = (unsigned int)gelesenesDWORD >> ((32-code_size) & 0xFF);
50 gelesenesDWORD = (unsigned int)gelesenesDWORD << code_size;
51 bitsInBuffer -= code_size;
52
53 if (currentCode == END_CODE) {
54 return outputBuffer - arg_outputBuffer;
55 } else {
56 if (dictionaryEmpty == 1) {
57 dictionaryEmpty = 0;
58 prevCode = currentCode;
59 prevCode2 = currentCode;
60 *outputBuffer = currentCode & 0xFF;
61 outputBuffer++;
62 } else {
63 if (currentCode == CLEAR_CODE) {
64 dictionaryEmpty = 1;
65 code_size = 9;
66 nextFreeCode = 0x102;
67 currentMaxCode = 0x1FF;
68 } else {
69 int idx_Z = 0, code;
70 if (currentCode < nextFreeCode) {
71 code = currentCode;
72 } else {
73 code = prevCode;
74 dict_Z[idx_Z++] = prevCode2;
75 }
76
77 while (code > 0xFF) {
78 dict_Z[idx_Z++] = dict_X[code];
79 code = dict_Y[code];
80 }
81 dict_Z[idx_Z] = prevCode2 = code;
82
83 do {
84 *outputBuffer = dict_Z[idx_Z];
85 outputBuffer++;
86 } while (--idx_Z >= 0);
87
88 if (nextFreeCode <= currentMaxCode) {
89 dict_Y[nextFreeCode] = prevCode;
90 dict_X[nextFreeCode] = prevCode2;
91 nextFreeCode++;
92 if ((nextFreeCode == currentMaxCode) && (code_size < MAX_CODESIZE)) {
93 currentMaxCode = (1 << ++code_size) - 1;
94 }
95 }
96
97 prevCode = currentCode;
98 }
99 }
100 }
101 }
102 }
103 }

Properties

Name Value
svn:mime-type application/x-trash