Mercurial > touhou
comparison pytouhou/formats/std.py @ 110:3ac41b966fed
Add writing support to pytouhou.formats.std!
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Tue, 06 Sep 2011 16:40:32 +0200 |
parents | ac2e5e1c2c3c |
children | 340fcda8e64a |
comparison
equal
deleted
inserted
replaced
109:e93a7ed4f203 | 110:3ac41b966fed |
---|---|
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 ## GNU General Public License for more details. | 12 ## GNU General Public License for more details. |
13 ## | 13 ## |
14 | 14 |
15 | 15 |
16 from struct import pack, unpack | 16 from struct import pack, unpack, calcsize |
17 from pytouhou.utils.helpers import read_string, get_logger | 17 from pytouhou.utils.helpers import read_string, get_logger |
18 | 18 |
19 logger = get_logger(__name__) | 19 logger = get_logger(__name__) |
20 | 20 |
21 | 21 |
27 self.quads = [] | 27 self.quads = [] |
28 | 28 |
29 | 29 |
30 | 30 |
31 class Stage(object): | 31 class Stage(object): |
32 _instructions = {0: ('fff', 'set_viewpos'), | |
33 1: ('BBBBff', 'set_fog'), | |
34 2: ('fff', 'set_viewpos2'), | |
35 3: ('III', 'start_interpolating_viewpos2'), | |
36 4: ('III', 'start_interpolating_fog')} | |
37 | |
32 def __init__(self): | 38 def __init__(self): |
33 self.name = '' | 39 self.name = '' |
34 self.bgms = (('', ''), ('', ''), ('', '')) | 40 self.bgms = (('', ''), ('', ''), ('', '')) |
35 self.models = [] | 41 self.models = [] |
36 self.object_instances = [] | 42 self.object_instances = [] |
44 nb_models, nb_faces = unpack('<HH', file.read(4)) | 50 nb_models, nb_faces = unpack('<HH', file.read(4)) |
45 object_instances_offset, script_offset = unpack('<II', file.read(8)) | 51 object_instances_offset, script_offset = unpack('<II', file.read(8)) |
46 if file.read(4) != b'\x00\x00\x00\x00': | 52 if file.read(4) != b'\x00\x00\x00\x00': |
47 raise Exception #TODO | 53 raise Exception #TODO |
48 | 54 |
49 stage.name = read_string(file, 128, 'shift-jis') | 55 stage.name = read_string(file, 128, 'shift_jis') |
50 | 56 |
51 bgm_a = read_string(file, 128, 'shift-jis') | 57 bgm_a = read_string(file, 128, 'shift_jis') |
52 bgm_b = read_string(file, 128, 'shift-jis') | 58 bgm_b = read_string(file, 128, 'shift_jis') |
53 bgm_c = read_string(file, 128, 'shift-jis') | 59 bgm_c = read_string(file, 128, 'shift_jis') |
54 bgm_d = read_string(file, 128, 'shift-jis') | 60 bgm_d = read_string(file, 128, 'shift_jis') |
55 | 61 |
56 bgm_a_path = read_string(file, 128, 'ascii') | 62 bgm_a_path = read_string(file, 128, 'ascii') |
57 bgm_b_path = read_string(file, 128, 'ascii') | 63 bgm_b_path = read_string(file, 128, 'ascii') |
58 bgm_c_path = read_string(file, 128, 'ascii') | 64 bgm_c_path = read_string(file, 128, 'ascii') |
59 bgm_d_path = read_string(file, 128, 'ascii') | 65 bgm_d_path = read_string(file, 128, 'ascii') |
71 unknown, size = unpack('<HH', file.read(4)) | 77 unknown, size = unpack('<HH', file.read(4)) |
72 if unknown == 0xffff: | 78 if unknown == 0xffff: |
73 break | 79 break |
74 if size != 0x1c: | 80 if size != 0x1c: |
75 raise Exception #TODO | 81 raise Exception #TODO |
76 script_index, _padding, x, y, z, width, height = unpack('<HHfffff', file.read(24)) | 82 script_index, x, y, z, width, height = unpack('<Hxxfffff', file.read(24)) |
77 #TODO: store script_index, x, y, z, width and height | |
78 model.quads.append((script_index, x, y, z, width, height)) | 83 model.quads.append((script_index, x, y, z, width, height)) |
79 stage.models.append(model) | 84 stage.models.append(model) |
80 | 85 |
81 | 86 |
82 # Read object usages | 87 # Read object usages |
91 | 96 |
92 | 97 |
93 # Read other funny things (script) | 98 # Read other funny things (script) |
94 file.seek(script_offset) | 99 file.seek(script_offset) |
95 while True: | 100 while True: |
96 frame, message_type, size = unpack('<IHH', file.read(8)) | 101 frame, opcode, size = unpack('<IHH', file.read(8)) |
97 if (frame, message_type, size) == (0xffffffff, 0xffff, 0xffff): | 102 if (frame, opcode, size) == (0xffffffff, 0xffff, 0xffff): |
98 break | 103 break |
99 if size != 0x0c: | 104 if size != 0x0c: |
100 raise Exception #TODO | 105 raise Exception #TODO |
101 data = file.read(12) | 106 data = file.read(size) |
102 #TODO: maybe add a name somewhere | 107 if opcode in cls._instructions: |
103 if message_type == 0: # ViewPos | 108 args = unpack('<%s' % cls._instructions[opcode][0], data) |
104 args = unpack('<fff', data) | |
105 elif message_type == 1: # Color | |
106 args = unpack('<BBBBff', data) | |
107 elif message_type == 2: # ViewPos2 | |
108 args = unpack('<fff', data) | |
109 elif message_type == 3: # StartInterpolatingViewPos2 | |
110 args = tuple(unpack('<III', data)[:1]) | |
111 elif message_type == 4: # StartInterpolatingFog | |
112 args = tuple(unpack('<III', data)[:1]) | |
113 else: | 109 else: |
114 args = (data,) | 110 args = (data,) |
115 logger.warn('unknown opcode %d (data: %r)', message_type, data) | 111 logger.warn('unknown opcode %d', opcode) |
116 stage.script.append((frame, message_type, args)) | 112 stage.script.append((frame, opcode, args)) |
117 | 113 |
118 return stage | 114 return stage |
119 | 115 |
116 | |
117 def write(self, file): | |
118 model_offsets = [] | |
119 second_section_offset = 0 | |
120 third_section_offset = 0 | |
121 | |
122 nb_faces = sum(len(model.quads) for model in self.models) | |
123 | |
124 # Write header | |
125 file.write(pack('<HH', len(self.models), nb_faces)) #TODO: nb_faces | |
126 file.write(pack('<II', 0, 0)) | |
127 file.write(pack('<I', 0)) | |
128 file.write(pack('<128s', self.name.encode('shift_jis'))) | |
129 for bgm_name, bgm_path in self.bgms: | |
130 file.write(pack('<128s', bgm_name.encode('shift_jis'))) | |
131 for bgm_name, bgm_path in self.bgms: | |
132 file.write(pack('<128s', bgm_path.encode('ascii'))) | |
133 file.write(b'\x00\x00\x00\x00' * len(self.models)) | |
134 | |
135 # Write first section | |
136 for i, model in enumerate(self.models): | |
137 model_offsets.append(file.tell()) | |
138 file.write(pack('<HHffffff', i, model.unknown, *model.bounding_box)) | |
139 for quad in model.quads: | |
140 file.write(pack('<HH', 0x00, 0x1c)) | |
141 file.write(pack('<Hxxfffff', *quad)) | |
142 file.write(pack('<HH', 0xffff, 4)) | |
143 | |
144 # Write second section | |
145 second_section_offset = file.tell() | |
146 for obj_id, x, y, z in self.object_instances: | |
147 file.write(pack('<HHfff', obj_id, 256, x, y, z)) | |
148 file.write(b'\xff' * 16) | |
149 | |
150 # Write third section | |
151 third_section_offset = file.tell() | |
152 for frame, opcode, args in self.script: | |
153 size = calcsize(self._instructions[opcode][0]) | |
154 file.write(pack('<IHH%s' % self._instructions[opcode][0], frame, opcode, size, *args)) | |
155 file.write(b'\xff' * 20) | |
156 | |
157 # Fix offsets | |
158 file.seek(4) | |
159 file.write(pack('<II', second_section_offset, third_section_offset)) | |
160 file.seek(16+128+128*2*4) | |
161 file.write(pack('<%sI' % len(self.models), *model_offsets)) | |
162 |