changeset 376:69ec72b990a4

Support more than one version of a vm.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 06 Aug 2012 23:10:09 +0200
parents 8f2f3053906a
children 70e2ed71b09c
files pytouhou/vm/anmrunner.py pytouhou/vm/common.py pytouhou/vm/eclrunner.py pytouhou/vm/msgrunner.py
diffstat 4 files changed, 23 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- 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:
--- 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
--- 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],
--- 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: