# HG changeset patch # User Gauvain "GovanifY" Roussel-Tarbouriech # Date 1565273018 -7200 # Node ID 16aa9a636d3578f0272fdc4bedc931285ecf9e54 # Parent 93bdc7b9df15c703972bc4439486529fef268e5b Some starting point for ecl_vm. diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,13 @@ /target **/*.rs.bk Cargo.lock +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags diff --git a/src/th06/ecl_vm.rs b/src/th06/ecl_vm.rs new file mode 100644 --- /dev/null +++ b/src/th06/ecl_vm.rs @@ -0,0 +1,131 @@ +//! ECL runner. + +use crate::th06::anm0::{ + Script, + Anm0, + Call, + Instruction, +}; +use crate::th06::interpolator::{Interpolator1, Interpolator2, Interpolator3, Formula}; +use crate::util::math::Mat4; +use crate::util::prng::Prng; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + + fn run_instruction(&mut self, instruction: Instruction) { + let mut sprite = self.sprite.borrow_mut(); + match instruction { + Instruction::Noop() { + // really + } + // 1 + Instruction::Stop() { + self._enemy.removed = true; + } + // 2 + Instruction::RelativeJump(frame, ip) { + self.frame = frame; + // ip = ip + flag in th06 + self.ip = ip; + // we jump back to the main of the interpreter + } + // 3 + // GHIDRA SAYS THERE IS A COMPARISON_REG BUFFER BUT THERE IS NOT!!! + // + // MOV ECX,dword ptr [EBP + 0x8] jumptable 00407544 case 31 + // CMP dword ptr [0x9d4 + ECX],0x0 + // JLE LAB_00407abb + // aka ECX = enemy pointer + // ECX->9d4 (aka enemy_pointer_copy->comparison_reg) == 0 + // only the pointer is copied, not the value, thus we are safe + Instruction::RelativeJumpEx(frame, ip, var_id) { + // TODO: counter_value is a field of "enemy" in th06, to check + counter_value = self._getval(var_id) - 1 + if counter_value > 0 { + Instruction::RelativeJump(frame, ip); + } + } + + //4, 5 + Instruction::SetVariable(var_id, value) { + self._setval(var_id, value); + } + // 6 + Instruction::SetRandomInt(var_id, maxval) { + self._setval(var_id, self._game.prng.rand_32()%self._getval(maxval)); + } + // 7 + Instruction::SetRandomIntMin(var_id, maxval, minval) { + self._setval(var_id, (self._game.prng.rand_32()%self._getval(maxval))+self._getval(minval)); + } + // 8 + Instruction::SetRandomFloat(var_id, maxval) { + self._setval(var_id, self._getval(maxval) * self._game.prng.rand_double()) + } + // 9 + Instruction::SetRandomFloatMin(var_id, maxval, minval) { + self._setval(var_id, (self._getval(maxval) * self._game.prng.rand_double())+self._getval(minval)) + } + // 10 + Instruction::StoreX(var_id) { + self._setval(var_id, self._enemy.x); + } + // 11 + Instruction::StoreY(var_id) { + self._setval(var_id, self._enemy.y); + } + // 12 + Instruction::StoreZ(var_id) { + self._setval(var_id, self._enemy.z); + } + // 13(int), 20(float), same impl in th06 + Instruction::Add(var_id, a, b) { + self._setval(var_id, self._getval(a) + self._getval(b)); + } + // 14(int), 21(float), same impl in th06 + Instruction::Substract(var_id, a, b) { + self._setval(var_id, self._getval(a) - self._getval(b)); + } + // 15(int), 22(unused) + Instruction::Multiply(var_id, a, b) { + self._setval(var_id, self._getval(a) * self._getval(b)); + } + // 16(int), 23(unused) + Instruction::Divide(var_id, a, b) { + self._setval(var_id, self._getval(a) / self._getval(b)); + } + // 17(int) 24(unused) + Instruction::Divide(var_id, a, b) { + self._setval(var_id, self._getval(a) % self._getval(b)); + } + // 18 + // setval used by pytouhou, but not in game(???) + Instruction::Increment(var_id) { + var_id = self._getval(var_id) + 1 + } + // 19 + Instruction::Decrement(var_id) { + var_id = self._getval(var_id) - 1 + } + //25 + + + + + + // 32 + Instruction::RelativeJumpIfGreaterThan(frame, ip) { + if self.comparison_reg == 1 + Instruction::RelativeJump(); + } + // 34 + Instruction::RelativeJumpIfNotEqual(frame, ip) { + if self.comparison_reg != 0 + Instruction::RelativeJump(); + } + + + + + +