changeset 51:0707ff53e7b5

Add support for a few instructions
author Thibaut Girka <thib@sitedethib.com>
date Mon, 22 Aug 2011 22:12:34 +0200
parents 811cefefb5c8
children ab826bc29aa2
files pytouhou/formats/ecl.py pytouhou/game/eclrunner.py
diffstat 2 files changed, 42 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/formats/ecl.py
+++ b/pytouhou/formats/ecl.py
@@ -160,7 +160,7 @@ class ECL(object):
             # Translate offsets to instruction pointers
             for instr_offset, (i, instr) in zip(instruction_offsets, enumerate(ecl.subs[-1])):
                 time, opcode, rank_mask, param_mask, args = instr
-                if opcode == 2: # relative_jump
+                if opcode in (2, 31): # relative_jump
                     frame, relative_offset = args
                     args = frame, instruction_offsets.index(instr_offset + relative_offset)
                 elif opcode == 3: # relative_jump_ex
--- a/pytouhou/game/eclrunner.py
+++ b/pytouhou/game/eclrunner.py
@@ -1,3 +1,6 @@
+from math import atan2, cos, sin
+
+
 class MetaRegistry(type):
     def __new__(mcs, name, bases, classdict):
         instruction_handlers = {}
@@ -27,7 +30,7 @@ def instruction(instruction_id):
 class ECLRunner(object):
     __metaclass__ = MetaRegistry
     __slots__ = ('_ecl', '_enemy', '_game_state', 'variables', 'sub', 'frame',
-                 'instruction_pointer', 'stack')
+                 'instruction_pointer', 'comparison_reg', 'stack')
 
     def __init__(self, ecl, sub, enemy, game_state):
         # Things not supposed to change
@@ -39,6 +42,7 @@ class ECLRunner(object):
         self.variables = [0,  0,  0,  0,
                           0., 0., 0., 0.,
                           0,  0,  0,  0]
+        self.comparison_reg = 0
         self.sub = sub
         self.frame = 0
         self.instruction_pointer = 0
@@ -131,6 +135,11 @@ class ECLRunner(object):
             raise IndexError #TODO: proper exception
 
 
+    @instruction(0)
+    def noop(self):
+        pass #TODO: Really?
+
+
     @instruction(1)
     def destroy(self, arg):
         #TODO: arg?
@@ -178,10 +187,27 @@ class ECLRunner(object):
         self._setval(variable_id, self._getval(a) - self._getval(b))
 
 
+    @instruction(27)
+    def compare_ints(self, a, b):
+        a, b = self._getval(a), self._getval(b)
+        if a < b:
+            self.comparison_reg = -1
+        elif a == b:
+            self.comparison_reg = 0
+        else:
+            self.comparison_reg = 1
+
+
+    @instruction(31)
+    def relative_jump_if_equal(self, frame, instruction_pointer):
+        if self.comparison_reg == 0:
+            self.relative_jump(frame, instruction_pointer)
+
+
     @instruction(35)
     def call(self, sub, param1, param2):
         self.stack.append((self.sub, self.frame, self.instruction_pointer,
-                           self.variables))
+                           self.variables, self.comparison_reg))
         self.sub = sub
         self.frame = 0
         self.instruction_pointer = 0
@@ -192,7 +218,7 @@ class ECLRunner(object):
 
     @instruction(36)
     def ret(self):
-        self.sub, self.frame, self.instruction_pointer, self.variables = self.stack.pop()
+        self.sub, self.frame, self.instruction_pointer, self.variables, self.comparison_reg = self.stack.pop()
 
 
     @instruction(39)
@@ -226,6 +252,13 @@ class ECLRunner(object):
         self._enemy.acceleration = acceleration
 
 
+    @instruction(50)
+    def set_random_angle(self, min_angle, max_angle):
+        #TODO: This thing is really odd, check, double check, triple check, disassemble...
+        angle = self._game_state.prng.rand_double() * (max_angle - min_angle) + min_angle
+        self._enemy.angle = atan2(-abs(sin(angle)), -abs(cos(angle)))
+
+
     @instruction(51)
     def target_player(self, unknown, speed):
         #TODO: unknown
@@ -309,6 +342,11 @@ class ECLRunner(object):
             self.instruction_pointer = 0
 
 
+    @instruction(111)
+    def set_life(self, value):
+        self._enemy.life = value
+
+
     @instruction(113)
     def set_low_life_trigger(self, value):
         self._enemy.low_life_trigger = value