summaryrefslogtreecommitdiff
path: root/src/libs/decomp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/decomp')
-rw-r--r--src/libs/decomp/Makeinfo2
-rw-r--r--src/libs/decomp/lzdecode.c415
-rw-r--r--src/libs/decomp/lzencode.c468
-rw-r--r--src/libs/decomp/lzh.h91
-rw-r--r--src/libs/decomp/update.c115
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 */
+}
+
+