view pytouhou/game/eclrunner.py @ 23:444ac7bca7bc

Refacto ECL stuff, add support for a few instructions, and add some culling
author Thibaut Girka <thib@sitedethib.com>
date Fri, 12 Aug 2011 19:13:43 +0200
parents
children 93aa1b55d97c
line wrap: on
line source

from struct import unpack


class ECLRunner(object):
    def __init__(self, ecl, sub, frame=0, instruction_pointer=0, implementation=None):
        self.ecl = ecl

        self.labels = {}
        self.implementation = {4: ('HHI', self.set_label),
                               3: ('IHHHH', self.goto)}
        if implementation:
            self.implementation.update(implementation)

        self.sub = sub
        self.frame = frame
        self.instruction_pointer = instruction_pointer


    def set_label(self, label, unknown, count):
        assert unknown == 0xffff
        self.labels[label] = (self.sub, self.instruction_pointer, count)


    def goto(self, frame, unknown1, unknown2, label, unknown3):
        try:
            sub, instruction_pointer, count = self.labels[label]
        except KeyError:
            pass
        else:
            count -= 1
            if count:
                self.labels[label] = sub, instruction_pointer, count
            else:
                del self.labels[label]
            self.frame = frame
            self.sub, self.instruction_pointer = sub, instruction_pointer


    def update(self):
        frame = self.frame
        while frame <= self.frame:
            try:
                frame, instr_type, rank_mask, param_mask, args = self.ecl.subs[self.sub][self.instruction_pointer]
            except IndexError:
                break #TODO: script ended, destroy enemy

            if frame == self.frame:
                try:
                    format, callback = self.implementation[instr_type]
                except KeyError:
                    print('Warning: unhandled opcode %d!' % instr_type) #TODO
                else:
                    callback(*unpack('<' + format, args))
                self.instruction_pointer += 1

        self.frame += 1