Mercurial > touhou
diff pytouhou/formats/t6rp.py @ 188:008f90ebfdc0
Fix replay handling and add support for encrypted replays
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Thu, 27 Oct 2011 14:24:07 +0200 |
parents | 46793ccfedca |
children | ba3297ab3bde |
line wrap: on
line diff
--- a/pytouhou/formats/t6rp.py +++ b/pytouhou/formats/t6rp.py @@ -13,6 +13,9 @@ ## from struct import unpack +from io import BytesIO + +from pytouhou.utils.random import Random from pytouhou.utils.helpers import read_string from pytouhou.utils.helpers import get_logger @@ -22,43 +25,70 @@ logger = get_logger(__name__) class Level(object): def __init__(self): + self.score = 0 + self.random_seed = 0 + + self.power = 0 + self.lives = 2 + self.bombs = 3 + self.difficulty = 16 self.keys = [] class T6RP(object): def __init__(self): + self.version = 0x102 + self.character = 0 + self.rank = 0 + self.key = 0 self.levels = [] @classmethod - def read(cls, file): + def read(cls, file, decrypt=True, verify=True): if file.read(4) != b'T6RP': raise Exception - if file.read(2) != b'\x02\x01': - raise Exception replay = cls() - replay.character, replay.rank, checksum, unknown, key, unknown = unpack('<BBHIBB', file.read(10)) + replay.version, replay.character, replay.rank = unpack('<HBB', file.read(4)) + checksum, replay.unknown1, replay.unknown2, replay.key = unpack('<IBBB', file.read(7)) + + # Decrypt data + if decrypt: + decrypted_file = BytesIO() + file.seek(0) + decrypted_file.write(file.read(15)) + decrypted_file.write(b''.join(chr((ord(c) - replay.key - 7*i) & 0xff) for i, c in enumerate(file.read()))) + file = decrypted_file + file.seek(15) + + # Verify checksum + if verify: + data = file.read() + file.seek(15) + if checksum != (sum(ord(c) for c in data) + 0x3f000318 + replay.key) & 0xffffffff: + raise Exception #TODO + + replay.unknown3 = unpack('<B', file.read(1)) replay.date = read_string(file, 9, 'ascii') replay.name = read_string(file, 9, 'ascii').rstrip() - unknown, replay.score, unknown, replay.slowdown, unknown = unpack('<HIIfI', file.read(18)) + replay.unknown4, replay.score, replay.unknown5, replay.slowdown, replay.unknown6 = unpack('<HIIfI', file.read(18)) stages_offsets = unpack('<7I', file.read(28)) replay.levels = [] for offset in stages_offsets: - replay.levels.append(None) - if offset == 0: continue level = Level() - replay.levels[-1] = level + replay.levels.append(level) file.seek(offset) - level.score, level.random_seed, unknown, level.power, level.lives, level.bombs, level.difficulty, unknown = unpack('<IHHBbbBI', file.read(16)) + (level.score, level.random_seed, level.unknown1, level.power, + level.lives, level.bombs, level.difficulty, level.unknown2) = unpack('<IHHBbbBI', file.read(16)) while True: time, keys, unknown = unpack('<IHH', file.read(8)) @@ -66,5 +96,6 @@ class T6RP(object): if time == 9999999: break - level.keys.append((time, keys)) + level.keys.append((time, keys, unknown)) + return replay