forked from magical/nlzss
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlzss.py
93 lines (79 loc) · 5.03 KB
/
lzss.py
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# adapted from http://code.google.com/p/dsdecmp/source/browse/trunk/CSharp/DSDecmp/Program.cs
import sys
from struct import pack, unpack
from cStringIO import StringIO
from array import array
def bits(byte):
return ((byte >> 7) & 1,
(byte >> 6) & 1,
(byte >> 5) & 1,
(byte >> 4) & 1,
(byte >> 3) & 1,
(byte >> 2) & 1,
(byte >> 1) & 1,
(byte) & 1)
def decompress(s):
return decompressfile(StringIO(s))
def decompressfile(f):
data = array('c')
def write(s):
data.extend(s)
def readbyte():
return ord(f.read(1))
b = readbyte()
assert b == 0x11
decompressed_size, = unpack("<L", f.read(3) + "\x00")
#print hex(decompressed_size)
while len(data) < decompressed_size:
b = readbyte()
if b == '\x00':
write(f.read(8))
continue
flags = bits(b)
for flag in flags:
if flag == 0:
write(f.read(1))
elif flag == 1:
b = readbyte()
indicator = b >> 4
if indicator == 0:
count = b << 4
b = readbyte()
count += b >> 4
count += 0x11
disp = (b & 0xf) << 8 # b >> 4 << 8
b = readbyte()
disp += b
elif indicator == 1:
count = (b & 0xf) << 12
b = readbyte()
count += b << 4
b = readbyte()
count += b >> 4
count += 0x111
disp = (b & 0xf) << 8
b = readbyte()
disp += b
else:
count = (b >> 4)
count += 1
disp = (b & 0xf) << 8
b = readbyte()
disp += b
#print count+3, disp, len(data)
for _ in range(count):
write(data[-disp-1])
else:
raise ValueError(flag)
if decompressed_size <= len(data):
break
assert len(data) == decompressed_size
extra = f.read()
assert len(extra) == 0, repr(extra)
return data.tostring()
def test():
stream = '\x110\x12\x00\x00RGCN\xff\xfe\x01\x01\x000 \x00\x00\x10\x00\x01\x00\x05RAHC \x0b\x0c \x01\x10\x03\x00\x00\x90\x01\x12\x00\x00\x18\xdd\xb0\x0f\x10\x16\x10\x0b\x11"\xa1 \x03\x82\x94\x10 \x12\x7f\x11 \x02\xc0\x01P)\xe0\x14\xe0\x1f0&\x00\xb0\x1f\xbf2\xf6\x01@F\x00\x10+\x04c\x02 \xcb0\xdf0\xe3\xb8 \xd3\x10P\xd7 \x06\x01\x90\x01333\x081#""\x00\xa0\x1e3""\x83\x02\xb0\x1f\x13\x11""3\x03 \xff1\xc3\xfb1\xc7Q]@\xebp\x03\x01 \xef1 \xc4\x00\xb0\x03\xaf\x000\x022!\x1b2"\'0\x03\x000"1\x1a\xdf0YP]2 \xe7\x00\x90\x03\x03\x12\xc5\x91\xdb\x000\x03\xfb\x01\x00\xff1\xe3!\xeb\x00\x82\x06#\x0f\x13\x00\x014 /\xbf!\xfd\x11B\x1fP\xe7\xb0\x07b\x1aq-\x04\xc0\xff\xff\x00p\xf7\x00\xc3\x94\x01\xb3\x073\x03\x00\xa0\x03\x00A\xfc!0\x80\x03\xff\xc1\xff!6"\xf7\x03\xc3\xff4\xa3\xb2\xf3s\x07c\x17\xfd\x03\x80\xff1\xef1\xf7\xb1\xfb0\xff`\xeb2"$\xfc2D2H0\x0bq\x03\x00\xf4r\x10\x00\xa6\x9c\x00\x11\xeb64\x04\xf7\x04F\x93\x01v\xc3\x01\x011\x9fF\xcb\xfff`\x03$\xbe\x00\xd6\x95\'8@\x03\x85\xe10\xabp\x03\xff\x03E>\x01\x02\xa2\xa1\x1b\x00\x00\x03\x05 \x7f\x00@wt\xe2\x05P\xff\xff\xb1sh\xc7a\x97\x07s*h\xf3\x01\x02_\x86\x1be+\xff\x01\xc5\xffu\x03\xaa#\xb5\xebu\x03\x01\xb9f\x05\x1d\x02J\xe3\xff\x00\x8ag\x00\x02\xe8J\xa5\x91K\x00\xc3\x14\x01\x1b\x1a\x00\x0bN;Q\xff\x07R6\x10\x07m\x84\x00T\xef\x94kl\xc8\x04w\nF_\x10\x06\xaf\xff' #'\xff'
#stream = '\x11@@\x00\x00RGCN\xff\xfe\x01\x01\x00@@\x00\x00\x10\x00\x02\x00\x04RAHC @\x0b \x00\x16\x03\x00\x00@\x01\x010\x07 \x1f\x18\xcd`\x0f\x10x\x00\x06\x11\x110\x01\x06x\x9d\x10P~?\x11\x11I\'\x06`\xfc\x06\x81\x02\xb0~\x06!\x83\xd0~\xff\x06\x02\x04\xf0~\x05\xe2\x85\x82z\x92\x04\x05\xc2\x84\x00\x10\xfe\x05\xc3\x86\xff\x00 \xfe\x05\xc3\x85\x000\xfe\x05\xa4\x87\x00@\xfe\x05\xa4\x86\x00P\xfe\x05\x85\x88\xe5\x00`\xfe\x05\x85\x87Vu33\xa0\x01\x13\x05\xb6\x89\x85F\xf51#""\x90\x013\x05\xa7\t\xa7V\xf61\xb0~"2\x05\xa7\x08\x06\xf0\x7fXt\xfe\x00@\xff\x05H\x8a\x06\xe0\x7fh\xf5\x00P\xff\x05)\t\xa0\x7f2\xffS\x83\x06\x90\x7f\xe0\t\x05J\tjt\x00P\x7f\x05+\x0bp\x7f\xff$\x7fTu\x06P\x7f5\x7fUu\x05\xd0\xff\x00\x19y\xc1\x7f\xdf\x05\x0c\n\x0f\xc0\x7f1\xf3\xff\x05\xe1\x7f4z\xc5\xff\x05\xe1\xff\xff\x88\x03\x10\x0e\xf0\x7fi\xff\x062\x7f\xba\xff\x062\xff\x80z\x05o\x05\xfe\x00\xd0\x7f\x05\xdfz\x0e0\x7f\xbf\xfb\x00\x01\xff\x05\x9a\x7fu\xff2\xff\x06\xb0\x7f6\xff\x06\x0f\x01\x00\xb0\x7f\x05\x9f~\x00Q\x7f\x05\x9e\xff\x00D\x7f\xff\x05\xae\xff\x06\x90\x7f\xa5\x01\xf5\x7f\x05@~\x07\x00\x7f\x9c\x02\xe6\x7f\xff\x05Q~\xa6\x82\xe4\x7f\x05`~\x9d\x03\xd4\x7f\x05p\xfe\xd7\x83\xff\x06\x10\xfe\x00>\x04\x05\xc0\xfe\x00Q\x00\x05\xa0~\x001\x00\x05\xb0\xfe\x002\x01\xff\x05\xc0~\x00\x12\x82\x05\xe0~\xf3\x03\x06\x00~\xdb\x08\x06 ~\xaf\x8a\xf0\x05\xd2z\x00\x0c\x0b\x06p}\x11u\xc0wSOPC@\x10o\xff \x00\x10\x00'
sys.stdout.write(decompress(stream))
if __name__ == '__main__':
test()