Mercurial > touhou
diff 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 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/formats/pbg3.py @@ -0,0 +1,71 @@ +from pytouhou.utils.bitstream import BitStream +import pytouhou.utils.lzss as lzss + + +class PBG3BitStream(BitStream): + def read_int(self): + size = self.read(2) + return self.read((size + 1) * 8) + + + def read_string(self, maxsize): + string = [] + for i in range(maxsize): + byte = self.read(8) + if byte == 0: + break + string.append(byte) + return ''.join(chr(byte) for byte in string) + + + +class PBG3(object): + def __init__(self, entries, bitstream=None): + self.entries = entries + self.bitstream = bitstream #TODO + + + @classmethod + def read(cls, file): + magic = file.read(4) + if magic != b'PBG3': + raise Exception #TODO + + bitstream = PBG3BitStream(file) + entries = {} + + nb_entries = bitstream.read_int() + offset = bitstream.read_int() + bitstream.seek(offset) + for i in range(nb_entries): + unknown1 = bitstream.read_int() + unknown2 = bitstream.read_int() + checksum = bitstream.read_int() # Checksum of *compressed data* + offset = bitstream.read_int() + size = bitstream.read_int() + name = bitstream.read_string(255).decode('ascii') + entries[name] = (unknown1, unknown2, checksum, offset, size) + + return PBG3(entries, bitstream) + + + def list_files(self): + return self.entries.keys() + + + def extract(self, filename, check=False): + unkwn1, unkwn2, checksum, offset, size = self.entries[filename] + self.bitstream.seek(offset) + data = lzss.decompress(self.bitstream, size) + if check: + # Checking the checksum + compressed_size = self.bitstream.io.tell() - offset + self.bitstream.seek(offset) + value = 0 + for c in self.bitstream.io.read(compressed_size): + value += ord(c) + value &= 0xFFFFFFFF + if value != checksum: + print('Warning: corrupted data') #TODO + return data +