forked from sikthehedgehog/mdtools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslz.c
76 lines (67 loc) · 2.18 KB
/
slz.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Required headers
#include <stdint.h>
//***************************************************************************
// decompress_slz
// Decompresses data stored in SLZ format
//---------------------------------------------------------------------------
// param out: where to store decompressed data
// param in: pointer to SLZ-compressed data
//***************************************************************************
void decompress_slz(uint8_t *out, const uint8_t *in) {
// Retrieve uncompressed size
uint16_t size = in[0] << 8 | in[1];
in += 2;
// To store the tokens
uint8_t num_tokens = 1;
uint8_t tokens;
// Go through all compressed data until we're done decompressing
while (size != 0) {
// Need more tokens?
num_tokens--;
if (num_tokens == 0) {
tokens = *in++;
num_tokens = 8;
}
// Compressed string?
if (tokens & 0x80) {
// Get distance and length
uint16_t dist = in[0] << 8 | in[1];
uint8_t len = dist & 0x0F;
dist = dist >> 4;
in += 2;
// Discount string length from size
size -= len + 3;
// Copy string using Duff's device
// Code looks crazy, doesn't it? :)
uint8_t *ptr = out - dist - 3;
switch (len) {
case 15: *out++ = *ptr++;
case 14: *out++ = *ptr++;
case 13: *out++ = *ptr++;
case 12: *out++ = *ptr++;
case 11: *out++ = *ptr++;
case 10: *out++ = *ptr++;
case 9: *out++ = *ptr++;
case 8: *out++ = *ptr++;
case 7: *out++ = *ptr++;
case 6: *out++ = *ptr++;
case 5: *out++ = *ptr++;
case 4: *out++ = *ptr++;
case 3: *out++ = *ptr++;
case 2: *out++ = *ptr++;
case 1: *out++ = *ptr++;
case 0: *out++ = *ptr++;
*out++ = *ptr++;
*out++ = *ptr++;
}
}
// Uncompressed byte?
else {
// Store byte as-is
*out++ = *in++;
size--;
}
// Go for next token
tokens += tokens;
}
}