Mercurial > touhou
diff 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 |
line wrap: on
line diff
--- a/pytouhou/formats/ecl.py +++ b/pytouhou/formats/ecl.py @@ -133,6 +133,16 @@ class ECL(object): 134: ('', None), 135: ('i', None)} #TODO + _main_instructions = {0: ('ffIhHHH', 'spawn_enemy'), + 2: ('ffIhHHH', 'spawn_enemy_mirrored'), + 4: ('ffIhHHH', 'spawn_enemy_random'), + 6: ('ffIhHHH', 'spawn_enemy_mirrored_random'), + 8: ('', None), + 9: ('', None), + 10: ('II', None), + 12: ('', None)} + + def __init__(self): self.main = [] self.subs = [[]] @@ -143,7 +153,7 @@ class ECL(object): sub_count, main_offset = unpack('<II', file.read(8)) if file.read(8) != b'\x00\x00\x00\x00\x00\x00\x00\x00': raise Exception #TODO - sub_offsets = unpack('<%s' % ('I' * sub_count), file.read(4 * sub_count)) + sub_offsets = unpack('<%dI' % sub_count, file.read(4 * sub_count)) ecl = cls() ecl.subs = [] @@ -197,14 +207,74 @@ class ECL(object): time, = unpack('<H', file.read(2)) if time == 0xffff: break - sub, instr_type, size = unpack('<HHH', file.read(6)) + + sub, opcode, size = unpack('<HHH', file.read(6)) data = file.read(size - 8) - if instr_type in (0, 2, 4, 6): # Enemy spawn - args = unpack('<ffIhHHH', data) + + if opcode in cls._main_instructions: + args = unpack('<%s' % cls._main_instructions[opcode][0], data) else: - logger.warn('unknown main opcode %d (data: %r)', instr_type, data) args = (data,) - ecl.main.append((time, sub, instr_type, args)) + logger.warn('unknown main opcode %d', opcode) + + ecl.main.append((time, sub, opcode, args)) return ecl + + def write(self, file): + sub_count = len(self.subs) + sub_offsets = [] + main_offset = 0 + + # Skip header, it will be written later + file.seek(8+8+4*sub_count) + + # Write subs + for sub in self.subs: + sub_offsets.append(file.tell()) + + instruction_offsets = [] + instruction_datas = [] + for time, opcode, rank_mask, param_mask, args in sub: + format = self._instructions[opcode][0] + if format.endswith('s'): + args = list(args) + args[-1] = args[-1].encode('shift_jis') + format = '%s%ds' % (format[:-1], len(args[-1])) + format = '<IHHHH%s' % format + size = calcsize(format) + instruction_offsets.append((instruction_offsets[-1] + len(instruction_datas[-1])) if instruction_offsets else 0) + instruction_datas.append(pack(format, time, opcode, size, rank_mask, param_mask, *args)) + + #TODO: clean up this mess + for instruction, data, offset in zip(sub, instruction_datas, instruction_offsets): + time, opcode, rank_mask, param_mask, args = instruction + if opcode in (2, 29, 30, 31, 32, 33, 34): # relative_jump + frame, index = args + args = frame, instruction_offsets[index] - offset + format = '<IHHHH%s' % self._instructions[opcode][0] + size = calcsize(format) + data = pack(format, time, opcode, size, rank_mask, param_mask, *args) + elif opcode == 3: # relative_jump_ex + frame, index, counter_id = args + args = frame, instruction_offsets[index] - offset, counter_id + format = '<IHHHH%s' % self._instructions[opcode][0] + size = calcsize(format) + data = pack(format, time, opcode, size, rank_mask, param_mask, *args) + file.write(data) + file.write(b'\xff' * 6 + b'\x0c\x00\x00\xff\xff\x00') + + # Write main + main_offset = file.tell() + for time, sub, opcode, args in self.main: + format = '<HHHH%s' % self._main_instructions[opcode][0] + size = calcsize(format) + + file.write(pack(format, time, sub, opcode, size, *args)) + file.write(b'\xff\xff\x04\x00') + + # Patch header + file.seek(0) + file.write(pack('<IIII%dI' % sub_count, sub_count, main_offset, 0, 0, *sub_offsets)) +