FreeCalypso > hg > freecalypso-reveng
comparison fluid-mnf/lzdecode.c @ 311:9cecc930d78f
fluid-mnf: original source from TI,
defenestrated line endings and rearranged directory structure,
but no *.[ch] source file content changes yet
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 29 Feb 2020 05:36:07 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
310:ae39d76d5b7a | 311:9cecc930d78f |
---|---|
1 /******************************************************************************* | |
2 * | |
3 * Simple LZ77 compressor (c) Texas Instruments, Jesper Pedersem TI-DK | |
4 * | |
5 * File format: | |
6 * --------------------------------------------------- | |
7 * | Tag | Data | Tag | Data | Tag | Data etc... | |
8 * --------------------------------------------------- | |
9 * | |
10 * Where TAG is 1 bit indicating how to interpret the following data | |
11 * (0 = uncompressed, 1 = compressed) | |
12 * | |
13 * Depending on TAG the Data is: | |
14 * 0 : One uncompressed char of raw data | |
15 * 1 : A length of and a pointer to a match in the previous data | |
16 * | |
17 * ---------------------------------------- | |
18 * Length + pointer = | Length (3 bits) | Position (12 bits) | | |
19 * ---------------------------------------- | |
20 * MSB LSB MSB LSB | |
21 * | |
22 * Compression threshold is 1 i.e. add 1 to Length to get the actual Length. | |
23 * | |
24 * It has been found that 5+14 bits is the most optimum for our kind of | |
25 * data, but we use only 3+12 bits for improoved speed. Compression is | |
26 * almost as good because we can set the threshold at 1 instead of 2 (2 char | |
27 * matches can be compressed to 12+3 bits) | |
28 * | |
29 * With a 12 bit position we can use 4K for the sliding window. Position | |
30 * indicates where the match exists as an absolute address into the | |
31 * window. This way we have a very simple "pseudo sliding window" which | |
32 * automatically enables RLE (Run Length Encoding). | |
33 * | |
34 * The code performs a "lazy" string search i.e. a match will be dropped if | |
35 * it prevents an even greater match for the very next string. This yeild | |
36 * slightly better compression (approx. 1%) at minor cost of compression | |
37 * speed - decompression time is the same! A second order lazy match could | |
38 * be implemented, but it gives an insignificant improovement of about 0.1% | |
39 * when compressing executeables | |
40 * | |
41 ******************************************************************************/ | |
42 | |
43 #if (TARGET == 0) | |
44 #include "fluid.h" | |
45 #include <stdlib.h> | |
46 #endif | |
47 | |
48 #include "lz.h" | |
49 | |
50 | |
51 /****************************************************************************** | |
52 * Globals | |
53 ******************************************************************************/ | |
54 | |
55 | |
56 /****************************************************************************** | |
57 * getchar/putchar | |
58 ******************************************************************************/ | |
59 | |
60 #define EOF -1 | |
61 | |
62 #define LZ_PUTCHAR(data) \ | |
63 *plz->buffer_out++ = data; \ | |
64 plz->buffer_out_size++; | |
65 | |
66 | |
67 | |
68 /****************************************************************************** | |
69 * Code | |
70 ******************************************************************************/ | |
71 uint8 get_byte(struct lz_s *plz) | |
72 { | |
73 plz->buffer_in_size--; | |
74 return(*plz->buffer_in++); | |
75 } | |
76 | |
77 uint16 get_word(struct lz_s *plz) | |
78 { | |
79 uint16 tmp; | |
80 | |
81 tmp = (*plz->buffer_in++) << 8; | |
82 tmp |= (*plz->buffer_in++); | |
83 plz->buffer_in_size -= 2; | |
84 return(tmp); | |
85 } | |
86 | |
87 | |
88 void decompress_init(struct lz_s *plz) | |
89 { | |
90 plz->window_pos = 0; | |
91 plz->bitbuf = 0; | |
92 plz->bitbuf_size = 0; | |
93 } | |
94 | |
95 int decompress(struct lz_s *plz, | |
96 unsigned char *outbuf, unsigned char *inbuf, int size) | |
97 { | |
98 int16 match_pos; | |
99 int16 match_len, i; | |
100 int8 ch; | |
101 uint8 tag_byte; | |
102 uint8 tag_pos; | |
103 uint16 tmp; | |
104 | |
105 | |
106 plz->buffer_out = outbuf; | |
107 plz->buffer_out_size = 0; | |
108 plz->buffer_in = inbuf; | |
109 plz->buffer_in_size = size; | |
110 | |
111 while(plz->buffer_in_size > 0) | |
112 { | |
113 tag_byte = get_byte(plz); | |
114 | |
115 for(tag_pos = 0x80; (plz->buffer_in_size > 0) && (tag_pos > 0x00); tag_pos >>= 0x01) | |
116 { | |
117 if(tag_byte & tag_pos) // Compressed? | |
118 { | |
119 tmp = get_word(plz); | |
120 match_len = (tmp >> POS_BITS) + THRESHOLD + 1; | |
121 match_pos = (tmp & POS_MASK); | |
122 for (i = 0; i < match_len; i++) | |
123 { | |
124 plz->window[plz->window_pos] = plz->window[WINDOW_MASK & (match_pos + i)]; | |
125 LZ_PUTCHAR(plz->window[plz->window_pos]); | |
126 plz->window_pos++; | |
127 plz->window_pos &= WINDOW_MASK; | |
128 } | |
129 } | |
130 else | |
131 { | |
132 ch = get_byte(plz); | |
133 plz->window[plz->window_pos] = ch; | |
134 LZ_PUTCHAR(ch); | |
135 plz->window_pos++; | |
136 plz->window_pos &= WINDOW_MASK; | |
137 } | |
138 } | |
139 } | |
140 return plz->buffer_out_size; | |
141 } | |
142 |