view pytouhou/formats/t6rp.py @ 200:300661f2ae8a

Fix orbs' original position
author Thibaut Girka <thib@sitedethib.com>
date Mon, 31 Oct 2011 17:54:06 +0100
parents 9f58e2a6e950
children 88361534c77e
line wrap: on
line source

# -*- encoding: utf-8 -*-
##
## Copyright (C) 2011 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##

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

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 = [None] * 7


    @classmethod
    def read(cls, file, decrypt=True, verify=True):
        if file.read(4) != b'T6RP':
            raise Exception

        replay = cls()

        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 = file.read(9) #read_string(file, 9, 'ascii')
        replay.name = file.read(9) #read_string(file, 9, 'ascii').rstrip()
        replay.unknown4, replay.score, replay.unknown5, replay.slowdown, replay.unknown6 = unpack('<HIIfI', file.read(18))

        stages_offsets = unpack('<7I', file.read(28))

        for i, offset in enumerate(stages_offsets):
            if offset == 0:
                continue

            level = Level()
            replay.levels[i] = level

            file.seek(offset)
            (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))

                if time == 9999999:
                    break

                level.keys.append((time, keys, unknown))

        return replay