summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/mspack/lzssd.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/mspack/lzssd.c')
-rw-r--r--utils/rbutilqt/mspack/lzssd.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/utils/rbutilqt/mspack/lzssd.c b/utils/rbutilqt/mspack/lzssd.c
new file mode 100644
index 0000000000..63716d414a
--- /dev/null
+++ b/utils/rbutilqt/mspack/lzssd.c
@@ -0,0 +1,93 @@
1/* This file is part of libmspack.
2 * (C) 2003-2010 Stuart Caie.
3 *
4 * LZSS is a derivative of LZ77 and was created by James Storer and
5 * Thomas Szymanski in 1982. Haruhiko Okumura wrote a very popular C
6 * implementation.
7 *
8 * libmspack is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License (LGPL) version 2.1
10 *
11 * For further details, see the file COPYING.LIB distributed with libmspack
12 */
13
14#include "system-mspack.h"
15#include "lzss.h"
16
17#define ENSURE_BYTES do { \
18 if (i_ptr >= i_end) { \
19 read = system->read(input, &inbuf[0], \
20 input_buffer_size); \
21 if (read <= 0) { \
22 system->free(window); \
23 return (read < 0) ? MSPACK_ERR_READ \
24 : MSPACK_ERR_OK; \
25 } \
26 i_ptr = &inbuf[0]; i_end = &inbuf[read]; \
27 } \
28} while (0)
29
30#define WRITE_BYTE do { \
31 if (system->write(output, &window[pos], 1) != 1) { \
32 system->free(window); \
33 return MSPACK_ERR_WRITE; \
34 } \
35} while (0)
36
37int lzss_decompress(struct mspack_system *system,
38 struct mspack_file *input,
39 struct mspack_file *output,
40 int input_buffer_size,
41 int mode)
42{
43 unsigned char *window, *inbuf, *i_ptr, *i_end;
44 unsigned int pos, i, c, invert, mpos, len;
45 int read;
46
47 /* check parameters */
48 if (!system || input_buffer_size < 1 || (mode != LZSS_MODE_EXPAND &&
49 mode != LZSS_MODE_MSHELP && mode != LZSS_MODE_QBASIC))
50 {
51 return MSPACK_ERR_ARGS;
52 }
53
54 /* allocate memory */
55 window = (unsigned char *) system->alloc(system, LZSS_WINDOW_SIZE + input_buffer_size);
56 if (!window) return MSPACK_ERR_NOMEMORY;
57
58 /* initialise decompression */
59 inbuf = &window[LZSS_WINDOW_SIZE];
60 memset(window, LZSS_WINDOW_FILL, (size_t) LZSS_WINDOW_SIZE);
61 pos = LZSS_WINDOW_SIZE - ((mode == LZSS_MODE_QBASIC) ? 18 : 16);
62 invert = (mode == LZSS_MODE_MSHELP) ? ~0 : 0;
63 i_ptr = i_end = &inbuf[0];
64
65 /* loop forever; exit condition is in ENSURE_BYTES macro */
66 for (;;) {
67 ENSURE_BYTES; c = *i_ptr++ ^ invert;
68 for (i = 0x01; i & 0xFF; i <<= 1) {
69 if (c & i) {
70 /* literal */
71 ENSURE_BYTES; window[pos] = *i_ptr++;
72 WRITE_BYTE;
73 pos++; pos &= LZSS_WINDOW_SIZE - 1;
74 }
75 else {
76 /* match */
77 ENSURE_BYTES; mpos = *i_ptr++;
78 ENSURE_BYTES; mpos |= (*i_ptr & 0xF0) << 4;
79 len = (*i_ptr++ & 0x0F) + 3;
80 while (len--) {
81 window[pos] = window[mpos];
82 WRITE_BYTE;
83 pos++; pos &= LZSS_WINDOW_SIZE - 1;
84 mpos++; mpos &= LZSS_WINDOW_SIZE - 1;
85 }
86 }
87 }
88 }
89
90 /* not reached */
91 system->free(window);
92 return MSPACK_ERR_OK;
93}