0
|
1 from pytouhou.utils.bitstream import BitStream
|
|
2 import pytouhou.utils.lzss as lzss
|
|
3
|
|
4
|
|
5 class PBG3BitStream(BitStream):
|
|
6 def read_int(self):
|
|
7 size = self.read(2)
|
|
8 return self.read((size + 1) * 8)
|
|
9
|
|
10
|
|
11 def read_string(self, maxsize):
|
|
12 string = []
|
|
13 for i in range(maxsize):
|
|
14 byte = self.read(8)
|
|
15 if byte == 0:
|
|
16 break
|
|
17 string.append(byte)
|
|
18 return ''.join(chr(byte) for byte in string)
|
|
19
|
|
20
|
|
21
|
|
22 class PBG3(object):
|
|
23 def __init__(self, entries, bitstream=None):
|
|
24 self.entries = entries
|
|
25 self.bitstream = bitstream #TODO
|
|
26
|
|
27
|
|
28 @classmethod
|
|
29 def read(cls, file):
|
|
30 magic = file.read(4)
|
|
31 if magic != b'PBG3':
|
|
32 raise Exception #TODO
|
|
33
|
|
34 bitstream = PBG3BitStream(file)
|
|
35 entries = {}
|
|
36
|
|
37 nb_entries = bitstream.read_int()
|
|
38 offset = bitstream.read_int()
|
|
39 bitstream.seek(offset)
|
|
40 for i in range(nb_entries):
|
|
41 unknown1 = bitstream.read_int()
|
|
42 unknown2 = bitstream.read_int()
|
|
43 checksum = bitstream.read_int() # Checksum of *compressed data*
|
|
44 offset = bitstream.read_int()
|
|
45 size = bitstream.read_int()
|
|
46 name = bitstream.read_string(255).decode('ascii')
|
|
47 entries[name] = (unknown1, unknown2, checksum, offset, size)
|
|
48
|
|
49 return PBG3(entries, bitstream)
|
|
50
|
|
51
|
|
52 def list_files(self):
|
|
53 return self.entries.keys()
|
|
54
|
|
55
|
|
56 def extract(self, filename, check=False):
|
|
57 unkwn1, unkwn2, checksum, offset, size = self.entries[filename]
|
|
58 self.bitstream.seek(offset)
|
|
59 data = lzss.decompress(self.bitstream, size)
|
|
60 if check:
|
|
61 # Checking the checksum
|
|
62 compressed_size = self.bitstream.io.tell() - offset
|
|
63 self.bitstream.seek(offset)
|
|
64 value = 0
|
|
65 for c in self.bitstream.io.read(compressed_size):
|
|
66 value += ord(c)
|
|
67 value &= 0xFFFFFFFF
|
|
68 if value != checksum:
|
|
69 print('Warning: corrupted data') #TODO
|
|
70 return data
|
|
71
|