FreeCalypso > hg > freecalypso-reveng
view 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 source
/******************************************************************************* * * 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; }