diff options
Diffstat (limited to 'src/libs/decomp')
-rw-r--r-- | src/libs/decomp/Makeinfo | 2 | ||||
-rw-r--r-- | src/libs/decomp/lzdecode.c | 415 | ||||
-rw-r--r-- | src/libs/decomp/lzencode.c | 468 | ||||
-rw-r--r-- | src/libs/decomp/lzh.h | 91 | ||||
-rw-r--r-- | src/libs/decomp/update.c | 115 |
5 files changed, 1091 insertions, 0 deletions
diff --git a/src/libs/decomp/Makeinfo b/src/libs/decomp/Makeinfo new file mode 100644 index 0000000..699a24e --- /dev/null +++ b/src/libs/decomp/Makeinfo @@ -0,0 +1,2 @@ +uqm_CFILES="lzdecode.c lzencode.c update.c" +uqm_HFILES="lzh.h" diff --git a/src/libs/decomp/lzdecode.c b/src/libs/decomp/lzdecode.c new file mode 100644 index 0000000..3b64a90 --- /dev/null +++ b/src/libs/decomp/lzdecode.c @@ -0,0 +1,415 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /* + * LZHUF.C English version 1.0 + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "lzh.h" +#include "libs/reslib.h" + +PLZHCODE_DESC _lpCurCodeDesc; +STREAM_TYPE _StreamType; +BYTE* _Stream; +UWORD _workbuf; +BYTE _workbuflen; + +/* get one bit */ +static SWORD +GetBit (void) +{ + SWORD i; + + while (_workbuflen <= 8) + { + if ((i = InChar ()) < 0) + i = 0; + _workbuf |= i << (8 - _workbuflen); + _workbuflen += 8; + } + i = (_workbuf & 0xFFFF) >> (16 - 1); + _workbuf = (_workbuf << 1) & 0xFFFF; + _workbuflen--; + + return (i); +} + +static UWORD +GetBits (BYTE num_bits) +{ + SWORD i; + + while (_workbuflen <= 8) + { + if ((i = InChar ()) < 0) + i = 0; + _workbuf |= i << (8 - _workbuflen); + _workbuflen += 8; + } + i = (_workbuf & 0xFFFF) >> (16 - num_bits); + _workbuf = (_workbuf << num_bits) & 0xFFFF; + _workbuflen -= num_bits; + + return (i); +} + +/* initialize freq tree */ + +void +StartHuff (void) +{ + COUNT i, j; + + for (i = 0; i < N_CHAR; i++) + { + _lpCurCodeDesc->freq[i] = 1; + _lpCurCodeDesc->son[i] = i + T; + _lpCurCodeDesc->prnt[i + T] = i; + } + i = 0; j = N_CHAR; + while (j <= R) + { + _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[i + 1]; + _lpCurCodeDesc->son[j] = i; + _lpCurCodeDesc->prnt[i] = _lpCurCodeDesc->prnt[i + 1] = j; + i += 2; j++; + } + _lpCurCodeDesc->freq[T] = 0xffff; + _lpCurCodeDesc->prnt[R] = 0; +} + +DECODE_REF +copen (void *InStream, STREAM_TYPE SType, STREAM_MODE SMode) +{ + DWORD StreamLength; + + _StreamType = SType; + _Stream = InStream; + if (SMode == STREAM_WRITE) /* writing */ + { + OutChar (0); /* skip future StreamLength */ + OutChar (0); + OutChar (0); + OutChar (0); + + StreamLength = 0; + } + else /* reading */ + { + BYTE lobyte, hibyte; + UWORD loword, hiword; + + lobyte = (BYTE)InChar (); + hibyte = (BYTE)InChar (); + loword = MAKE_WORD (lobyte, hibyte); + lobyte = (BYTE)InChar (); + hibyte = (BYTE)InChar (); + hiword = MAKE_WORD (lobyte, hibyte); + + StreamLength = MAKE_DWORD (loword, hiword); + } + + if (StreamLength == 0xFFFFFFFF + || (_lpCurCodeDesc = AllocCodeDesc ()) == NULL) + { + FreeCodeDesc (_lpCurCodeDesc); + _lpCurCodeDesc = NULL; + } + else + { + _lpCurCodeDesc->Stream = _Stream; + _lpCurCodeDesc->StreamType = _StreamType; + _lpCurCodeDesc->StreamMode = SMode; + _lpCurCodeDesc->StreamLength = StreamLength; + _lpCurCodeDesc->buf_index = N - F; + memset (&_lpCurCodeDesc->text_buf[0], ' ', N - F); + + StartHuff (); + } + + return ((DECODE_REF)_lpCurCodeDesc); +} + +DWORD +cclose (PLZHCODE_DESC lpCodeDesc) +{ + _lpCurCodeDesc = lpCodeDesc; + if (_lpCurCodeDesc) + { + DWORD StreamIndex; + + if (_lpCurCodeDesc->CleanupFunc) + (*_lpCurCodeDesc->CleanupFunc) (); + + StreamIndex = lpCodeDesc->StreamIndex; + FreeCodeDesc (lpCodeDesc); + _lpCurCodeDesc = NULL; + + return (StreamIndex); + } + + return (0); +} + +void +cfilelength (PLZHCODE_DESC lpCodeDesc, DWORD *pfilelen) +{ + if (lpCodeDesc == 0) + *pfilelen = 0; + else + *pfilelen = lpCodeDesc->StreamLength; +} + + /* decoder table */ +static const BYTE d_code[256] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, + 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, + 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, + 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, +}; +static const BYTE d_len[256] = +{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +}; + + /* decode upper 6 bits from given table */ +#define DecodePosition(p) \ +{ \ + while (_workbuflen <= 8) \ + { \ + *(p) = InChar (); \ + _workbuf |= *(p) << (8 - _workbuflen); \ + _workbuflen += 8; \ + } \ + *(p) = HIBYTE (_workbuf); \ + _workbuf = (_workbuf << 8) & 0xFFFF; \ + _workbuflen -= 8; \ + \ + /* input lower 6 bits directly */ \ + j = d_len[*(p)]; \ + *(p) = ((UWORD)d_code[*(p)] << 6) \ + | (((*(p) << j) | GetBits (j)) & 0x3f); \ +} + + /* start searching tree from the root to leaves. + * choose node #(son[]) if input bit == 0 + * else choose #(son[]+1) (input bit == 1) + */ +#define DecodeChar(c) \ +{ \ + for (*(c) = lpCodeDesc->son[R]; \ + *(c) < T; \ + *(c) = lpCodeDesc->son[*(c) + GetBit ()]) \ + ; \ + _update (*(c)); \ + *(c) -= T; \ +} + +COUNT +cread (void *buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc) +{ + COUNT r, j, i; + BYTE *lpStr; + + if ((_lpCurCodeDesc = lpCodeDesc) == 0) + return (0); + + size *= count; + if (lpCodeDesc->StreamIndex + size > lpCodeDesc->StreamLength) + { + size /= count; + count = (COUNT)((lpCodeDesc->StreamLength + - lpCodeDesc->StreamIndex) / size); + + size *= count; + } + + if (size == 0) + return (0); + + lpStr = (BYTE*)buf; + _StreamType = lpCodeDesc->StreamType; + + _Stream = lpCodeDesc->Stream; + _workbuf = lpCodeDesc->workbuf; + _workbuflen = lpCodeDesc->workbuflen; + + lpCodeDesc->StreamIndex += size; + r = lpCodeDesc->buf_index; + j = lpCodeDesc->bytes_left; + if (j) + { + lpCodeDesc->bytes_left = 0; + i = lpCodeDesc->restart_index; + + goto ReenterRun; + } + + do + { + COUNT c; + + DecodeChar (&c); + + if (c < 256) + { + size--; + + *lpStr++ = lpCodeDesc->text_buf[r++ & (N - 1)] = (BYTE)c; + } + else + { + COUNT copy_size; + + //i is a COUNT; + DecodePosition(&i); + i = r - i - 1; + j = c - 255 + THRESHOLD; +ReenterRun: + if (j > size) + { + lpCodeDesc->bytes_left = j - size; + lpCodeDesc->restart_index = i + size; + j = size; + } + + size -= j; + do + { + COUNT loc_size; + + i &= (N - 1); + r &= (N - 1); + if ((i < r && i + j > r) || (i > r && i + j > r + N)) + copy_size = (r - i) & (N - 1); + else if ((copy_size = j) > N) + copy_size = N; + + loc_size = copy_size; + if (i + loc_size > N) + { + COUNT k; + + k = N - i; + memcpy (lpStr, &lpCodeDesc->text_buf[i], k); + lpStr += k; + loc_size -= k; + i = 0; + } + + memcpy (lpStr, &lpCodeDesc->text_buf[i], loc_size); + lpStr += loc_size; + i += loc_size; + + lpStr -= copy_size; + + loc_size = copy_size; + if (r + loc_size > N) + { + COUNT k; + + k = N - r; + memcpy (&lpCodeDesc->text_buf[r], lpStr, k); + lpStr += k; + loc_size -= k; + r = 0; + } + + memcpy (&lpCodeDesc->text_buf[r], lpStr, loc_size); + lpStr += loc_size; + r += loc_size; + } while (j -= copy_size); + } + } while (size); + + lpCodeDesc->buf_index = r; + lpCodeDesc->Stream = _Stream; + lpCodeDesc->workbuf = _workbuf; + lpCodeDesc->workbuflen = _workbuflen; + + return (count); +} + diff --git a/src/libs/decomp/lzencode.c b/src/libs/decomp/lzencode.c new file mode 100644 index 0000000..e26f344 --- /dev/null +++ b/src/libs/decomp/lzencode.c @@ -0,0 +1,468 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /* + * LZHUF.C English version 1.0 + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE + */ + +#include <stdio.h> +#include "lzh.h" +#include "libs/reslib.h" + +static UWORD match_position, match_length; +static SWORD *lson; +static SWORD *rson; +static SWORD *dad; +static SWORD *encode_arrays; + +#define AllocEncodeArrays() \ + HCalloc ( \ + (((N + 1) + (N + 257) + (N + 1)) \ + * sizeof (lson[0]))) +#define FreeCodeArrays HFree + +static BOOLEAN +InitTree (void) +{ + if ((encode_arrays = AllocEncodeArrays ()) == NULL) + { + FreeCodeArrays (encode_arrays); + encode_arrays = NULL; + return (FALSE); + } + else + { + SWORD i; + + lson = encode_arrays; + rson = lson + (N + 1); + dad = rson + (N + 257); + + for (i = N + 1; i <= N + 256; i++) + rson[i] = NIL; /* root */ + for (i = 0; i < N; i++) + dad[i] = NIL; /* node */ + + return (TRUE); + } +} + +static void +InsertNode (SWORD r) +{ + SWORD p, cmp; + BYTE *lpBuf; + + cmp = 1; + lpBuf = _lpCurCodeDesc->text_buf; + p = N + 1 + lpBuf[r]; + rson[r] = lson[r] = NIL; + match_length = 0; + for (;;) + { + UWORD i; + + if (cmp >= 0) + { + if (rson[p] != NIL) + p = rson[p]; + else + { + rson[p] = r; + dad[r] = p; + return; + } + } + else + { + if (lson[p] != NIL) + p = lson[p]; + else + { + lson[p] = r; + dad[r] = p; + return; + } + } + + i = F; + { + SWORD _r, _p; + + _r = r; + _p = p; + while (--i && (cmp = lpBuf[++_r] - lpBuf[++_p]) == 0) + ; + } + if ((i = F - i) > THRESHOLD) + { + if (i > match_length) + { + match_position = ((r - p) & (N - 1)) - 1; + if ((match_length = i) >= F) + break; + } + else if (i == match_length) + { + if ((i = ((r - p) & (N - 1)) - 1) < match_position) + { + match_position = i; + } + } + } + } + dad[r] = dad[p]; + lson[r] = lson[p]; + rson[r] = rson[p]; + dad[lson[p]] = r; + dad[rson[p]] = r; + if (rson[dad[p]] == p) + rson[dad[p]] = r; + else + lson[dad[p]] = r; + dad[p] = NIL; /* remove p */ +} + +static void +DeleteNode (SWORD p) +{ + SWORD q; + + if (dad[p] == NIL) + return; /* unregistered */ + if (rson[p] == NIL) + q = lson[p]; + else if (lson[p] == NIL) + q = rson[p]; + else + { + q = lson[p]; + if (rson[q] != NIL) + { + do + { + q = rson[q]; + } while (rson[q] != NIL); + rson[dad[q]] = lson[q]; + dad[lson[q]] = dad[q]; + lson[q] = lson[p]; + dad[lson[p]] = q; + } + rson[q] = rson[p]; + dad[rson[p]] = q; + } + dad[q] = dad[p]; + if (rson[dad[p]] == p) + rson[dad[p]] = q; + else + lson[dad[p]] = q; + dad[p] = NIL; +} + +static void +Putcode (SWORD l, UWORD c) +{ + _workbuf |= c >> _workbuflen; + if ((_workbuflen += l) >= 8) + { + OutChar ((BYTE)(_workbuf >> 8)); + ++_lpCurCodeDesc->StreamIndex; + if ((_workbuflen -= 8) >= 8) + { + OutChar ((BYTE)(_workbuf)); + ++_lpCurCodeDesc->StreamIndex; + _workbuflen -= 8; + _workbuf = c << (l - _workbuflen); + } + else + { + _workbuf <<= 8; + } + _workbuf &= 0xFFFF; + } +} + +static void +EncodeChar (UWORD c) +{ + UWORD i; + SWORD j, k; + + i = 0; + j = 0; + k = _lpCurCodeDesc->prnt[c + T]; + + /* search connections from leaf node to the root */ + do + { + i >>= 1; + + /* + if node's address is odd, output 1 + else output 0 + */ + if (k & 1) + i += 0x8000; + + j++; + } while ((k = _lpCurCodeDesc->prnt[k]) != R); + Putcode (j, i); + _update (c + T); +} + +static void +EncodePosition (UWORD c) +{ + UWORD i; + /* + * Tables for encoding/decoding upper 6 bits of + * sliding dictionary pointer + */ + /* encoder table */ + static const BYTE p_len[64] = + { + 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 + }; + + static const BYTE p_code[64] = + { + 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, + 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, + 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, + 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, + 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, + 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + }; + + /* output upper 6 bits with encoding */ + i = c >> 6; + Putcode (p_len[i], (UWORD)p_code[i] << 8); + + /* output lower 6 bits directly */ + Putcode (6, (c & 0x3f) << 10); +} + +static void +UninitTree (void) +{ + if (_workbuflen) + { + OutChar ((BYTE)(_workbuf >> 8)); + ++_lpCurCodeDesc->StreamIndex; + } + + FreeCodeArrays (encode_arrays); + encode_arrays = NULL; + lson = NULL; + rson = NULL; + dad = NULL; +} + +static void +_encode_cleanup (void) +{ + UWORD r, s, last_match_length, len; + + _StreamType = _lpCurCodeDesc->StreamType; + _Stream = _lpCurCodeDesc->Stream; + _workbuf = _lpCurCodeDesc->workbuf; + _workbuflen = _lpCurCodeDesc->workbuflen; + + r = _lpCurCodeDesc->buf_index; + s = _lpCurCodeDesc->restart_index; + last_match_length = _lpCurCodeDesc->bytes_left; + if (_lpCurCodeDesc->StreamLength >= F) + len = F; + else + { + UWORD i; + + for (i = 1; i <= F; i++) + InsertNode (r - i); + InsertNode (r); + + len = (UWORD)_lpCurCodeDesc->StreamLength; + } + + while (1) + { + while (last_match_length--) + { + DeleteNode (s); + if (--len == 0) + { + BYTE lobyte, hibyte; + UWORD loword, hiword; + + UninitTree (); + + _lpCurCodeDesc->StreamIndex += 4; + /* rewind */ + if (_lpCurCodeDesc->StreamType == FILE_STREAM) + SeekResFile ((uio_Stream *)_Stream, + -(int)_lpCurCodeDesc->StreamIndex, SEEK_CUR); + else /* _lpCurCodeDesc->StreamType == MEMORY_STREAM */ + _Stream = (BYTE*)_Stream - _lpCurCodeDesc->StreamIndex; + + loword = LOWORD (_lpCurCodeDesc->StreamLength); + lobyte = LOBYTE (loword); + hibyte = HIBYTE (loword); + OutChar (lobyte); + OutChar (hibyte); + hiword = HIWORD (_lpCurCodeDesc->StreamLength); + lobyte = LOBYTE (hiword); + hibyte = HIBYTE (hiword); + OutChar (lobyte); + OutChar (hibyte); + + return; + } + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + InsertNode (r); + } + if (match_length > len) + match_length = len; + if (match_length <= THRESHOLD) + { + match_length = 1; + EncodeChar (_lpCurCodeDesc->text_buf[r]); + } + else + { + EncodeChar (255 - THRESHOLD + match_length); + EncodePosition (match_position); + } + last_match_length = match_length; + } +} + +COUNT +cwrite (const void *buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc) +{ + UWORD r, s, last_match_length; + BYTE *lpBuf; + const BYTE *lpStr; + + if ((_lpCurCodeDesc = lpCodeDesc) == 0 + || (size *= count) == 0) + return (0); + + _StreamType = lpCodeDesc->StreamType; + _Stream = lpCodeDesc->Stream; + _workbuf = lpCodeDesc->workbuf; + _workbuflen = lpCodeDesc->workbuflen; + lpStr = (const BYTE *) buf; + lpBuf = lpCodeDesc->text_buf; + + r = lpCodeDesc->buf_index; + s = lpCodeDesc->restart_index; + last_match_length = lpCodeDesc->bytes_left; + if (last_match_length) + { + lpCodeDesc->StreamLength += size; + goto EncodeRestart; + } + else if (lpCodeDesc->StreamLength < F) + { + UWORD i; + + if ((i = (UWORD)lpCodeDesc->StreamLength) == 0) + { + if (!InitTree ()) + return (0); + + _lpCurCodeDesc->StreamIndex = 0; + lpCodeDesc->CleanupFunc = _encode_cleanup; + } + + lpCodeDesc->StreamLength += size; + + for (; i < F && size; ++i, --size) + lpBuf[r + i] = *lpStr++; + if (i < F) + goto EncodeExit; + + for (i = 1; i <= F; i++) + InsertNode (r - i); + InsertNode (r); + if (size == 0) + goto EncodeExit; + } + else + lpCodeDesc->StreamLength += size; + + do + { + if (match_length > F) + match_length = F; + if (match_length <= THRESHOLD) + { + match_length = 1; + EncodeChar (lpBuf[r]); + } + else + { + EncodeChar (255 - THRESHOLD + match_length); + EncodePosition (match_position); + } + last_match_length = match_length; +EncodeRestart: + while (last_match_length && size) + { + BYTE c; + + --size; + --last_match_length; + + DeleteNode (s); + c = *lpStr++; + lpBuf[s] = c; + if (s < F - 1) + lpBuf[s + N] = c; + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + InsertNode (r); + } + } while (last_match_length == 0); + +EncodeExit: + lpCodeDesc->buf_index = r; + lpCodeDesc->restart_index = s; + lpCodeDesc->bytes_left = last_match_length; + + lpCodeDesc->Stream = _Stream; + lpCodeDesc->workbuf = _workbuf; + lpCodeDesc->workbuflen = _workbuflen; + + return (count); +} + diff --git a/src/libs/decomp/lzh.h b/src/libs/decomp/lzh.h new file mode 100644 index 0000000..8ebdef4 --- /dev/null +++ b/src/libs/decomp/lzh.h @@ -0,0 +1,91 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef LIBS_DECOMP_LZH_H_ +#define LIBS_DECOMP_LZH_H_ + +#include "libs/declib.h" +#include "libs/memlib.h" + +/* LZSS Parameters */ + +#define N 4096 /* Size of string buffer */ +#define F 16 /* Size of look-ahead buffer */ +//#define F 60 /* Size of look-ahead buffer */ +#define THRESHOLD 2 +#define NIL N /* End of tree's node */ + +/* Huffman coding parameters */ + +#define N_CHAR (256 - THRESHOLD + F) + /* character code (= 0..N_CHAR-1) */ +#define T (N_CHAR * 2 - 1) /* Size of table */ +#define R (T - 1) /* root position */ +#define MAX_FREQ 0x8000 + /* update when cumulative frequency */ + +struct _LZHCODE_DESC +{ + COUNT buf_index, restart_index, bytes_left; + BYTE text_buf[N + F - 1]; + /* reconstruct freq tree */ + COUNT freq[T + 1]; /* cumulative freq table */ + /* + * pointing parent nodes. + * area [T..(T + N_CHAR - 1)] are pointers for leaves + */ + COUNT prnt[T + N_CHAR]; + /* pointing children nodes (son[], son[] + 1)*/ + COUNT son[T]; + UWORD workbuf; + BYTE workbuflen; + + STREAM_TYPE StreamType; + + void *Stream; + DWORD StreamIndex, StreamLength; + + STREAM_MODE StreamMode; + PVOIDFUNC CleanupFunc; +}; + +typedef struct _LZHCODE_DESC LZHCODE_DESC; +typedef LZHCODE_DESC *PLZHCODE_DESC; + +#define InChar() (_StreamType == FILE_STREAM ? \ + GetResFileChar ((uio_Stream *)_Stream) : \ + (int)*_Stream++) +#define OutChar(c) (_StreamType == FILE_STREAM ? \ + PutResFileChar ((c), (uio_Stream *)_Stream) : \ + (*_Stream++ = (BYTE)(c))) + + +#define AllocCodeDesc() HCalloc (sizeof (LZHCODE_DESC)) +#define FreeCodeDesc HFree + +extern void _update (COUNT c); +extern void StartHuff (void); + +extern PLZHCODE_DESC _lpCurCodeDesc; +extern STREAM_TYPE _StreamType; +extern BYTE* _Stream; +extern UWORD _workbuf; +extern BYTE _workbuflen; + +#endif /* LIBS_DECOMP_LZH_H_ */ + diff --git a/src/libs/decomp/update.c b/src/libs/decomp/update.c new file mode 100644 index 0000000..13de988 --- /dev/null +++ b/src/libs/decomp/update.c @@ -0,0 +1,115 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include "lzh.h" + +static void +reconst (void) +{ + COUNT i, j; + + /* halven cumulative freq for leaf nodes */ + j = 0; + for (i = 0; i < T; i++) + { + if (_lpCurCodeDesc->son[i] >= T) + { + _lpCurCodeDesc->freq[j] = (_lpCurCodeDesc->freq[i] + 1) >> 1; + _lpCurCodeDesc->son[j] = _lpCurCodeDesc->son[i]; + j++; + } + } + /* make a tree : first, connect children nodes */ + for (i = 0, j = N_CHAR; j < T; i += 2, j++) + { + SWORD k; + UWORD f, l; + + k = i + 1; + f = _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[k]; + for (k = j - 1; f < _lpCurCodeDesc->freq[k]; k--) + ; + k++; + l = (j - k); + + memmove (_lpCurCodeDesc->freq + k + 1, _lpCurCodeDesc->freq + k, + sizeof(_lpCurCodeDesc->freq[0]) * l); + _lpCurCodeDesc->freq[k] = f; + memmove (_lpCurCodeDesc->son + k + 1, _lpCurCodeDesc->son + k, + sizeof(_lpCurCodeDesc->son[0]) * l); + _lpCurCodeDesc->son[k] = i; + } + /* connect parent nodes */ + for (i = 0; i < T; i++) + { + if ((j = _lpCurCodeDesc->son[i]) >= T) + _lpCurCodeDesc->prnt[j] = i; + else + _lpCurCodeDesc->prnt[j] = _lpCurCodeDesc->prnt[j + 1] = i; + } +} + + +/* update freq tree */ + +void +_update (COUNT c) +{ + PLZHCODE_DESC lpCD; + + if ((lpCD = _lpCurCodeDesc)->freq[R] == MAX_FREQ) + reconst (); + + c = lpCD->prnt[c]; + do + { + COUNT i, l; + + i = ++lpCD->freq[c]; + + /* swap nodes to keep the tree freq-ordered */ + if (i > lpCD->freq[l = c + 1]) + { + COUNT j; + + while (i > lpCD->freq[++l]) + ; + l--; + lpCD->freq[c] = lpCD->freq[l]; + lpCD->freq[l] = i; + + i = lpCD->son[c]; + j = lpCD->son[l]; + lpCD->son[l] = i; + lpCD->son[c] = j; + + lpCD->prnt[i] = l; + if (i < T) + lpCD->prnt[i + 1] = l; + + lpCD->prnt[j] = c; + if (j < T) + lpCD->prnt[j + 1] = c; + + c = l; + } + } while ((c = lpCD->prnt[c]) != 0); /* do it until reaching the root */ +} + + |