Mercurial > touhou
comparison pytouhou/formats/pbg3.py @ 0:6b2c7af2384c
Hello Gensokyo _o/
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sun, 31 Jul 2011 21:32:12 +0200 |
parents | |
children | ab826bc29aa2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6b2c7af2384c |
---|---|
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 |