# HG changeset patch # User Emmanuel Gil Peyrot # Date 1565463894 -7200 # Node ID 598f3125cbacc184b3ae056497202ae916259ebe # Parent 31fc0d881105a8dccc3bfe00bb9d64fd5f28057c Implement enough instructions to execute sub 0 from stage 1. diff --git a/examples/eclrenderer.rs b/examples/eclrenderer.rs --- a/examples/eclrenderer.rs +++ b/examples/eclrenderer.rs @@ -165,7 +165,7 @@ fn main() { } } - if frame == 60 { + if ecl_runner.running == false { break; } frame += 1; @@ -214,11 +214,11 @@ fn main() { } } -fn fill_vertices_ptr(sprites: Vec>>, vertices: *mut Vertex) { +fn fill_vertices_ptr(sprites: Vec<(f32, f32, f32, Rc>)>, vertices: *mut Vertex) { let mut fake_vertices = unsafe { std::mem::transmute::<*mut Vertex, &mut [FakeVertex; 4]>(vertices) }; - for sprite in sprites { + for (x, y, z, sprite) in sprites { let sprite = sprite.borrow(); - sprite.fill_vertices(&mut fake_vertices); + sprite.fill_vertices(&mut fake_vertices, x, y, z); } } diff --git a/src/th06/anm0_vm.rs b/src/th06/anm0_vm.rs --- a/src/th06/anm0_vm.rs +++ b/src/th06/anm0_vm.rs @@ -87,7 +87,7 @@ impl Sprite { } /// TODO - pub fn fill_vertices(&self, vertices: &mut [Vertex; 4]) { + pub fn fill_vertices(&self, vertices: &mut [Vertex; 4], x: f32, y: f32, z: f32) { let mut mat = Mat4::new([[-0.5, 0.5, 0.5, -0.5], [-0.5, -0.5, 0.5, 0.5], [0., 0., 0., 0.], @@ -127,6 +127,8 @@ impl Sprite { mat.translate_2d(width / 2., height / 2.); } + mat.translate([x, y, z]); + let mat = mat.borrow_inner(); vertices[0].pos[0] = mat[0][0] as i16; vertices[0].pos[1] = mat[1][0] as i16; diff --git a/src/th06/ecl.rs b/src/th06/ecl.rs --- a/src/th06/ecl.rs +++ b/src/th06/ecl.rs @@ -226,7 +226,7 @@ declare_sub_instructions!{ 100 => fn SetDeathAnim(sprite_index: i32), 101 => fn SetBossMode(value: i32), 102 => fn CreateSquares(UNK1: i32, UNK2: f32, UNK3: f32, UNK4: f32, UNK5: f32), - 103 => fn SetEnemyHitbox(width: f32, height: f32, depth: f32), + 103 => fn SetHitbox(width: f32, height: f32, depth: f32), 104 => fn SetCollidable(collidable: i32), 105 => fn SetDamageable(damageable: i32), 106 => fn PlaySound(index: i32), diff --git a/src/th06/ecl_vm.rs b/src/th06/ecl_vm.rs --- a/src/th06/ecl_vm.rs +++ b/src/th06/ecl_vm.rs @@ -14,7 +14,8 @@ pub struct EclRunner { enemy: Rc>, ecl: Option, sub: u8, - running: bool, + /// XXX + pub running: bool, /// XXX pub frame: i32, ip: i32, @@ -31,6 +32,7 @@ impl EclRunner { // XXX: no clone. ecl: Some(ecl.clone()), sub, + running: true, ..Default::default() } } @@ -143,6 +145,7 @@ impl EclRunner { } fn run_instruction(&mut self, instruction: SubInstruction) { + println!("Running instruction {:?}", instruction); match instruction { SubInstruction::Noop() => { // really @@ -428,16 +431,19 @@ impl EclRunner { */ // 45 SubInstruction::SetAngleAndSpeed(angle, speed) => { + let angle = self.get_f32(angle); + let speed = self.get_f32(speed); let mut enemy = self.enemy.borrow_mut(); enemy.update_mode = 0; - enemy.angle = self.get_f32(angle); - enemy.speed = self.get_f32(speed); + enemy.angle = angle; + enemy.speed = speed; } // 46 SubInstruction::SetRotationSpeed(speed) => { + let rotation_speed = self.get_f32(speed); let mut enemy = self.enemy.borrow_mut(); enemy.update_mode = 0; - enemy.rotation_speed = self.get_f32(speed); + enemy.rotation_speed = rotation_speed; } // 47 SubInstruction::SetSpeed(speed) => { @@ -460,6 +466,28 @@ impl EclRunner { // 83 -> star items >>> life items + // 97 + SubInstruction::SetAnim(index) => { + // TODO: check in ghidra! + let mut enemy = self.enemy.borrow_mut(); + enemy.set_anim(index as u8); + } + + // 100 + SubInstruction::SetDeathAnim(index) => { + // TODO: check in ghidra! + let mut enemy = self.enemy.borrow_mut(); + enemy.death_anim = index; + } + + // 103 + SubInstruction::SetHitbox(width, height, depth) => { + // TODO: check in ghidra! + assert_eq!(depth, 32.); + let mut enemy = self.enemy.borrow_mut(); + enemy.set_hitbox(width, height); + } + _ => unimplemented!() } } diff --git a/src/th06/enemy.rs b/src/th06/enemy.rs --- a/src/th06/enemy.rs +++ b/src/th06/enemy.rs @@ -91,12 +91,14 @@ impl Game { } /// Returns a list of all sprites currently being displayed on screen. - pub fn get_sprites(&self) -> Vec>> { + pub fn get_sprites(&self) -> Vec<(f32, f32, f32, Rc>)> { let mut sprites = vec![]; - for anmrunner in self.anmrunners.iter() { + for enemy in self.enemies.iter() { + let enemy = enemy.borrow(); + let anmrunner = enemy.anmrunner.upgrade().unwrap(); let anmrunner = anmrunner.borrow(); let sprite = anmrunner.get_sprite(); - sprites.push(sprite); + sprites.push((enemy.pos.x, enemy.pos.y, enemy.z, sprite)); } sprites } @@ -139,7 +141,7 @@ pub struct Enemy { pub(crate) remaining_lives: u32, pub(crate) bullet_launch_interval: u32, pub(crate) bullet_launch_timer: u32, - pub(crate) death_anim: u32, + pub(crate) death_anim: i32, pub(crate) direction: u32, pub(crate) update_mode: u32, @@ -245,6 +247,18 @@ impl Enemy { } } +trait Renderable { + fn get_sprites(&self) -> Vec>>; +} + +impl Renderable for Enemy { + fn get_sprites(&self) -> Vec>> { + let anmrunner = self.anmrunner.upgrade().unwrap(); + let anmrunner = anmrunner.borrow(); + vec![anmrunner.get_sprite()] + } +} + #[cfg(test)] mod tests { use super::*;