Mercurial > touhou
changeset 133:2cad2e84a49e
Add reading support for the MSG format.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 11 Sep 2011 07:34:34 -0700 |
parents | fba45c37ec99 |
children | e9ac3640280b |
files | pytouhou/formats/msg.py pytouhou/resource/loader.py |
diffstat | 2 files changed, 99 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/formats/msg.py @@ -0,0 +1,90 @@ +# -*- 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. +## + +import struct +from struct import pack, unpack, calcsize +from pytouhou.utils.helpers import read_string + +from pytouhou.utils.helpers import get_logger + +logger = get_logger(__name__) + +class MSG(object): + _instructions = {0: ('', None), + 1: ('hh', None), + 2: ('hh', 'change_face'), + 3: ('hhs', 'display_dialog_line'), + 4: ('I', 'pause'), + 5: ('hh', 'switch'), + 6: ('', 'add_enemy_sprite'), + 7: ('I', 'change_music'), + 8: ('hhs', 'display_character_line'), + 9: ('I', None), + 10: ('', None), + 11: ('', 'next_level'), + 12: ('', None), + 13: ('I', None), + 14: ('', None)} #TODO + + + def __init__(self): + self.msgs = [[]] + + + @classmethod + def read(cls, file): + entry_count, = unpack('<I', file.read(4)) + entry_offsets = unpack('<%dI' % entry_count, file.read(4 * entry_count)) + + msg = cls() + msg.msgs = [] + + new_entry = True + while True: + offset = file.tell() + + try: + time, opcode, size = unpack('<HBB', file.read(4)) + except: + return + + if time == 0 and opcode == 0: + new_entry = True + + if new_entry and opcode != 0: + new_entry = False + time = -1 + if offset in entry_offsets: + #print(entry_offsets.index(offset)) + msg.msgs.append([]) + + data = file.read(size) + + if opcode in cls._instructions: + fmt = '<%s' % cls._instructions[opcode][0] + if fmt.endswith('s'): + fmt = fmt[:-1] + fmt = '%s%ds' % (fmt, size - calcsize(fmt)) + args = unpack(fmt, data) + if fmt.endswith('s'): + args = args[:-1] + (args[-1].decode('shift_jis'),) + else: + args = (data, ) + logger.warn('unknown msg opcode %d', opcode) + + msg.msgs[-1].append((time, opcode, args)) + + + return msg +
--- a/pytouhou/resource/loader.py +++ b/pytouhou/resource/loader.py @@ -4,6 +4,7 @@ from pytouhou.formats.pbg3 import PBG3 from pytouhou.formats.std import Stage from pytouhou.formats.ecl import ECL from pytouhou.formats.anm0 import Animations +from pytouhou.formats.msg import MSG from pytouhou.resource.anmwrapper import AnmWrapper @@ -42,6 +43,7 @@ class Loader(object): self.instanced_ecls = {} self.instanced_anms = {} self.instanced_stages = {} + self.instanced_msgs = {} def scan_archives(self, paths): @@ -84,6 +86,13 @@ class Loader(object): return self.instanced_ecls[name] + def get_msg(self, name): + if name not in self.instanced_msgs: + file = self.get_file(name) + self.instanced_msgs[name] = MSG.read(file) #TODO: modular + return self.instanced_msgs[name] + + def get_anm_wrapper(self, names): return AnmWrapper(self.get_anm(name) for name in names)