Mercurial > touhou
comparison pytouhou/formats/ecl.py @ 112:e544f9a7966d
Add writing support to pytouhou.formats.ecl!
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Tue, 06 Sep 2011 22:40:45 +0200 |
parents | 5d9052b9a4e8 |
children | 732c64662f87 |
comparison
equal
deleted
inserted
replaced
111:340fcda8e64a | 112:e544f9a7966d |
---|---|
131 132: ('i', None), | 131 132: ('i', None), |
132 133: ('', None), | 132 133: ('', None), |
133 134: ('', None), | 133 134: ('', None), |
134 135: ('i', None)} #TODO | 134 135: ('i', None)} #TODO |
135 | 135 |
136 _main_instructions = {0: ('ffIhHHH', 'spawn_enemy'), | |
137 2: ('ffIhHHH', 'spawn_enemy_mirrored'), | |
138 4: ('ffIhHHH', 'spawn_enemy_random'), | |
139 6: ('ffIhHHH', 'spawn_enemy_mirrored_random'), | |
140 8: ('', None), | |
141 9: ('', None), | |
142 10: ('II', None), | |
143 12: ('', None)} | |
144 | |
145 | |
136 def __init__(self): | 146 def __init__(self): |
137 self.main = [] | 147 self.main = [] |
138 self.subs = [[]] | 148 self.subs = [[]] |
139 | 149 |
140 | 150 |
141 @classmethod | 151 @classmethod |
142 def read(cls, file): | 152 def read(cls, file): |
143 sub_count, main_offset = unpack('<II', file.read(8)) | 153 sub_count, main_offset = unpack('<II', file.read(8)) |
144 if file.read(8) != b'\x00\x00\x00\x00\x00\x00\x00\x00': | 154 if file.read(8) != b'\x00\x00\x00\x00\x00\x00\x00\x00': |
145 raise Exception #TODO | 155 raise Exception #TODO |
146 sub_offsets = unpack('<%s' % ('I' * sub_count), file.read(4 * sub_count)) | 156 sub_offsets = unpack('<%dI' % sub_count, file.read(4 * sub_count)) |
147 | 157 |
148 ecl = cls() | 158 ecl = cls() |
149 ecl.subs = [] | 159 ecl.subs = [] |
150 ecl.main = [] | 160 ecl.main = [] |
151 | 161 |
195 file.seek(main_offset) | 205 file.seek(main_offset) |
196 while True: | 206 while True: |
197 time, = unpack('<H', file.read(2)) | 207 time, = unpack('<H', file.read(2)) |
198 if time == 0xffff: | 208 if time == 0xffff: |
199 break | 209 break |
200 sub, instr_type, size = unpack('<HHH', file.read(6)) | 210 |
211 sub, opcode, size = unpack('<HHH', file.read(6)) | |
201 data = file.read(size - 8) | 212 data = file.read(size - 8) |
202 if instr_type in (0, 2, 4, 6): # Enemy spawn | 213 |
203 args = unpack('<ffIhHHH', data) | 214 if opcode in cls._main_instructions: |
215 args = unpack('<%s' % cls._main_instructions[opcode][0], data) | |
204 else: | 216 else: |
205 logger.warn('unknown main opcode %d (data: %r)', instr_type, data) | |
206 args = (data,) | 217 args = (data,) |
207 ecl.main.append((time, sub, instr_type, args)) | 218 logger.warn('unknown main opcode %d', opcode) |
219 | |
220 ecl.main.append((time, sub, opcode, args)) | |
208 | 221 |
209 return ecl | 222 return ecl |
210 | 223 |
224 | |
225 def write(self, file): | |
226 sub_count = len(self.subs) | |
227 sub_offsets = [] | |
228 main_offset = 0 | |
229 | |
230 # Skip header, it will be written later | |
231 file.seek(8+8+4*sub_count) | |
232 | |
233 # Write subs | |
234 for sub in self.subs: | |
235 sub_offsets.append(file.tell()) | |
236 | |
237 instruction_offsets = [] | |
238 instruction_datas = [] | |
239 for time, opcode, rank_mask, param_mask, args in sub: | |
240 format = self._instructions[opcode][0] | |
241 if format.endswith('s'): | |
242 args = list(args) | |
243 args[-1] = args[-1].encode('shift_jis') | |
244 format = '%s%ds' % (format[:-1], len(args[-1])) | |
245 format = '<IHHHH%s' % format | |
246 size = calcsize(format) | |
247 instruction_offsets.append((instruction_offsets[-1] + len(instruction_datas[-1])) if instruction_offsets else 0) | |
248 instruction_datas.append(pack(format, time, opcode, size, rank_mask, param_mask, *args)) | |
249 | |
250 #TODO: clean up this mess | |
251 for instruction, data, offset in zip(sub, instruction_datas, instruction_offsets): | |
252 time, opcode, rank_mask, param_mask, args = instruction | |
253 if opcode in (2, 29, 30, 31, 32, 33, 34): # relative_jump | |
254 frame, index = args | |
255 args = frame, instruction_offsets[index] - offset | |
256 format = '<IHHHH%s' % self._instructions[opcode][0] | |
257 size = calcsize(format) | |
258 data = pack(format, time, opcode, size, rank_mask, param_mask, *args) | |
259 elif opcode == 3: # relative_jump_ex | |
260 frame, index, counter_id = args | |
261 args = frame, instruction_offsets[index] - offset, counter_id | |
262 format = '<IHHHH%s' % self._instructions[opcode][0] | |
263 size = calcsize(format) | |
264 data = pack(format, time, opcode, size, rank_mask, param_mask, *args) | |
265 file.write(data) | |
266 file.write(b'\xff' * 6 + b'\x0c\x00\x00\xff\xff\x00') | |
267 | |
268 # Write main | |
269 main_offset = file.tell() | |
270 for time, sub, opcode, args in self.main: | |
271 format = '<HHHH%s' % self._main_instructions[opcode][0] | |
272 size = calcsize(format) | |
273 | |
274 file.write(pack(format, time, sub, opcode, size, *args)) | |
275 file.write(b'\xff\xff\x04\x00') | |
276 | |
277 # Patch header | |
278 file.seek(0) | |
279 file.write(pack('<IIII%dI' % sub_count, sub_count, main_offset, 0, 0, *sub_offsets)) | |
280 |