Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/inflate.hpp
2 views
1
#ifndef NALL_INFLATE_HPP
2
#define NALL_INFLATE_HPP
3
4
#include <setjmp.h>
5
6
namespace nall {
7
8
namespace puff {
9
inline int puff(
10
unsigned char *dest, unsigned long *destlen,
11
unsigned char *source, unsigned long *sourcelen
12
);
13
}
14
15
inline bool inflate(
16
uint8_t *target, unsigned targetLength,
17
const uint8_t *source, unsigned sourceLength
18
) {
19
unsigned long tl = targetLength, sl = sourceLength;
20
int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
21
return result == 0;
22
}
23
24
namespace puff {
25
26
//zlib/contrib/puff.c
27
//version 2.1*
28
//author: Mark Adler
29
//license: zlib
30
//ported by: byuu
31
32
//* I have corrected a bug in fixed(), where it was accessing uninitialized
33
// memory: calling construct() with lencode prior to initializing lencode.count
34
35
enum {
36
MAXBITS = 15,
37
MAXLCODES = 286,
38
MAXDCODES = 30,
39
FIXLCODES = 288,
40
MAXCODES = MAXLCODES + MAXDCODES,
41
};
42
43
struct state {
44
unsigned char *out;
45
unsigned long outlen;
46
unsigned long outcnt;
47
48
unsigned char *in;
49
unsigned long inlen;
50
unsigned long incnt;
51
int bitbuf;
52
int bitcnt;
53
54
jmp_buf env;
55
};
56
57
struct huffman {
58
short *count;
59
short *symbol;
60
};
61
62
inline int bits(state *s, int need) {
63
long val;
64
65
val = s->bitbuf;
66
while(s->bitcnt < need) {
67
if(s->incnt == s->inlen) longjmp(s->env, 1);
68
val |= (long)(s->in[s->incnt++]) << s->bitcnt;
69
s->bitcnt += 8;
70
}
71
72
s->bitbuf = (int)(val >> need);
73
s->bitcnt -= need;
74
75
return (int)(val & ((1L << need) - 1));
76
}
77
78
inline int stored(state *s) {
79
unsigned len;
80
81
s->bitbuf = 0;
82
s->bitcnt = 0;
83
84
if(s->incnt + 4 > s->inlen) return 2;
85
len = s->in[s->incnt++];
86
len |= s->in[s->incnt++] << 8;
87
if(s->in[s->incnt++] != (~len & 0xff) ||
88
s->in[s->incnt++] != ((~len >> 8) & 0xff)
89
) return 2;
90
91
if(s->incnt + len > s->inlen) return 2;
92
if(s->out != 0) {
93
if(s->outcnt + len > s->outlen) return 1;
94
while(len--) s->out[s->outcnt++] = s->in[s->incnt++];
95
} else {
96
s->outcnt += len;
97
s->incnt += len;
98
}
99
100
return 0;
101
}
102
103
inline int decode(state *s, huffman *h) {
104
int len, code, first, count, index, bitbuf, left;
105
short *next;
106
107
bitbuf = s->bitbuf;
108
left = s->bitcnt;
109
code = first = index = 0;
110
len = 1;
111
next = h->count + 1;
112
while(true) {
113
while(left--) {
114
code |= bitbuf & 1;
115
bitbuf >>= 1;
116
count = *next++;
117
if(code - count < first) {
118
s->bitbuf = bitbuf;
119
s->bitcnt = (s->bitcnt - len) & 7;
120
return h->symbol[index + (code - first)];
121
}
122
index += count;
123
first += count;
124
first <<= 1;
125
code <<= 1;
126
len++;
127
}
128
left = (MAXBITS + 1) - len;
129
if(left == 0) break;
130
if(s->incnt == s->inlen) longjmp(s->env, 1);
131
bitbuf = s->in[s->incnt++];
132
if(left > 8) left = 8;
133
}
134
135
return -10;
136
}
137
138
inline int construct(huffman *h, short *length, int n) {
139
int symbol, len, left;
140
short offs[MAXBITS + 1];
141
142
for(len = 0; len <= MAXBITS; len++) h->count[len] = 0;
143
for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++;
144
if(h->count[0] == n) return 0;
145
146
left = 1;
147
for(len = 1; len <= MAXBITS; len++) {
148
left <<= 1;
149
left -= h->count[len];
150
if(left < 0) return left;
151
}
152
153
offs[1] = 0;
154
for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len];
155
156
for(symbol = 0; symbol < n; symbol++) {
157
if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol;
158
}
159
160
return left;
161
}
162
163
inline int codes(state *s, huffman *lencode, huffman *distcode) {
164
int symbol, len;
165
unsigned dist;
166
static const short lens[29] = {
167
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
168
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
169
};
170
static const short lext[29] = {
171
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
172
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
173
};
174
static const short dists[30] = {
175
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
176
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
177
8193, 12289, 16385, 24577
178
};
179
static const short dext[30] = {
180
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
181
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
182
12, 12, 13, 13
183
};
184
185
do {
186
symbol = decode(s, lencode);
187
if(symbol < 0) return symbol;
188
if(symbol < 256) {
189
if(s->out != 0) {
190
if(s->outcnt == s->outlen) return 1;
191
s->out[s->outcnt] = symbol;
192
}
193
s->outcnt++;
194
} else if(symbol > 256) {
195
symbol -= 257;
196
if(symbol >= 29) return -10;
197
len = lens[symbol] + bits(s, lext[symbol]);
198
199
symbol = decode(s, distcode);
200
if(symbol < 0) return symbol;
201
dist = dists[symbol] + bits(s, dext[symbol]);
202
#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
203
if(dist > s->outcnt) return -11;
204
#endif
205
206
if(s->out != 0) {
207
if(s->outcnt + len > s->outlen) return 1;
208
while(len--) {
209
s->out[s->outcnt] =
210
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
211
dist > s->outcnt ? 0 :
212
#endif
213
s->out[s->outcnt - dist];
214
s->outcnt++;
215
}
216
} else {
217
s->outcnt += len;
218
}
219
}
220
} while(symbol != 256);
221
222
return 0;
223
}
224
225
inline int fixed(state *s) {
226
static int virgin = 1;
227
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
228
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
229
static huffman lencode, distcode;
230
231
if(virgin) {
232
int symbol = 0;
233
short lengths[FIXLCODES];
234
235
lencode.count = lencnt;
236
lencode.symbol = lensym;
237
distcode.count = distcnt;
238
distcode.symbol = distsym;
239
240
for(; symbol < 144; symbol++) lengths[symbol] = 8;
241
for(; symbol < 256; symbol++) lengths[symbol] = 9;
242
for(; symbol < 280; symbol++) lengths[symbol] = 7;
243
for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8;
244
construct(&lencode, lengths, FIXLCODES);
245
246
for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5;
247
construct(&distcode, lengths, MAXDCODES);
248
249
virgin = 0;
250
}
251
252
return codes(s, &lencode, &distcode);
253
}
254
255
inline int dynamic(state *s) {
256
int nlen, ndist, ncode, index, err;
257
short lengths[MAXCODES];
258
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
259
short distcnt[MAXBITS + 1], distsym[MAXDCODES];
260
huffman lencode, distcode;
261
static const short order[19] = {
262
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
263
};
264
265
lencode.count = lencnt;
266
lencode.symbol = lensym;
267
distcode.count = distcnt;
268
distcode.symbol = distsym;
269
270
nlen = bits(s, 5) + 257;
271
ndist = bits(s, 5) + 1;
272
ncode = bits(s, 4) + 4;
273
if(nlen > MAXLCODES || ndist > MAXDCODES) return -3;
274
275
for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3);
276
for(; index < 19; index++) lengths[order[index]] = 0;
277
278
err = construct(&lencode, lengths, 19);
279
if(err != 0) return -4;
280
281
index = 0;
282
while(index < nlen + ndist) {
283
int symbol, len;
284
285
symbol = decode(s, &lencode);
286
if(symbol < 16) {
287
lengths[index++] = symbol;
288
} else {
289
len = 0;
290
if(symbol == 16) {
291
if(index == 0) return -5;
292
len = lengths[index - 1];
293
symbol = 3 + bits(s, 2);
294
} else if(symbol == 17) {
295
symbol = 3 + bits(s, 3);
296
} else {
297
symbol = 11 + bits(s, 7);
298
}
299
if(index + symbol > nlen + ndist) return -6;
300
while(symbol--) lengths[index++] = len;
301
}
302
}
303
304
if(lengths[256] == 0) return -9;
305
306
err = construct(&lencode, lengths, nlen);
307
if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7;
308
309
err = construct(&distcode, lengths + nlen, ndist);
310
if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8;
311
312
return codes(s, &lencode, &distcode);
313
}
314
315
inline int puff(
316
unsigned char *dest, unsigned long *destlen,
317
unsigned char *source, unsigned long *sourcelen
318
) {
319
state s;
320
int last, type, err;
321
322
s.out = dest;
323
s.outlen = *destlen;
324
s.outcnt = 0;
325
326
s.in = source;
327
s.inlen = *sourcelen;
328
s.incnt = 0;
329
s.bitbuf = 0;
330
s.bitcnt = 0;
331
332
if(setjmp(s.env) != 0) {
333
err = 2;
334
} else {
335
do {
336
last = bits(&s, 1);
337
type = bits(&s, 2);
338
err = type == 0 ? stored(&s)
339
: type == 1 ? fixed(&s)
340
: type == 2 ? dynamic(&s)
341
: -1;
342
if(err != 0) break;
343
} while(!last);
344
}
345
346
if(err <= 0) {
347
*destlen = s.outcnt;
348
*sourcelen = s.incnt;
349
}
350
351
return err;
352
}
353
354
}
355
356
}
357
358
#endif
359
360