rev |
line source |
pascal@18757
|
1 --- core/fs/loadhigh.c
|
pascal@18757
|
2 +++ core/fs/loadhigh.c
|
pascal@18757
|
3 @@ -36,6 +36,11 @@
|
pascal@18757
|
4 #include <minmax.h>
|
pascal@18757
|
5 #include "core.h"
|
pascal@18757
|
6 #include "fs.h"
|
pascal@18757
|
7 +#define LZLOAD ".c32 modules can be compressed with lz4 or lzma"
|
pascal@18757
|
8 +#ifdef LZLOAD
|
pascal@18757
|
9 +#include "../unlz4.c"
|
pascal@18757
|
10 +#include "../unlzma.c"
|
pascal@18757
|
11 +#endif
|
pascal@18757
|
12
|
pascal@18757
|
13 #define MAX_CHUNK (1 << 20) /* 1 MB */
|
pascal@18757
|
14
|
pascal@18801
|
15 @@ -51,6 +56,9 @@
|
pascal@18757
|
16 uint32_t sector_mask;
|
pascal@18757
|
17 size_t pad;
|
pascal@18757
|
18 uint32_t retflags = 0;
|
pascal@18757
|
19 +#ifdef LZLOAD
|
pascal@18757
|
20 + char *unpacked = (char *) regs->edi.l;
|
pascal@18757
|
21 +#endif
|
pascal@18757
|
22
|
pascal@18757
|
23 bytes = regs->eax.l;
|
pascal@18757
|
24 zero_mask = regs->edx.w[0];
|
pascal@18801
|
25 @@ -101,6 +109,27 @@
|
pascal@18757
|
26 break;
|
pascal@18757
|
27 }
|
pascal@18757
|
28 }
|
pascal@18757
|
29 +
|
pascal@18757
|
30 +#ifdef LZLOAD
|
pascal@18757
|
31 + switch (* (short *) unpacked) {
|
pascal@18757
|
32 + char *packed;
|
pascal@18801
|
33 + size_t packedsz, unpackedsz;
|
pascal@18757
|
34 + case 0x005D:
|
pascal@18801
|
35 + packedsz = buf - unpacked;
|
pascal@18801
|
36 + unpackedsz = * (unsigned long *) (unpacked + 5);
|
pascal@18801
|
37 + if (unpackedsz > 1000000) break; /* no size? */
|
pascal@18801
|
38 + packed = unpacked + unpackedsz - packedsz + 1024;
|
pascal@18801
|
39 + if (packed < unpacked + 1024) packed = unpacked + 1024;
|
pascal@18801
|
40 + memmove(packed, unpacked, packedsz);
|
pascal@18801
|
41 + unlzma(packed, unpacked, packed + packedsz /* heap */);
|
pascal@18757
|
42 + buf = packed;
|
pascal@18757
|
43 + break;
|
pascal@18757
|
44 + case 0x2204:
|
pascal@18757
|
45 + case 0x2102:
|
pascal@18759
|
46 + buf = (char *) unlz4((unsigned char *) unpacked, (unsigned char *) buf);
|
pascal@18757
|
47 + break;
|
pascal@18757
|
48 + }
|
pascal@18757
|
49 +#endif
|
pascal@18757
|
50
|
pascal@18757
|
51 pad = (size_t)buf & zero_mask;
|
pascal@18757
|
52 if (pad)
|
pascal@18757
|
53 --- /dev/null
|
pascal@18757
|
54 +++ core/unlzma.c
|
pascal@18759
|
55 @@ -0,0 +1,385 @@
|
pascal@18757
|
56 +typedef unsigned char uint8_t;
|
pascal@18757
|
57 +typedef unsigned short uint16_t;
|
pascal@18757
|
58 +typedef unsigned uint32_t;
|
pascal@18757
|
59 +typedef unsigned long long uint64_t;
|
pascal@18757
|
60 +typedef unsigned size_t;
|
pascal@18757
|
61 +#define SWAP_LE32(x) (x)
|
pascal@18757
|
62 +#define SWAP_LE64(x) (x)
|
pascal@18757
|
63 +/* vi: set sw=4 ts=4: */
|
pascal@18757
|
64 +/*
|
pascal@18757
|
65 + * Small lzma deflate implementation.
|
pascal@18757
|
66 + * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
|
pascal@18757
|
67 + *
|
pascal@18757
|
68 + * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
|
pascal@18757
|
69 + * Copyright (C) 1999-2005 Igor Pavlov
|
pascal@18757
|
70 + *
|
pascal@18757
|
71 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
pascal@18757
|
72 + */
|
pascal@18757
|
73 +
|
pascal@18759
|
74 +#include <string.h>
|
pascal@18759
|
75 +
|
pascal@18757
|
76 +#define PACKED __attribute__ ((packed))
|
pascal@18757
|
77 +#define ALWAYS_INLINE inline
|
pascal@18757
|
78 +#define speed_inline
|
pascal@18757
|
79 +#define size_inline ALWAYS_INLINE
|
pascal@18757
|
80 +
|
pascal@18757
|
81 +
|
pascal@18757
|
82 +typedef struct {
|
pascal@18757
|
83 + uint8_t *ptr;
|
pascal@18757
|
84 +
|
pascal@18757
|
85 + uint32_t code;
|
pascal@18757
|
86 + uint32_t range;
|
pascal@18757
|
87 + uint32_t bound;
|
pascal@18757
|
88 +} rc_t;
|
pascal@18757
|
89 +
|
pascal@18757
|
90 +#define RC_TOP_BITS 24
|
pascal@18757
|
91 +#define RC_MOVE_BITS 5
|
pascal@18757
|
92 +#define RC_MODEL_TOTAL_BITS 11
|
pascal@18757
|
93 +
|
pascal@18757
|
94 +/* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */
|
pascal@18757
|
95 +static void rc_do_normalize(rc_t *rc)
|
pascal@18757
|
96 +{
|
pascal@18757
|
97 + rc->range <<= 8;
|
pascal@18757
|
98 + rc->code = (rc->code << 8) | *rc->ptr++;
|
pascal@18757
|
99 +}
|
pascal@18757
|
100 +
|
pascal@18757
|
101 +static ALWAYS_INLINE void rc_normalize(rc_t *rc)
|
pascal@18757
|
102 +{
|
pascal@18757
|
103 + if (rc->range < (1 << RC_TOP_BITS)) {
|
pascal@18757
|
104 + rc_do_normalize(rc);
|
pascal@18757
|
105 + }
|
pascal@18757
|
106 +}
|
pascal@18757
|
107 +
|
pascal@18757
|
108 +/* Called once */
|
pascal@18757
|
109 +static void rc_init(rc_t *rc) /*, int buffer_size) */
|
pascal@18757
|
110 +{
|
pascal@18757
|
111 + int i;
|
pascal@18757
|
112 +
|
pascal@18757
|
113 + rc->range = 0;
|
pascal@18757
|
114 + for (i = 0; i < 5; i++) {
|
pascal@18757
|
115 + rc_do_normalize(rc);
|
pascal@18757
|
116 + }
|
pascal@18757
|
117 + rc->range = 0xffffffff;
|
pascal@18757
|
118 +}
|
pascal@18757
|
119 +
|
pascal@18757
|
120 +/* rc_is_bit_1 is called 9 times */
|
pascal@18757
|
121 +static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
|
pascal@18757
|
122 +{
|
pascal@18757
|
123 + rc_normalize(rc);
|
pascal@18757
|
124 + rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
|
pascal@18757
|
125 + if (rc->code < rc->bound) {
|
pascal@18757
|
126 + rc->range = rc->bound;
|
pascal@18757
|
127 + *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
|
pascal@18757
|
128 + return 0;
|
pascal@18757
|
129 + }
|
pascal@18757
|
130 + rc->range -= rc->bound;
|
pascal@18757
|
131 + rc->code -= rc->bound;
|
pascal@18757
|
132 + *p -= *p >> RC_MOVE_BITS;
|
pascal@18757
|
133 + return 1;
|
pascal@18757
|
134 +}
|
pascal@18757
|
135 +
|
pascal@18757
|
136 +/* Called 4 times in unlzma loop */
|
pascal@18757
|
137 +static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
|
pascal@18757
|
138 +{
|
pascal@18757
|
139 + int ret = rc_is_bit_1(rc, p);
|
pascal@18757
|
140 + *symbol = *symbol * 2 + ret;
|
pascal@18757
|
141 + return ret;
|
pascal@18757
|
142 +}
|
pascal@18757
|
143 +
|
pascal@18757
|
144 +/* Called once */
|
pascal@18757
|
145 +static ALWAYS_INLINE int rc_direct_bit(rc_t *rc)
|
pascal@18757
|
146 +{
|
pascal@18757
|
147 + rc_normalize(rc);
|
pascal@18757
|
148 + rc->range >>= 1;
|
pascal@18757
|
149 + if (rc->code >= rc->range) {
|
pascal@18757
|
150 + rc->code -= rc->range;
|
pascal@18757
|
151 + return 1;
|
pascal@18757
|
152 + }
|
pascal@18757
|
153 + return 0;
|
pascal@18757
|
154 +}
|
pascal@18757
|
155 +
|
pascal@18757
|
156 +/* Called twice */
|
pascal@18757
|
157 +static speed_inline void
|
pascal@18757
|
158 +rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol)
|
pascal@18757
|
159 +{
|
pascal@18757
|
160 + int i = num_levels;
|
pascal@18757
|
161 +
|
pascal@18757
|
162 + *symbol = 1;
|
pascal@18757
|
163 + while (i--)
|
pascal@18757
|
164 + rc_get_bit(rc, p + *symbol, symbol);
|
pascal@18757
|
165 + *symbol -= 1 << num_levels;
|
pascal@18757
|
166 +}
|
pascal@18757
|
167 +
|
pascal@18757
|
168 +
|
pascal@18757
|
169 +typedef struct {
|
pascal@18757
|
170 + uint8_t pos;
|
pascal@18757
|
171 + uint32_t dict_size;
|
pascal@18757
|
172 + uint64_t dst_size;
|
pascal@18757
|
173 +} PACKED lzma_header_t;
|
pascal@18757
|
174 +
|
pascal@18757
|
175 +
|
pascal@18757
|
176 +/* #defines will force compiler to compute/optimize each one with each usage.
|
pascal@18757
|
177 + * Have heart and use enum instead. */
|
pascal@18757
|
178 +enum {
|
pascal@18757
|
179 + LZMA_BASE_SIZE = 1846,
|
pascal@18757
|
180 + LZMA_LIT_SIZE = 768,
|
pascal@18757
|
181 +
|
pascal@18757
|
182 + LZMA_NUM_POS_BITS_MAX = 4,
|
pascal@18757
|
183 +
|
pascal@18757
|
184 + LZMA_LEN_NUM_LOW_BITS = 3,
|
pascal@18757
|
185 + LZMA_LEN_NUM_MID_BITS = 3,
|
pascal@18757
|
186 + LZMA_LEN_NUM_HIGH_BITS = 8,
|
pascal@18757
|
187 +
|
pascal@18757
|
188 + LZMA_LEN_CHOICE = 0,
|
pascal@18757
|
189 + LZMA_LEN_CHOICE_2 = (LZMA_LEN_CHOICE + 1),
|
pascal@18757
|
190 + LZMA_LEN_LOW = (LZMA_LEN_CHOICE_2 + 1),
|
pascal@18757
|
191 + LZMA_LEN_MID = (LZMA_LEN_LOW \
|
pascal@18757
|
192 + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))),
|
pascal@18757
|
193 + LZMA_LEN_HIGH = (LZMA_LEN_MID \
|
pascal@18757
|
194 + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))),
|
pascal@18757
|
195 + LZMA_NUM_LEN_PROBS = (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)),
|
pascal@18757
|
196 +
|
pascal@18757
|
197 + LZMA_NUM_STATES = 12,
|
pascal@18757
|
198 + LZMA_NUM_LIT_STATES = 7,
|
pascal@18757
|
199 +
|
pascal@18757
|
200 + LZMA_START_POS_MODEL_INDEX = 4,
|
pascal@18757
|
201 + LZMA_END_POS_MODEL_INDEX = 14,
|
pascal@18757
|
202 + LZMA_NUM_FULL_DISTANCES = (1 << (LZMA_END_POS_MODEL_INDEX >> 1)),
|
pascal@18757
|
203 +
|
pascal@18757
|
204 + LZMA_NUM_POS_SLOT_BITS = 6,
|
pascal@18757
|
205 + LZMA_NUM_LEN_TO_POS_STATES = 4,
|
pascal@18757
|
206 +
|
pascal@18757
|
207 + LZMA_NUM_ALIGN_BITS = 4,
|
pascal@18757
|
208 +
|
pascal@18757
|
209 + LZMA_MATCH_MIN_LEN = 2,
|
pascal@18757
|
210 +
|
pascal@18757
|
211 + LZMA_IS_MATCH = 0,
|
pascal@18757
|
212 + LZMA_IS_REP = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
|
pascal@18757
|
213 + LZMA_IS_REP_G0 = (LZMA_IS_REP + LZMA_NUM_STATES),
|
pascal@18757
|
214 + LZMA_IS_REP_G1 = (LZMA_IS_REP_G0 + LZMA_NUM_STATES),
|
pascal@18757
|
215 + LZMA_IS_REP_G2 = (LZMA_IS_REP_G1 + LZMA_NUM_STATES),
|
pascal@18757
|
216 + LZMA_IS_REP_0_LONG = (LZMA_IS_REP_G2 + LZMA_NUM_STATES),
|
pascal@18757
|
217 + LZMA_POS_SLOT = (LZMA_IS_REP_0_LONG \
|
pascal@18757
|
218 + + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
|
pascal@18757
|
219 + LZMA_SPEC_POS = (LZMA_POS_SLOT \
|
pascal@18757
|
220 + + (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)),
|
pascal@18757
|
221 + LZMA_ALIGN = (LZMA_SPEC_POS \
|
pascal@18757
|
222 + + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX),
|
pascal@18757
|
223 + LZMA_LEN_CODER = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)),
|
pascal@18757
|
224 + LZMA_REP_LEN_CODER = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS),
|
pascal@18757
|
225 + LZMA_LITERAL = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS),
|
pascal@18757
|
226 +};
|
pascal@18757
|
227 +
|
pascal@18757
|
228 +
|
pascal@18757
|
229 +void unlzma(char *from, char *to, char *heap)
|
pascal@18757
|
230 +{
|
pascal@18757
|
231 + lzma_header_t header;
|
pascal@18757
|
232 + int lc, pb, lp;
|
pascal@18757
|
233 + uint32_t pos_state_mask;
|
pascal@18757
|
234 + uint32_t literal_pos_mask;
|
pascal@18757
|
235 + uint16_t *p;
|
pascal@18757
|
236 + rc_t *rc = (rc_t *) heap;
|
pascal@18757
|
237 + int i;
|
pascal@18757
|
238 + uint8_t *buffer = (void *) to;
|
pascal@18757
|
239 + uint8_t previous_byte = 0;
|
pascal@18757
|
240 + size_t buffer_pos = 0;
|
pascal@18757
|
241 + int len = 0;
|
pascal@18757
|
242 + int state = 0;
|
pascal@18757
|
243 + uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
pascal@18757
|
244 +
|
pascal@18757
|
245 + memcpy(&header, from, sizeof(header));
|
pascal@18757
|
246 + from += sizeof(header);
|
pascal@18757
|
247 + heap += sizeof(*rc);
|
pascal@18757
|
248 + rc->ptr = (void *) from;
|
pascal@18757
|
249 +
|
pascal@18757
|
250 + i = header.pos / 9;
|
pascal@18757
|
251 + lc = header.pos % 9;
|
pascal@18757
|
252 + pb = i / 5;
|
pascal@18757
|
253 + lp = i % 5;
|
pascal@18757
|
254 + pos_state_mask = (1 << pb) - 1;
|
pascal@18757
|
255 + literal_pos_mask = (1 << lp) - 1;
|
pascal@18757
|
256 +
|
pascal@18757
|
257 + /* Example values from linux-3.3.4.tar.lzma:
|
pascal@18757
|
258 + * dict_size: 64M, dst_size: 2^64-1
|
pascal@18757
|
259 + */
|
pascal@18757
|
260 + header.dict_size = SWAP_LE32(header.dict_size);
|
pascal@18757
|
261 + header.dst_size = SWAP_LE64(header.dst_size);
|
pascal@18757
|
262 +
|
pascal@18757
|
263 + //if (header.dict_size == 0)
|
pascal@18757
|
264 + // header.dict_size++;
|
pascal@18757
|
265 +
|
pascal@18757
|
266 + rc_init(rc);
|
pascal@18757
|
267 +
|
pascal@18757
|
268 + {
|
pascal@18757
|
269 + int num_probs;
|
pascal@18757
|
270 +
|
pascal@18757
|
271 + num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
|
pascal@18757
|
272 + //p = xmalloc(num_probs * sizeof(*p));
|
pascal@18757
|
273 + p = (void *) heap;
|
pascal@18757
|
274 + num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
|
pascal@18757
|
275 + for (i = 0; i < num_probs; i++)
|
pascal@18757
|
276 + p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
|
pascal@18757
|
277 + }
|
pascal@18757
|
278 +
|
pascal@18757
|
279 +
|
pascal@18757
|
280 + while (buffer_pos < header.dst_size) {
|
pascal@18757
|
281 + int pos_state = buffer_pos & pos_state_mask;
|
pascal@18757
|
282 + uint16_t *prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
|
pascal@18757
|
283 +
|
pascal@18757
|
284 + if (!rc_is_bit_1(rc, prob)) {
|
pascal@18757
|
285 + static const char next_state[LZMA_NUM_STATES] =
|
pascal@18757
|
286 + { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
|
pascal@18757
|
287 + int mi = 1;
|
pascal@18757
|
288 +
|
pascal@18757
|
289 + prob = (p + LZMA_LITERAL
|
pascal@18757
|
290 + + (LZMA_LIT_SIZE * (((buffer_pos & literal_pos_mask) << lc)
|
pascal@18757
|
291 + + (previous_byte >> (8 - lc))
|
pascal@18757
|
292 + )
|
pascal@18757
|
293 + )
|
pascal@18757
|
294 + );
|
pascal@18757
|
295 +
|
pascal@18757
|
296 + if (state >= LZMA_NUM_LIT_STATES) {
|
pascal@18757
|
297 + int match_byte;
|
pascal@18757
|
298 + uint32_t pos = buffer_pos - rep0;
|
pascal@18757
|
299 +
|
pascal@18757
|
300 + while (pos >= header.dict_size)
|
pascal@18757
|
301 + pos += header.dict_size;
|
pascal@18757
|
302 + match_byte = buffer[pos];
|
pascal@18757
|
303 + do {
|
pascal@18757
|
304 + int bit;
|
pascal@18757
|
305 +
|
pascal@18757
|
306 + match_byte <<= 1;
|
pascal@18757
|
307 + bit = match_byte & 0x100;
|
pascal@18757
|
308 + bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
|
pascal@18757
|
309 + if (bit)
|
pascal@18757
|
310 + break;
|
pascal@18757
|
311 + } while (mi < 0x100);
|
pascal@18757
|
312 + }
|
pascal@18757
|
313 + while (mi < 0x100) {
|
pascal@18757
|
314 + rc_get_bit(rc, prob + mi, &mi);
|
pascal@18757
|
315 + }
|
pascal@18757
|
316 +
|
pascal@18757
|
317 + state = next_state[state];
|
pascal@18757
|
318 +
|
pascal@18757
|
319 + previous_byte = (uint8_t) mi;
|
pascal@18757
|
320 + len = 1;
|
pascal@18757
|
321 + goto one_byte2;
|
pascal@18757
|
322 + } else {
|
pascal@18757
|
323 + int num_bits;
|
pascal@18757
|
324 + int offset;
|
pascal@18757
|
325 + uint16_t *prob2;
|
pascal@18757
|
326 +#define prob_len prob2
|
pascal@18757
|
327 +
|
pascal@18757
|
328 + prob2 = p + LZMA_IS_REP + state;
|
pascal@18757
|
329 + if (!rc_is_bit_1(rc, prob2)) {
|
pascal@18757
|
330 + rep3 = rep2;
|
pascal@18757
|
331 + rep2 = rep1;
|
pascal@18757
|
332 + rep1 = rep0;
|
pascal@18757
|
333 + state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
|
pascal@18757
|
334 + prob2 = p + LZMA_LEN_CODER;
|
pascal@18757
|
335 + } else {
|
pascal@18757
|
336 + prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP;
|
pascal@18757
|
337 + if (!rc_is_bit_1(rc, prob2)) {
|
pascal@18757
|
338 + prob2 = (p + LZMA_IS_REP_0_LONG
|
pascal@18757
|
339 + + (state << LZMA_NUM_POS_BITS_MAX)
|
pascal@18757
|
340 + + pos_state
|
pascal@18757
|
341 + );
|
pascal@18757
|
342 + if (!rc_is_bit_1(rc, prob2)) {
|
pascal@18757
|
343 + state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
|
pascal@18757
|
344 + len = 1;
|
pascal@18757
|
345 + goto string;
|
pascal@18757
|
346 + }
|
pascal@18757
|
347 + } else {
|
pascal@18757
|
348 + uint32_t distance;
|
pascal@18757
|
349 +
|
pascal@18757
|
350 + prob2 += LZMA_IS_REP_G1 - LZMA_IS_REP_G0;
|
pascal@18757
|
351 + distance = rep1;
|
pascal@18757
|
352 + if (rc_is_bit_1(rc, prob2)) {
|
pascal@18757
|
353 + prob2 += LZMA_IS_REP_G2 - LZMA_IS_REP_G1;
|
pascal@18757
|
354 + distance = rep2;
|
pascal@18757
|
355 + if (rc_is_bit_1(rc, prob2)) {
|
pascal@18757
|
356 + distance = rep3;
|
pascal@18757
|
357 + rep3 = rep2;
|
pascal@18757
|
358 + }
|
pascal@18757
|
359 + rep2 = rep1;
|
pascal@18757
|
360 + }
|
pascal@18757
|
361 + rep1 = rep0;
|
pascal@18757
|
362 + rep0 = distance;
|
pascal@18757
|
363 + }
|
pascal@18757
|
364 + state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
|
pascal@18757
|
365 + prob2 = p + LZMA_REP_LEN_CODER;
|
pascal@18757
|
366 + }
|
pascal@18757
|
367 +
|
pascal@18757
|
368 + prob_len = prob2 + LZMA_LEN_CHOICE;
|
pascal@18757
|
369 + num_bits = LZMA_LEN_NUM_LOW_BITS;
|
pascal@18757
|
370 + if (!rc_is_bit_1(rc, prob_len)) {
|
pascal@18757
|
371 + prob_len += LZMA_LEN_LOW - LZMA_LEN_CHOICE
|
pascal@18757
|
372 + + (pos_state << LZMA_LEN_NUM_LOW_BITS);
|
pascal@18757
|
373 + offset = 0;
|
pascal@18757
|
374 + } else {
|
pascal@18757
|
375 + prob_len += LZMA_LEN_CHOICE_2 - LZMA_LEN_CHOICE;
|
pascal@18757
|
376 + if (!rc_is_bit_1(rc, prob_len)) {
|
pascal@18757
|
377 + prob_len += LZMA_LEN_MID - LZMA_LEN_CHOICE_2
|
pascal@18757
|
378 + + (pos_state << LZMA_LEN_NUM_MID_BITS);
|
pascal@18757
|
379 + offset = 1 << LZMA_LEN_NUM_LOW_BITS;
|
pascal@18757
|
380 + num_bits += LZMA_LEN_NUM_MID_BITS - LZMA_LEN_NUM_LOW_BITS;
|
pascal@18757
|
381 + } else {
|
pascal@18757
|
382 + prob_len += LZMA_LEN_HIGH - LZMA_LEN_CHOICE_2;
|
pascal@18757
|
383 + offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
|
pascal@18757
|
384 + + (1 << LZMA_LEN_NUM_MID_BITS));
|
pascal@18757
|
385 + num_bits += LZMA_LEN_NUM_HIGH_BITS - LZMA_LEN_NUM_LOW_BITS;
|
pascal@18757
|
386 + }
|
pascal@18757
|
387 + }
|
pascal@18757
|
388 + rc_bit_tree_decode(rc, prob_len, num_bits, &len);
|
pascal@18757
|
389 + len += offset;
|
pascal@18757
|
390 +
|
pascal@18757
|
391 + if (state < 4) {
|
pascal@18757
|
392 + int pos_slot;
|
pascal@18757
|
393 + uint16_t *prob3;
|
pascal@18757
|
394 +
|
pascal@18757
|
395 + state += LZMA_NUM_LIT_STATES;
|
pascal@18757
|
396 + prob3 = p + LZMA_POS_SLOT +
|
pascal@18757
|
397 + ((len < LZMA_NUM_LEN_TO_POS_STATES ? len :
|
pascal@18757
|
398 + LZMA_NUM_LEN_TO_POS_STATES - 1)
|
pascal@18757
|
399 + << LZMA_NUM_POS_SLOT_BITS);
|
pascal@18757
|
400 + rc_bit_tree_decode(rc, prob3,
|
pascal@18757
|
401 + LZMA_NUM_POS_SLOT_BITS, &pos_slot);
|
pascal@18757
|
402 + rep0 = pos_slot;
|
pascal@18757
|
403 + if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
|
pascal@18757
|
404 + int i2, mi2, num_bits2 = (pos_slot >> 1) - 1;
|
pascal@18757
|
405 + rep0 = 2 | (pos_slot & 1);
|
pascal@18757
|
406 + if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
|
pascal@18757
|
407 + rep0 <<= num_bits2;
|
pascal@18757
|
408 + prob3 = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
|
pascal@18757
|
409 + } else {
|
pascal@18757
|
410 + for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
|
pascal@18757
|
411 + rep0 = (rep0 << 1) | rc_direct_bit(rc);
|
pascal@18757
|
412 + rep0 <<= LZMA_NUM_ALIGN_BITS;
|
pascal@18757
|
413 + prob3 = p + LZMA_ALIGN;
|
pascal@18757
|
414 + }
|
pascal@18757
|
415 + i2 = 1;
|
pascal@18757
|
416 + mi2 = 1;
|
pascal@18757
|
417 + while (num_bits2--) {
|
pascal@18757
|
418 + if (rc_get_bit(rc, prob3 + mi2, &mi2))
|
pascal@18757
|
419 + rep0 |= i2;
|
pascal@18757
|
420 + i2 <<= 1;
|
pascal@18757
|
421 + }
|
pascal@18757
|
422 + }
|
pascal@18757
|
423 + if (++rep0 == 0)
|
pascal@18757
|
424 + break;
|
pascal@18757
|
425 + }
|
pascal@18757
|
426 +
|
pascal@18757
|
427 + len += LZMA_MATCH_MIN_LEN;
|
pascal@18757
|
428 + string:
|
pascal@18757
|
429 + do {
|
pascal@18757
|
430 + uint32_t pos = buffer_pos - rep0;
|
pascal@18757
|
431 + while (pos >= header.dict_size)
|
pascal@18757
|
432 + pos += header.dict_size;
|
pascal@18757
|
433 + previous_byte = buffer[pos];
|
pascal@18757
|
434 + one_byte2:
|
pascal@18757
|
435 + buffer[buffer_pos++] = previous_byte;
|
pascal@18757
|
436 + len--;
|
pascal@18757
|
437 + } while (len != 0 && buffer_pos < header.dst_size);
|
pascal@18757
|
438 + }
|
pascal@18757
|
439 + }
|
pascal@18757
|
440 +}
|
pascal@18757
|
441 --- /dev/null
|
pascal@18757
|
442 +++ core/unlz4.c
|
pascal@18759
|
443 @@ -0,0 +1,114 @@
|
pascal@18757
|
444 +/*
|
pascal@18757
|
445 + * Copyright (C) 2015, pascal.bellard@slitaz.org
|
pascal@18757
|
446 + *
|
pascal@18757
|
447 + * This program is free software; you can redistribute it and/or modify
|
pascal@18757
|
448 + * it under the terms of the GNU General Public License version 2 as
|
pascal@18757
|
449 + * published by the Free Software Foundation.
|
pascal@18757
|
450 + */
|
pascal@18757
|
451 +
|
pascal@18759
|
452 +#include <string.h>
|
pascal@18759
|
453 +
|
pascal@18757
|
454 +#define LZ4_MAGIC 0x184D2204 /* Spec 1.5.0 */
|
pascal@18757
|
455 +#define LZ4_LEGACY 0x184C2102
|
pascal@18757
|
456 +#define LZ4_SKIP(n) ((((n) - 0x184D2A50) >> 4) == 0)
|
pascal@18757
|
457 +
|
pascal@18757
|
458 +static unsigned lz4cnt(unsigned char **p, unsigned n)
|
pascal@18757
|
459 +{
|
pascal@18757
|
460 + int i;
|
pascal@18757
|
461 +
|
pascal@18757
|
462 + if (n == 0xF) do {
|
pascal@18757
|
463 + i = *(*p)++;
|
pascal@18757
|
464 + n += i;
|
pascal@18757
|
465 + } while (i == 0xFF);
|
pascal@18757
|
466 + return n;
|
pascal@18757
|
467 +}
|
pascal@18757
|
468 +
|
pascal@18759
|
469 +unsigned char *unlz4(unsigned char *from, unsigned char *end)
|
pascal@18757
|
470 +{
|
pascal@18757
|
471 + unsigned char *p, *end_chunk, *to, flags, mask;
|
pascal@18757
|
472 + long magic;
|
pascal@18757
|
473 + unsigned i, n, size;
|
pascal@18757
|
474 +
|
pascal@18757
|
475 + for (p = from, flags = size = 0; p < end;) {
|
pascal@18757
|
476 + while (1) {
|
pascal@18757
|
477 + magic = * (long *) p;
|
pascal@18757
|
478 + p += sizeof(long);
|
pascal@18757
|
479 + if (magic == LZ4_LEGACY) continue;
|
pascal@18757
|
480 + if (magic != LZ4_MAGIC) break;
|
pascal@18757
|
481 + flags = *p;
|
pascal@18757
|
482 + if (flags & 8) {
|
pascal@18757
|
483 + size = * (unsigned *) (p + 2);
|
pascal@18757
|
484 + goto sizefound;
|
pascal@18757
|
485 + }
|
pascal@18757
|
486 + p += 3; /* skip FLG BD HC */
|
pascal@18757
|
487 + }
|
pascal@18757
|
488 + if (LZ4_SKIP(magic)) {
|
pascal@18757
|
489 + p += 4 + * (long *) p;
|
pascal@18757
|
490 + continue;
|
pascal@18757
|
491 + }
|
pascal@18757
|
492 + mask = 4; /* Content checksum */
|
pascal@18757
|
493 + if (magic) {
|
pascal@18757
|
494 + if (magic > 0)
|
pascal@18757
|
495 + for (end_chunk = p + magic; p < end_chunk;) {
|
pascal@18757
|
496 + unsigned char token = *p++;
|
pascal@18757
|
497 +
|
pascal@18757
|
498 + n = lz4cnt(&p, token >> 4);
|
pascal@18757
|
499 + size += n;
|
pascal@18757
|
500 + p += n;
|
pascal@18757
|
501 + if (p >= end_chunk) break;
|
pascal@18757
|
502 + p += sizeof(unsigned short);
|
pascal@18757
|
503 + size += 4 + lz4cnt(&p, token & 0xF);
|
pascal@18757
|
504 + }
|
pascal@18757
|
505 + else {
|
pascal@18757
|
506 + magic &= 0x7FffFFff;
|
pascal@18757
|
507 + p += magic;
|
pascal@18757
|
508 + size += magic;
|
pascal@18757
|
509 + }
|
pascal@18757
|
510 + mask = 0x10; /* Block checksum */
|
pascal@18757
|
511 + }
|
pascal@18757
|
512 + if (flags & mask) p += 4; /* skip block checksum */
|
pascal@18757
|
513 + }
|
pascal@18757
|
514 +sizefound:
|
pascal@18757
|
515 + size += 16 - (p - from);
|
pascal@18757
|
516 + memmove(from + size, from, p - from);
|
pascal@18757
|
517 + for (to = from, p = from += size, end += size, flags = 0; p < end;) {
|
pascal@18757
|
518 + while (1) {
|
pascal@18757
|
519 + magic = * (long *) p;
|
pascal@18757
|
520 + p += sizeof(long);
|
pascal@18757
|
521 + if (magic == LZ4_LEGACY) continue;
|
pascal@18757
|
522 + if (magic != LZ4_MAGIC) break;
|
pascal@18757
|
523 + flags = *p;
|
pascal@18757
|
524 + if (flags & 8) p += 8; /* skip size */
|
pascal@18757
|
525 + p += 3; /* skip FLG BD HC */
|
pascal@18757
|
526 + }
|
pascal@18757
|
527 + if (LZ4_SKIP(magic)) {
|
pascal@18757
|
528 + p += 4 + * (long *) p;
|
pascal@18757
|
529 + continue;
|
pascal@18757
|
530 + }
|
pascal@18757
|
531 + mask = 4; /* Content checksum */
|
pascal@18757
|
532 + if (magic) {
|
pascal@18757
|
533 + if (magic > 0)
|
pascal@18757
|
534 + for (end_chunk = p + magic; p < end_chunk;) {
|
pascal@18758
|
535 + unsigned char *dico;
|
pascal@18757
|
536 + unsigned char token = *p++;
|
pascal@18757
|
537 +
|
pascal@18757
|
538 + n = lz4cnt(&p, token >> 4);
|
pascal@18757
|
539 + for (i = 0; i < n; i++)
|
pascal@18757
|
540 + *to++ = *p++;
|
pascal@18757
|
541 + if (p >= end_chunk) break;
|
pascal@18757
|
542 + dico = to - (* (unsigned short *) p);
|
pascal@18757
|
543 + p += sizeof(unsigned short);
|
pascal@18757
|
544 + n = 4 + lz4cnt(&p, token & 0xF);
|
pascal@18757
|
545 + for (i = 0; i < n; i++)
|
pascal@18757
|
546 + *to++ = *dico++;
|
pascal@18757
|
547 + }
|
pascal@18757
|
548 + else for (end_chunk = p + (magic & 0x7FffFFff);
|
pascal@18757
|
549 + p < end_chunk;) {
|
pascal@18757
|
550 + *to++ = *p++;
|
pascal@18757
|
551 + }
|
pascal@18757
|
552 + mask = 0x10; /* Block checksum */
|
pascal@18757
|
553 + }
|
pascal@18757
|
554 + if (flags & mask) p += 4; /* Skip checksum */
|
pascal@18757
|
555 + }
|
pascal@18757
|
556 + return to;
|
pascal@18757
|
557 +}
|