FreeCalypso > hg > freecalypso-reveng
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fluid-mnf/lzdecode.c Sat Feb 29 05:36:07 2020 +0000 @@ -0,0 +1,142 @@ +/******************************************************************************* + * + * Simple LZ77 compressor (c) Texas Instruments, Jesper Pedersem TI-DK + * + * File format: + * --------------------------------------------------- + * | Tag | Data | Tag | Data | Tag | Data etc... + * --------------------------------------------------- + * + * Where TAG is 1 bit indicating how to interpret the following data + * (0 = uncompressed, 1 = compressed) + * + * Depending on TAG the Data is: + * 0 : One uncompressed char of raw data + * 1 : A length of and a pointer to a match in the previous data + * + * ---------------------------------------- + * Length + pointer = | Length (3 bits) | Position (12 bits) | + * ---------------------------------------- + * MSB LSB MSB LSB + * + * Compression threshold is 1 i.e. add 1 to Length to get the actual Length. + * + * It has been found that 5+14 bits is the most optimum for our kind of + * data, but we use only 3+12 bits for improoved speed. Compression is + * almost as good because we can set the threshold at 1 instead of 2 (2 char + * matches can be compressed to 12+3 bits) + * + * With a 12 bit position we can use 4K for the sliding window. Position + * indicates where the match exists as an absolute address into the + * window. This way we have a very simple "pseudo sliding window" which + * automatically enables RLE (Run Length Encoding). + * + * The code performs a "lazy" string search i.e. a match will be dropped if + * it prevents an even greater match for the very next string. This yeild + * slightly better compression (approx. 1%) at minor cost of compression + * speed - decompression time is the same! A second order lazy match could + * be implemented, but it gives an insignificant improovement of about 0.1% + * when compressing executeables + * + ******************************************************************************/ + +#if (TARGET == 0) +#include "fluid.h" +#include <stdlib.h> +#endif + +#include "lz.h" + + +/****************************************************************************** + * Globals + ******************************************************************************/ + + +/****************************************************************************** + * getchar/putchar + ******************************************************************************/ + +#define EOF -1 + +#define LZ_PUTCHAR(data) \ + *plz->buffer_out++ = data; \ + plz->buffer_out_size++; + + + +/****************************************************************************** + * Code + ******************************************************************************/ +uint8 get_byte(struct lz_s *plz) +{ + plz->buffer_in_size--; + return(*plz->buffer_in++); +} + +uint16 get_word(struct lz_s *plz) +{ + uint16 tmp; + + tmp = (*plz->buffer_in++) << 8; + tmp |= (*plz->buffer_in++); + plz->buffer_in_size -= 2; + return(tmp); +} + + +void decompress_init(struct lz_s *plz) +{ + plz->window_pos = 0; + plz->bitbuf = 0; + plz->bitbuf_size = 0; +} + +int decompress(struct lz_s *plz, + unsigned char *outbuf, unsigned char *inbuf, int size) +{ + int16 match_pos; + int16 match_len, i; + int8 ch; + uint8 tag_byte; + uint8 tag_pos; + uint16 tmp; + + + plz->buffer_out = outbuf; + plz->buffer_out_size = 0; + plz->buffer_in = inbuf; + plz->buffer_in_size = size; + + while(plz->buffer_in_size > 0) + { + tag_byte = get_byte(plz); + + for(tag_pos = 0x80; (plz->buffer_in_size > 0) && (tag_pos > 0x00); tag_pos >>= 0x01) + { + if(tag_byte & tag_pos) // Compressed? + { + tmp = get_word(plz); + match_len = (tmp >> POS_BITS) + THRESHOLD + 1; + match_pos = (tmp & POS_MASK); + for (i = 0; i < match_len; i++) + { + plz->window[plz->window_pos] = plz->window[WINDOW_MASK & (match_pos + i)]; + LZ_PUTCHAR(plz->window[plz->window_pos]); + plz->window_pos++; + plz->window_pos &= WINDOW_MASK; + } + } + else + { + ch = get_byte(plz); + plz->window[plz->window_pos] = ch; + LZ_PUTCHAR(ch); + plz->window_pos++; + plz->window_pos &= WINDOW_MASK; + } + } + } + return plz->buffer_out_size; +} +