changeset 685:11d7e4d6947a

ecl_vm: nearing the complete list
author Gauvain "GovanifY" Roussel-Tarbouriech <gauvain@govanify.com>
date Fri, 16 Aug 2019 23:27:09 +0200
parents c8bb28961d31
children aefe5b5f481e
files src/th06/ecl.rs src/th06/ecl_vm.rs
diffstat 2 files changed, 163 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/src/th06/ecl.rs
+++ b/src/th06/ecl.rs
@@ -189,18 +189,24 @@ declare_sub_instructions!{
     4 => fn SetInt(var: i32, value: i32),
     5 => fn SetFloat(var: i32, value: f32),
     6 => fn SetRandomInt(var: i32, max: i32),
+    7 => fn SetRandomIntMin(var: i32, max: i32, min: i32),
     8 => fn SetRandomFloat(var: i32, max: f32),
     9 => fn SetRandomFloatMin(var: i32, amplitude: f32, min: f32),
     10 => fn StoreX(var: i32),
+    11 => fn StoreY(var: i32),
+    12 => fn StoreZ(var: i32),
     13 => fn AddInt(var: i32, a: i32, b: i32),
     14 => fn SubstractInt(var: i32, a: i32, b: i32),
     15 => fn MultiplyInt(var: i32, a: i32, b: i32),
     16 => fn DivideInt(var: i32, a: i32, b: i32),
     17 => fn ModuloInt(var: i32, a: i32, b: i32),
     18 => fn Increment(var: i32),
+    19 => fn Decrement(var: i32),
     20 => fn AddFloat(var: i32, a: f32, b: f32),
     21 => fn SubstractFloat(var: i32, a: f32, b: f32),
+    22 => fn MultiplyFloat(var: i32, a: f32, b: f32),
     23 => fn DivideFloat(var: i32, a: f32, b: f32),
+    24 => fn ModuloFloat(var: i32, a: f32, b: f32),
     25 => fn GetDirection(var: i32, x1: f32, y1: f32, x2: f32, y2: f32),
     26 => fn FloatToUnitCircle(var: i32),
     27 => fn CompareInts(a: i32, b: i32),
@@ -213,7 +219,12 @@ declare_sub_instructions!{
     34 => fn RelativeJumpIfNotEqual(frame: i32, ip: i32),
     35 => fn Call(sub: i32, param1: i32, param2: f32),
     36 => fn Return(),
+    37 => fn CallIfSuperior(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
+    38 => fn CallIfSuperiorOrEqual(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
     39 => fn CallIfEqual(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
+    40 => fn CallIfInferior(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
+    41 => fn CallIfInferiorOrEqual(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
+    42 => fn CallIfNotEqual(sub: i32, param1: i32, param2: f32, a: i32, b: i32),
     43 => fn SetPosition(x: f32, y: f32, z: f32),
     45 => fn SetAngleAndSpeed(angle: f32, speed: f32),
     46 => fn SetRotationSpeed(speed: f32),
@@ -254,7 +265,7 @@ declare_sub_instructions!{
     91 => fn LaserSetCompare(id: u32),
     92 => fn CancelLaser(id: u32),
     93 => fn SetSpellcard(face: i16, number: i16, name: String),
-    94 => fn Endspellcard(),
+    94 => fn EndSpellcard(),
     95 => fn SpawnEnemy(sub: i32, x: f32, y: f32, z: f32, life: i16, bonus_dropped: i16, die_score: i32),
     96 => fn KillAllEnemies(),
     97 => fn SetAnim(script: i32),
@@ -271,7 +282,7 @@ declare_sub_instructions!{
     108 => fn SetDeathCallback(sub: i32),
     109 => fn MemoryWriteInt(value: i32, index: i32),
     111 => fn SetLife(life: i32),
-    112 => fn SetEllapsedTime(frame: i32),
+    112 => fn SetElapsedTime(frame: i32),
     113 => fn SetLowLifeTrigger(trigger: i32),
     114 => fn SetLowLifeCallback(sub: i32),
     115 => fn SetTimeout(timeout: i32),
--- a/src/th06/ecl_vm.rs
+++ b/src/th06/ecl_vm.rs
@@ -248,11 +248,10 @@ impl EclRunner {
                 self.set_i32(var_id, random % self.get_i32(maxval));
             }
             // 7
-            /*
             SubInstruction::SetRandomIntMin(var_id, maxval, minval) => {
-                self.set_i32(var_id, (self.get_prng().borrow_mut().get_u32() % self.get_i32(maxval)) + self.get_i32(minval));
+                let random = self.get_prng().borrow_mut().get_u32() as i32;
+                self.set_i32(var_id, (random % self.get_i32(maxval)) + self.get_i32(minval));
             }
-            */
             // 8
             SubInstruction::SetRandomFloat(var_id, maxval) => {
                 let random = self.get_prng().borrow_mut().get_f64() as f32;
@@ -273,19 +272,21 @@ impl EclRunner {
                 self.set_i32(var_id, x as i32);
             }
             // 11
-            /*
             SubInstruction::StoreY(var_id) => {
-                let enemy = self.enemy.borrow();
-                self.set_i32(var_id, enemy.pos.y);
+                let y = {
+                    let enemy = self.enemy.borrow();
+                    enemy.pos.y
+                };
+                self.set_i32(var_id, y as i32);
             }
-            */
             // 12
-            /*
             SubInstruction::StoreZ(var_id) => {
-                let enemy = self.enemy.borrow();
-                self.set_i32(var_id, enemy.z);
+                let z = {
+                    let enemy = self.enemy.borrow();
+                    enemy.z
+                };
+                self.set_i32(var_id, z as i32);
             }
-            */
             // 13(int), 20(float), same impl in th06
             SubInstruction::AddInt(var_id, a, b) => {
                 self.set_i32(var_id, self.get_i32(a) + self.get_i32(b));
@@ -313,31 +314,31 @@ impl EclRunner {
             SubInstruction::DivideInt(var_id, a, b) => {
                 self.set_i32(var_id, self.get_i32(a) / self.get_i32(b));
             }
-            /*
-            SubInstruction::Divide(var_id, a, b) => {
+
+            SubInstruction::DivideFloat(var_id, a, b) => {
                 self.set_f32(var_id as f32, self.get_f32(a) / self.get_f32(b));
             }
-            */
+
             // 17(int) 24(unused)
             SubInstruction::ModuloInt(var_id, a, b) => {
                 self.set_i32(var_id, self.get_i32(a) % self.get_i32(b));
             }
-            /*
+
             SubInstruction::ModuloFloat(var_id, a, b) => {
                 self.set_f32(var_id as f32, self.get_f32(a) % self.get_f32(b));
             }
-            */
+
             // 18
             // setval used by pytouhou, but not in game(???)
             SubInstruction::Increment(var_id) => {
                 self.set_i32(var_id, self.get_i32(var_id) + 1);
             }
+
             // 19
-            /*
             SubInstruction::Decrement(var_id) => {
                 self.set_i32(var_id, self.get_i32(var_id) - 1);
             }
-            */
+
             //25
             SubInstruction::GetDirection(var_id, x1, y1, x2, y2) => {
                 //__ctrandisp2 in ghidra, let's assume from pytouhou it's atan2
@@ -426,51 +427,43 @@ impl EclRunner {
                 unimplemented!()
             }
             // 37
-            /*
             SubInstruction::CallIfSuperior(sub, param1, param2, a, b) => {
-                if self.get_i32(b) <= self.get_i32(a) {
+                if self.get_i32(a) < self.get_i32(b) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
-            */
             // 38
-            /*
             SubInstruction::CallIfSuperiorOrEqual(sub, param1, param2, a, b) => {
-                if self.get_i32(b) <= self.get_i32(a) {
+                if self.get_i32(a) <= self.get_i32(b) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
-            */
             // 39
             SubInstruction::CallIfEqual(sub, param1, param2, a, b) => {
-                if self.get_i32(b) == self.get_i32(a) {
+                if self.get_i32(a) == self.get_i32(b) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
             // 40
-            /*
-            SubInstruction::CallIfEqual(sub, param1, param2, a, b) => {
-                if self.get_i32(b) == self.get_i32(a) {
+            SubInstruction::CallIfInferior(sub, param1, param2, a, b) => {
+                if self.get_i32(b) < self.get_i32(a) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
-            */
-            //41
-            /*
-            SubInstruction::CallIfInferior(sub, param1, param2, a, b) => {
-                if self.get_i32(a) < self.get_i32(b) {
+
+            // 41
+            SubInstruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) => {
+                if self.get_i32(b) <= self.get_i32(a) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
-            */
             //42
-            /*
-            SubInstruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) => {
-                if self.get_i32(a) <= self.get_i32(b) {
+            SubInstruction::CallIfNotEqual(sub, param1, param2, a, b) => {
+                if self.get_i32(a) != self.get_i32(b) {
                     SubInstruction::Call(sub, param1, param2);
                 }
             }
-            */
+
             // 43
             SubInstruction::SetPosition(x, y, z) => {
                 let mut enemy = self.enemy.borrow_mut();
@@ -671,9 +664,37 @@ impl EclRunner {
                 }
             }
             */
+            // 93
+            // TODO: actually implement that hell
+            SubInstruction::SetSpellcard(face, number, name) => {
+                unimplemented!("spellcard start");
+
+            }
+            // 94
+            SubInstruction::EndSpellcard() => {
+                unimplemented!("spellcard end");
+
+            }
+
+            // 95
+            /*
+            SubInstruction::PopEnemy(sub, x, y, z, life, bonus_dropped, die_score) => {
+                self._pop_enemy(sub, 0, self.get_f32(x),
+                                self.get_f32(y),
+                                self.get_f32(z),
+                                life, bonus_dropped, die_score)
+
+            }
+            */
 
 
-
+            // 96 
+            /* 
+            SubInstruction::KillEnemies() => {
+                let mut game = self.game.borrow_mut();
+                game.kill_enemies();
+            }
+            */
 
 
 
@@ -697,6 +718,14 @@ impl EclRunner {
                     Some((end_left as u8, end_right as u8, left as u8, right as u8))
                 };
             }
+            /*
+            // 99
+            SubInstruction::SetAuxAnims(number, script) => {
+                assert!(7 < number);
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.set_aux_anm(number, script)
+            }
+            */
 
             // 100
             SubInstruction::SetDeathAnim(index) => {
@@ -705,6 +734,27 @@ impl EclRunner {
                 let mut enemy = self.enemy.borrow_mut();
                 enemy.death_anim = index;
             }
+            // 101
+            /*
+            SubInstruction::SetBossMode(value) => {
+                let mut enemy = self.enemy.borrow_mut();
+                if value < 0 {
+                    enemy.set_boss(false);
+                }
+                else {
+                    // the boss pointer is written somewhere in memory and overwrote by a 0 when
+                    // the boss mode is false, might want to look into that 
+                    enemy.set_boss(true);
+                }
+            }
+            */
+
+            // 102
+            // TODO: title says it all
+            /*
+            SubInstruction::ParticlesVoodooMagic(unk1, unk2, unk3, unk4, unk5) => {
+            }
+            */
 
             // 103
             SubInstruction::SetHitbox(width, height, depth) => {
@@ -742,12 +792,73 @@ impl EclRunner {
                 let mut enemy = self.enemy.borrow_mut();
                 enemy.death_flags = death_flags;
             }
+            // 108
+            /*
+            SubInstruction::SetDeathCallback(sub) => {
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.death_callback.enable(self.switch_to_sub, (sub,));
+            }
+            */
 
             // 109
             SubInstruction::MemoryWriteInt(value, index) => {
                 unimplemented!("not again that damn foe corrupted my ret\\x41\\x41\\x41\\x41");
             }
 
+            // 110 
+            /*
+            SubInstruction::KillEnemy(enemy) => {
+                let mut game = self.game.borrow_mut();
+                game.kill_enemy(enemy);
+            }
+            */
+
+            // 111
+            /*
+            SubInstruction::SetLife(value) => {
+                let mut enemy = self.enemy.borrow_mut();
+                let mut game = self.game.borrow_mut();
+                enemy.life = value;
+                game.interface.set_boss_life();
+            }
+            */
+            // 112
+            SubInstruction::SetElapsedTime(value) => {
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.frame = value as u32;
+            }
+            // 113
+            /*
+            SubInstruction::SetLowLifeTrigger(value) => {
+                let mut enemy = self.enemy.borrow_mut();
+                let mut game = self.game.borrow_mut();
+                enemy.low_life_trigger = value;
+                game.interface.set_spell_life();
+            }
+            */
+            // 114
+            /*
+             SubInstruction::SetLowLifeCallback(sub) => {
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.low_life_callback.enable(self.switch_to_sub, (sub,));
+            }
+            */
+            // 115
+            /*
+            SubInstruction::SetTimeout(timeout) => {
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.frame = value;
+                enemy.timeout = timeout;
+            }
+            */
+            // 116
+            /*
+             SubInstruction::SetTimeoutCallback(sub) => {
+                let mut enemy = self.enemy.borrow_mut();
+                enemy.timeout_callback.enable(self.switch_to_sub, (sub,));
+            }
+            */
+
 
             // 117
             SubInstruction::SetTouchable(touchable) => {