1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "bladerunner/decompress_lzo.h"
24
25 namespace BladeRunner {
26
decode_count(const uint8 ** pp)27 static inline uint32 decode_count(const uint8 **pp) {
28 uint32 v = 0;
29 for (; !**pp; ++(*pp))
30 v += 255;
31
32 v += **pp;
33 ++(*pp);
34
35 return v;
36 }
37
copy(uint8 ** dst,const uint8 ** src,int count)38 static inline void copy(uint8 **dst, const uint8 **src, int count) {
39 assert(count > 0);
40
41 uint8 *d = *dst;
42 const uint8 *s = *src;
43
44 *dst += count;
45 *src += count;
46
47 do { *d++ = *s++; } while (--count);
48 }
49
decompress_lzo1x(const uint8 * in,size_t inLen,uint8 * out,size_t * outLen)50 int decompress_lzo1x(const uint8 *in, size_t inLen, uint8 *out, size_t *outLen) {
51 uint32 t;
52 uint8 *op;
53 const uint8 *ip, *m_pos;
54 const uint8 * const ip_end = in + inLen;
55
56 *outLen = 0;
57
58 op = out;
59 ip = in;
60
61 if (*ip > 17) {
62 t = *ip++ - 17;
63 if (t < 4)
64 goto match_next;
65 copy(&op, &ip, t);
66 goto first_literal_run;
67 }
68
69 for (;;) {
70 t = *ip++;
71 if (t >= 16)
72 goto match;
73
74 if (t == 0)
75 t = 15 + decode_count(&ip);
76 copy(&op, &ip, t + 3);
77
78 first_literal_run:
79 t = *ip++;
80 if (t >= 16)
81 goto match;
82 m_pos = op - 0x0801 - (t >> 2) - (*ip++ << 2);
83 copy(&op, &m_pos, 3);
84 goto match_done;
85
86 for (;;) {
87 match:
88 if (t >= 64) {
89 m_pos = op - 1 - ((t >> 2) & 7) - (*ip++ << 3);
90 t = (t >> 5) - 1;
91 goto copy_match;
92 } else if (t >= 32) {
93 t &= 31;
94 if (t == 0)
95 t = 31 + decode_count(&ip);
96 m_pos = op - 1 - (ip[0] >> 2) - (ip[1] << 6);
97 ip += 2;
98 } else if (t >= 16) {
99 m_pos = op - ((t & 8) << 11);
100 t &= 7;
101 if (t == 0)
102 t = 7 + decode_count(&ip);
103 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
104 ip += 2;
105 if (m_pos == op)
106 goto eof_found;
107 m_pos -= 0x4000;
108 } else {
109 m_pos = op - 1 - (t >> 2) - (*ip++ << 2);
110 copy(&op, &m_pos, 2);
111 goto match_done;
112 }
113
114 copy_match:
115 copy(&op, &m_pos, t + 2);
116
117 match_done:
118 t = ip[-2] & 3;
119 if (t == 0)
120 break;
121
122 match_next:
123 assert(t > 0 && t <= 3);
124 copy(&op, &ip, t);
125 t = *ip++;
126 }
127 }
128
129 eof_found:
130 *outLen = op - out;
131 return ip != ip_end;
132 }
133
134 } // End of namespace BladeRunner
135