/* Low-Level Startup Library Copyright 2001-2014 Green Hills Software, Inc. This program is the property of Green Hills Software, Inc, its contents are proprietary information and no part of it is to be disclosed to anyone except employees of Green Hills Software, Inc., or as agreed in writing signed by the President of Green Hills Software, Inc. */ /*----------------------------------------------------------------------*/ /* ind_uzip.c: ROM decompression code. */ /* */ /* CALLED FROM: __ghs_ind_crt0 */ /* ENTRY POINT: __ghs_decompress */ /* */ /* Decompression code based upon LZSS by Haruhiko Okumura */ /* */ /* This code was modified by GHS to not require a temporary ring buffer */ /*----------------------------------------------------------------------*/ #include "ind_startup.h" /* Data for the decompression algorithm used for CROM */ #define DECODE_N 4096 /* size of ring buffer */ #define DECODE_F 18 /* upper limit for match_length */ #define DECODE_THRESHOLD 2 /* encode string into position and length if match_length is greater than this */ /*----------------------------------------------------------------------*/ /* */ /* Decompress and Copy from CROM to RAM */ /* */ /*----------------------------------------------------------------------*/ syze_t __ghs_decompress(void *dst, const void *src, syze_t n) { int r,c; unsigned int flags; const unsigned char *s = (const unsigned char *)src; unsigned char *t = (unsigned char *)dst; const unsigned char *s_stop = s + n; unsigned char *t_start = t; /* Decompress and copy */ r = DECODE_N - DECODE_F; flags = 0; while (s < s_stop) { if (((flags >>= 1) & 0x100) == 0) { /* Flag byte describing the next sequence of 8 literals or dictionary references. */ c = *s++; /* Use the higher byte in flags to count to 8.*/ flags = c | 0xff00; } if (flags & 1) { /* Literal (byte): copy byte directly. */ c = *s++; *t++ = (char)c; r = ((r + 1) & (DECODE_N - 1)); } else { /* Pattern Reference: 2 bytes consisting of: 12 bits of offset (0..4095) 4 bits of length, representing lengths 3..18 */ unsigned char* pattern; int patoff, patlen, i; patoff = *s++; patlen = *s++; patoff |= ((patlen & 0xf0) << 4); patlen = (patlen & 0x0f) + DECODE_THRESHOLD + 1; pattern = t - (r - patoff); if (r <= patoff) pattern -= DECODE_N; /* The pattern >= t check is only necessary for the case where * we are unpacking within DECODE_F bytes of 0 and where addresses * are considered unsigned. In this case, pattern could be * a large positive value. */ for (i=0; (pattern < t_start || pattern >= t) && (i < patlen); i++) { *t++ = 0; pattern++; } /* Copy the pattern. */ for ( ; i < patlen; i++) { *t++ = *pattern++; } r = ((r + patlen) & (DECODE_N - 1)); } } /* Return the number of bytes written. */ return t - (unsigned char *)dst; }