# HG changeset patch # User Emmanuel Gil Peyrot # Date 1344287409 -7200 # Node ID 69ec72b990a475118d07495647e04f63ce7ee499 # Parent 8f2f3053906a6421c0ce300f66ced8f10acbf5b0 Support more than one version of a vm. diff --git a/pytouhou/vm/anmrunner.py b/pytouhou/vm/anmrunner.py --- a/pytouhou/vm/anmrunner.py +++ b/pytouhou/vm/anmrunner.py @@ -24,14 +24,14 @@ logger = get_logger(__name__) class ANMRunner(object): __metaclass__ = MetaRegistry __slots__ = ('_anm_wrapper', '_sprite', 'running', - 'sprite_index_offset', - 'script', 'instruction_pointer', 'frame', - 'waiting') + 'sprite_index_offset', 'script', 'instruction_pointer', + 'frame', 'waiting', 'handlers') def __init__(self, anm_wrapper, script_id, sprite, sprite_index_offset=0): self._anm_wrapper = anm_wrapper self._sprite = sprite + self.handlers = self._handlers[6] self.running = True self.waiting = False @@ -71,7 +71,7 @@ class ANMRunner(object): if frame == self.frame: try: - callback = self._handlers[opcode] + callback = self.handlers[opcode] except KeyError: logger.warn('unhandled opcode %d (args: %r)', opcode, args) else: diff --git a/pytouhou/vm/common.py b/pytouhou/vm/common.py --- a/pytouhou/vm/common.py +++ b/pytouhou/vm/common.py @@ -17,22 +17,19 @@ class MetaRegistry(type): def __new__(mcs, name, bases, classdict): instruction_handlers = {} for item in classdict.itervalues(): - try: - instruction_ids = item._instruction_ids - except AttributeError: - pass - else: - for id_ in instruction_ids: - instruction_handlers[id_] = item + if hasattr(item, '_instruction_ids'): + for version, instruction_ids in item._instruction_ids.iteritems(): + for id_ in instruction_ids: + instruction_handlers.setdefault(version, {})[id_] = item classdict['_handlers'] = instruction_handlers return type.__new__(mcs, name, bases, classdict) -def instruction(instruction_id): +def instruction(instruction_id, version=6): def _decorator(func): if not hasattr(func, '_instruction_ids'): - func._instruction_ids = set() - func._instruction_ids.add(instruction_id) + func._instruction_ids = {} + func._instruction_ids.setdefault(version, set()).add(instruction_id) return func return _decorator diff --git a/pytouhou/vm/eclrunner.py b/pytouhou/vm/eclrunner.py --- a/pytouhou/vm/eclrunner.py +++ b/pytouhou/vm/eclrunner.py @@ -26,13 +26,13 @@ logger = get_logger(__name__) class ECLMainRunner(object): __metaclass__ = MetaRegistry __slots__ = ('_main', '_subs', '_game', 'frame', - 'instruction_pointer', - 'boss_wait') + 'instruction_pointer', 'boss_wait', 'handlers') def __init__(self, main, subs, game): self._main = main self._subs = subs self._game = game + self.handlers = self._handlers[6] self.frame = 0 self.boss_wait = False @@ -57,7 +57,7 @@ class ECLMainRunner(object): if frame == self.frame: try: - callback = self._handlers[instr_type] + callback = self.handlers[instr_type] except KeyError: logger.warn('unhandled main opcode %d (args: %r)', instr_type, args) else: @@ -121,9 +121,9 @@ class ECLMainRunner(object): class ECLRunner(object): __metaclass__ = MetaRegistry - __slots__ = ('_subs', '_enemy', '_game', '_pop_enemy', 'variables', 'sub', 'frame', - 'instruction_pointer', 'comparison_reg', 'stack', - 'running') + __slots__ = ('_subs', '_enemy', '_game', '_pop_enemy', 'variables', 'sub', + 'frame', 'instruction_pointer', 'comparison_reg', 'stack', + 'running', 'handlers') def __init__(self, subs, sub, enemy, game, pop_enemy): # Things not supposed to change @@ -131,6 +131,7 @@ class ECLRunner(object): self._enemy = enemy self._game = game self._pop_enemy = pop_enemy + self.handlers = self._handlers[6] self.running = True @@ -172,7 +173,7 @@ class ECLRunner(object): if frame == self.frame: try: - callback = self._handlers[instr_type] + callback = self.handlers[instr_type] except KeyError: logger.warn('[%d %r - %04d] unhandled opcode %d (args: %r)', id(self), [self.sub] + [e[0] for e in self.stack], diff --git a/pytouhou/vm/msgrunner.py b/pytouhou/vm/msgrunner.py --- a/pytouhou/vm/msgrunner.py +++ b/pytouhou/vm/msgrunner.py @@ -28,11 +28,13 @@ class NextStage(Exception): class MSGRunner(object): __metaclass__ = MetaRegistry __slots__ = ('_msg', '_game', 'frame', 'sleep_time', 'allow_skip', - 'skipping', 'frozen', 'faces', 'ended', 'instruction_pointer') + 'skipping', 'frozen', 'faces', 'ended', 'instruction_pointer', + 'handlers') def __init__(self, msg, script, game): self._msg = msg.msgs[script + 10 * (game.players[0].state.character // 2)] self._game = game + self.handlers = self._handlers[6] self.frame = 0 self.sleep_time = 0 self.allow_skip = True @@ -68,7 +70,7 @@ class MSGRunner(object): if frame == self.frame: try: - callback = self._handlers[instr_type] + callback = self.handlers[instr_type] except KeyError: logger.warn('unhandled msg opcode %d (args: %r)', instr_type, args) else: