Mercurial > touhou
comparison pytouhou/formats/msg.py @ 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 | |
children | d3005ebe797a |
comparison
equal
deleted
inserted
replaced
132:fba45c37ec99 | 133:2cad2e84a49e |
---|---|
1 # -*- encoding: utf-8 -*- | |
2 ## | |
3 ## Copyright (C) 2011 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | |
4 ## | |
5 ## This program is free software; you can redistribute it and/or modify | |
6 ## it under the terms of the GNU General Public License as published | |
7 ## by the Free Software Foundation; version 3 only. | |
8 ## | |
9 ## This program is distributed in the hope that it will be useful, | |
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 ## GNU General Public License for more details. | |
13 ## | |
14 | |
15 import struct | |
16 from struct import pack, unpack, calcsize | |
17 from pytouhou.utils.helpers import read_string | |
18 | |
19 from pytouhou.utils.helpers import get_logger | |
20 | |
21 logger = get_logger(__name__) | |
22 | |
23 class MSG(object): | |
24 _instructions = {0: ('', None), | |
25 1: ('hh', None), | |
26 2: ('hh', 'change_face'), | |
27 3: ('hhs', 'display_dialog_line'), | |
28 4: ('I', 'pause'), | |
29 5: ('hh', 'switch'), | |
30 6: ('', 'add_enemy_sprite'), | |
31 7: ('I', 'change_music'), | |
32 8: ('hhs', 'display_character_line'), | |
33 9: ('I', None), | |
34 10: ('', None), | |
35 11: ('', 'next_level'), | |
36 12: ('', None), | |
37 13: ('I', None), | |
38 14: ('', None)} #TODO | |
39 | |
40 | |
41 def __init__(self): | |
42 self.msgs = [[]] | |
43 | |
44 | |
45 @classmethod | |
46 def read(cls, file): | |
47 entry_count, = unpack('<I', file.read(4)) | |
48 entry_offsets = unpack('<%dI' % entry_count, file.read(4 * entry_count)) | |
49 | |
50 msg = cls() | |
51 msg.msgs = [] | |
52 | |
53 new_entry = True | |
54 while True: | |
55 offset = file.tell() | |
56 | |
57 try: | |
58 time, opcode, size = unpack('<HBB', file.read(4)) | |
59 except: | |
60 return | |
61 | |
62 if time == 0 and opcode == 0: | |
63 new_entry = True | |
64 | |
65 if new_entry and opcode != 0: | |
66 new_entry = False | |
67 time = -1 | |
68 if offset in entry_offsets: | |
69 #print(entry_offsets.index(offset)) | |
70 msg.msgs.append([]) | |
71 | |
72 data = file.read(size) | |
73 | |
74 if opcode in cls._instructions: | |
75 fmt = '<%s' % cls._instructions[opcode][0] | |
76 if fmt.endswith('s'): | |
77 fmt = fmt[:-1] | |
78 fmt = '%s%ds' % (fmt, size - calcsize(fmt)) | |
79 args = unpack(fmt, data) | |
80 if fmt.endswith('s'): | |
81 args = args[:-1] + (args[-1].decode('shift_jis'),) | |
82 else: | |
83 args = (data, ) | |
84 logger.warn('unknown msg opcode %d', opcode) | |
85 | |
86 msg.msgs[-1].append((time, opcode, args)) | |
87 | |
88 | |
89 return msg | |
90 |