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