Rizin
unix-like reverse engineering framework and cli tools
lzssd.c
Go to the documentation of this file.
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.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 
37 int 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 &&
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 */
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 }
size_t len
Definition: 6502dis.c:15
static unsigned invert(unsigned x)
Definition: aesdata.c:73
lzma_index ** i
Definition: index.h:629
#define MSPACK_ERR_OK
Definition: mspack.h:485
#define MSPACK_ERR_ARGS
Definition: mspack.h:487
#define MSPACK_ERR_NOMEMORY
Definition: mspack.h:497
unsigned char inbuf[SIZE]
Definition: gun.c:161
const char int mode
Definition: ioapi.h:137
return memset(p, 0, total)
#define LZSS_WINDOW_FILL
Definition: lzss.h:20
#define LZSS_WINDOW_SIZE
Definition: lzss.h:19
#define LZSS_MODE_EXPAND
Definition: lzss.h:22
#define LZSS_MODE_QBASIC
Definition: lzss.h:24
#define LZSS_MODE_MSHELP
Definition: lzss.h:23
int lzss_decompress(struct mspack_system *system, struct mspack_file *input, struct mspack_file *output, int input_buffer_size, int mode)
Definition: lzssd.c:37
#define WRITE_BYTE
Definition: lzssd.c:30
#define ENSURE_BYTES
Definition: lzssd.c:17
#define c(i)
Definition: sha256.c:43
void(* free)(void *ptr)
Definition: mspack.h:430
void *(* alloc)(struct mspack_system *self, size_t bytes)
Definition: mspack.h:421
int pos
Definition: main.c:11
struct _window window
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
diff_output_t output
Definition: zipcmp.c:237
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115