comparison src/th06/ecl_vm.rs @ 696:7ae576a418ff

ecl_vm: implement Call, Return, and the call stack thingy.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 23 Aug 2019 02:31:08 +0200
parents f5b34a1c2707
children 600eb0a69b25
comparison
equal deleted inserted replaced
695:f5b34a1c2707 696:7ae576a418ff
22 enemy.set_bullet_attributes($opcode, $anim, sprite_index_offset, bullets_per_shot, 22 enemy.set_bullet_attributes($opcode, $anim, sprite_index_offset, bullets_per_shot,
23 number_of_shots, speed, speed2, launch_angle, angle, $flags); 23 number_of_shots, speed, speed2, launch_angle, angle, $flags);
24 }}; 24 }};
25 } 25 }
26 26
27 type Variables = ([i32; 4], [f32; 4], [i32; 4]); 27 #[derive(Clone, Default)]
28 struct StackFrame {
29 frame: i32,
30 ip: i32,
31 //ins122_callback: Option<Box<FnMut(Enemy)>>,
32 ints1: [i32; 4],
33 floats: [f32; 4],
34 ints2: [i32; 4],
35 comparison_reg: i32,
36 sub: u16,
37 }
28 38
29 /// Interpreter for enemy scripts. 39 /// Interpreter for enemy scripts.
30 #[derive(Default)] 40 #[derive(Default)]
31 pub struct EclRunner { 41 pub struct EclRunner {
32 enemy: Rc<RefCell<Enemy>>, 42 enemy: Rc<RefCell<Enemy>>,
33 ecl: Option<Ecl>, 43 ecl: Option<Ecl>,
34 sub: u8,
35 /// XXX 44 /// XXX
36 pub running: bool, 45 pub running: bool,
37 /// XXX 46 frame: StackFrame,
38 pub frame: i32, 47 // TODO: there are only 8 of these.
39 ip: i32, 48 stack: Vec<StackFrame>,
40 variables: Variables,
41 comparison_reg: i8,
42 stack: Vec<Variables>,
43 } 49 }
44 50
45 impl EclRunner { 51 impl EclRunner {
46 /// Create a new ECL runner. 52 /// Create a new ECL runner.
47 pub fn new(ecl: &Ecl, enemy: Rc<RefCell<Enemy>>, sub: u8) -> EclRunner { 53 pub fn new(ecl: &Ecl, enemy: Rc<RefCell<Enemy>>, sub: u16) -> EclRunner {
48 EclRunner { 54 let mut ecl_runner = EclRunner {
49 enemy, 55 enemy,
50 // XXX: no clone. 56 // XXX: no clone.
51 ecl: Some(ecl.clone()), 57 ecl: Some(ecl.clone()),
52 sub,
53 running: true, 58 running: true,
54 ..Default::default() 59 ..Default::default()
55 } 60 };
61 ecl_runner.frame.sub = sub;
62 ecl_runner
56 } 63 }
57 64
58 /// Advance the ECL of a single frame. 65 /// Advance the ECL of a single frame.
59 pub fn run_frame(&mut self) { 66 pub fn run_frame(&mut self) {
60 while self.running { 67 while self.running {
61 let ecl = self.ecl.clone().unwrap(); 68 let ecl = self.ecl.clone().unwrap();
62 let sub = &ecl.subs[self.sub as usize]; 69 let sub = &ecl.subs[self.frame.sub as usize];
63 let call = match sub.instructions.get(self.ip as usize) { 70 let call = match sub.instructions.get(self.frame.ip as usize) {
64 Some(call) => call, 71 Some(call) => call,
65 None => { 72 None => {
66 self.running = false; 73 self.running = false;
67 break; 74 break;
68 } 75 }
69 }; 76 };
70 77
71 if call.time > self.frame { 78 if call.time > self.frame.frame {
72 break; 79 break;
73 } 80 }
74 self.ip += 1; 81 self.frame.ip += 1;
75 82
76 let rank = self.enemy.borrow().get_rank(); 83 let rank = self.enemy.borrow().get_rank();
77 if (call.rank_mask & rank).is_empty() { 84 if (call.rank_mask & rank).is_empty() {
78 continue; 85 continue;
79 } 86 }
80 87
81 if call.time == self.frame { 88 if call.time == self.frame.frame {
82 self.run_instruction(call.instr.clone()); 89 self.run_instruction(call.instr.clone());
83 } 90 }
84 } 91 }
85 self.frame += 1; 92 self.frame.frame += 1;
86 } 93 }
87 94
88 fn get_i32(&self, var: i32) -> i32 { 95 fn get_i32(&self, var: i32) -> i32 {
89 let enemy = self.enemy.borrow(); 96 let enemy = self.enemy.borrow();
90 match var { 97 match var {
91 -10001 => self.variables.0[0], 98 -10001 => self.frame.ints1[0],
92 -10002 => self.variables.0[1], 99 -10002 => self.frame.ints1[1],
93 -10003 => self.variables.0[2], 100 -10003 => self.frame.ints1[2],
94 -10004 => self.variables.0[3], 101 -10004 => self.frame.ints1[3],
95 -10005 => self.variables.1[0] as i32, 102 -10005 => self.frame.floats[0] as i32,
96 -10006 => self.variables.1[1] as i32, 103 -10006 => self.frame.floats[1] as i32,
97 -10007 => self.variables.1[2] as i32, 104 -10007 => self.frame.floats[2] as i32,
98 -10008 => self.variables.1[3] as i32, 105 -10008 => self.frame.floats[3] as i32,
99 -10009 => self.variables.2[0], 106 -10009 => self.frame.ints2[0],
100 -10010 => self.variables.2[1], 107 -10010 => self.frame.ints2[1],
101 -10011 => self.variables.2[2], 108 -10011 => self.frame.ints2[2],
102 -10012 => self.variables.2[3], 109 -10012 => self.frame.ints2[3],
103 -10013 => enemy.get_rank().bits() as i32, 110 -10013 => enemy.get_rank().bits() as i32,
104 -10014 => enemy.get_difficulty(), 111 -10014 => enemy.get_difficulty(),
105 -10015 => enemy.pos.x as i32, 112 -10015 => enemy.pos.x as i32,
106 -10016 => enemy.pos.y as i32, 113 -10016 => enemy.pos.y as i32,
107 -10017 => enemy.z as i32, 114 -10017 => enemy.z as i32,
118 } 125 }
119 126
120 fn get_f32(&self, var: f32) -> f32 { 127 fn get_f32(&self, var: f32) -> f32 {
121 let enemy = self.enemy.borrow(); 128 let enemy = self.enemy.borrow();
122 match var { 129 match var {
123 -10001.0 => self.variables.0[0] as f32, 130 -10001.0 => self.frame.ints1[0] as f32,
124 -10002.0 => self.variables.0[1] as f32, 131 -10002.0 => self.frame.ints1[1] as f32,
125 -10003.0 => self.variables.0[2] as f32, 132 -10003.0 => self.frame.ints1[2] as f32,
126 -10004.0 => self.variables.0[3] as f32, 133 -10004.0 => self.frame.ints1[3] as f32,
127 -10005.0 => self.variables.1[0], 134 -10005.0 => self.frame.floats[0],
128 -10006.0 => self.variables.1[1], 135 -10006.0 => self.frame.floats[1],
129 -10007.0 => self.variables.1[2], 136 -10007.0 => self.frame.floats[2],
130 -10008.0 => self.variables.1[3], 137 -10008.0 => self.frame.floats[3],
131 -10009.0 => self.variables.2[0] as f32, 138 -10009.0 => self.frame.ints2[0] as f32,
132 -10010.0 => self.variables.2[1] as f32, 139 -10010.0 => self.frame.ints2[1] as f32,
133 -10011.0 => self.variables.2[2] as f32, 140 -10011.0 => self.frame.ints2[2] as f32,
134 -10012.0 => self.variables.2[3] as f32, 141 -10012.0 => self.frame.ints2[3] as f32,
135 -10013.0 => enemy.get_rank().bits() as f32, 142 -10013.0 => enemy.get_rank().bits() as f32,
136 -10014.0 => enemy.get_difficulty() as f32, 143 -10014.0 => enemy.get_difficulty() as f32,
137 -10015.0 => enemy.pos.x, 144 -10015.0 => enemy.pos.x,
138 -10016.0 => enemy.pos.y, 145 -10016.0 => enemy.pos.y,
139 -10017.0 => enemy.z, 146 -10017.0 => enemy.z,
150 } 157 }
151 158
152 fn set_i32(&mut self, var: i32, value: i32) { 159 fn set_i32(&mut self, var: i32, value: i32) {
153 let mut enemy = self.enemy.borrow_mut(); 160 let mut enemy = self.enemy.borrow_mut();
154 match var { 161 match var {
155 -10001 => self.variables.0[0] = value, 162 -10001 => self.frame.ints1[0] = value,
156 -10002 => self.variables.0[1] = value, 163 -10002 => self.frame.ints1[1] = value,
157 -10003 => self.variables.0[2] = value, 164 -10003 => self.frame.ints1[2] = value,
158 -10004 => self.variables.0[3] = value, 165 -10004 => self.frame.ints1[3] = value,
159 -10005 => unimplemented!(), 166 -10005 => unimplemented!(),
160 -10006 => unimplemented!(), 167 -10006 => unimplemented!(),
161 -10007 => unimplemented!(), 168 -10007 => unimplemented!(),
162 -10008 => unimplemented!(), 169 -10008 => unimplemented!(),
163 -10009 => self.variables.2[0] = value, 170 -10009 => self.frame.ints2[0] = value,
164 -10010 => self.variables.2[1] = value, 171 -10010 => self.frame.ints2[1] = value,
165 -10011 => self.variables.2[2] = value, 172 -10011 => self.frame.ints2[2] = value,
166 -10012 => self.variables.2[3] = value, 173 -10012 => self.frame.ints2[3] = value,
167 -10013 => unreachable!(), 174 -10013 => unreachable!(),
168 -10014 => unreachable!(), 175 -10014 => unreachable!(),
169 -10015 => unimplemented!(), 176 -10015 => unimplemented!(),
170 -10016 => unimplemented!(), 177 -10016 => unimplemented!(),
171 -10017 => unimplemented!(), 178 -10017 => unimplemented!(),
186 match var { 193 match var {
187 -10001.0 => unimplemented!(), 194 -10001.0 => unimplemented!(),
188 -10002.0 => unimplemented!(), 195 -10002.0 => unimplemented!(),
189 -10003.0 => unimplemented!(), 196 -10003.0 => unimplemented!(),
190 -10004.0 => unimplemented!(), 197 -10004.0 => unimplemented!(),
191 -10005.0 => self.variables.1[0] = value, 198 -10005.0 => self.frame.floats[0] = value,
192 -10006.0 => self.variables.1[1] = value, 199 -10006.0 => self.frame.floats[1] = value,
193 -10007.0 => self.variables.1[2] = value, 200 -10007.0 => self.frame.floats[2] = value,
194 -10008.0 => self.variables.1[3] = value, 201 -10008.0 => self.frame.floats[3] = value,
195 -10009.0 => unimplemented!(), 202 -10009.0 => unimplemented!(),
196 -10010.0 => unimplemented!(), 203 -10010.0 => unimplemented!(),
197 -10011.0 => unimplemented!(), 204 -10011.0 => unimplemented!(),
198 -10012.0 => unimplemented!(), 205 -10012.0 => unimplemented!(),
199 -10013.0 => unreachable!(), 206 -10013.0 => unreachable!(),
229 let mut enemy = self.enemy.borrow_mut(); 236 let mut enemy = self.enemy.borrow_mut();
230 enemy.removed = true; 237 enemy.removed = true;
231 } 238 }
232 // 2 239 // 2
233 SubInstruction::RelativeJump(frame, ip) => { 240 SubInstruction::RelativeJump(frame, ip) => {
234 self.frame = frame; 241 self.frame.frame = frame;
235 // ip = ip + flag in th06 242 // ip = ip + flag in th06
236 self.ip = ip; 243 self.frame.ip = ip;
237 // we jump back to the main of the interpreter 244 // we jump back to the main of the interpreter
238 } 245 }
239 // 3 246 // 3
240 // GHIDRA SAYS THERE IS A COMPARISON_REG BUFFER BUT THERE IS NOT!!! 247 // GHIDRA SAYS THERE IS A COMPARISON_REG BUFFER BUT THERE IS NOT!!!
241 // 248 //
373 // 27(int), 28(float) 380 // 27(int), 28(float)
374 SubInstruction::CompareInts(a, b) => { 381 SubInstruction::CompareInts(a, b) => {
375 let a = self.get_i32(a); 382 let a = self.get_i32(a);
376 let b = self.get_i32(b); 383 let b = self.get_i32(b);
377 if a < b { 384 if a < b {
378 self.comparison_reg = -1; 385 self.frame.comparison_reg = -1;
379 } 386 }
380 else if a == b { 387 else if a == b {
381 self.comparison_reg = 0; 388 self.frame.comparison_reg = 0;
382 } 389 }
383 else { 390 else {
384 self.comparison_reg = 1; 391 self.frame.comparison_reg = 1;
385 } 392 }
386 } 393 }
387 SubInstruction::CompareFloats(a, b) => { 394 SubInstruction::CompareFloats(a, b) => {
388 let a = self.get_f32(a); 395 let a = self.get_f32(a);
389 let b = self.get_f32(b); 396 let b = self.get_f32(b);
390 if a < b { 397 if a < b {
391 self.comparison_reg = -1; 398 self.frame.comparison_reg = -1;
392 } 399 }
393 else if a == b { 400 else if a == b {
394 self.comparison_reg = 0; 401 self.frame.comparison_reg = 0;
395 } 402 }
396 else { 403 else {
397 self.comparison_reg = 1; 404 self.frame.comparison_reg = 1;
398 } 405 }
399 } 406 }
400 // 29 407 // 29
401 SubInstruction::RelativeJumpIfLowerThan(frame, ip) => { 408 SubInstruction::RelativeJumpIfLowerThan(frame, ip) => {
402 if self.comparison_reg == -1 { 409 if self.frame.comparison_reg == -1 {
403 SubInstruction::RelativeJump(frame, ip); 410 SubInstruction::RelativeJump(frame, ip);
404 } 411 }
405 } 412 }
406 // 30 413 // 30
407 SubInstruction::RelativeJumpIfLowerOrEqual(frame, ip) => { 414 SubInstruction::RelativeJumpIfLowerOrEqual(frame, ip) => {
408 if self.comparison_reg != 1 { 415 if self.frame.comparison_reg != 1 {
409 SubInstruction::RelativeJump(frame, ip); 416 SubInstruction::RelativeJump(frame, ip);
410 } 417 }
411 } 418 }
412 // 31 419 // 31
413 SubInstruction::RelativeJumpIfEqual(frame, ip) => { 420 SubInstruction::RelativeJumpIfEqual(frame, ip) => {
414 if self.comparison_reg == 0 { 421 if self.frame.comparison_reg == 0 {
415 SubInstruction::RelativeJump(frame, ip); 422 SubInstruction::RelativeJump(frame, ip);
416 } 423 }
417 } 424 }
418 // 32 425 // 32
419 SubInstruction::RelativeJumpIfGreaterThan(frame, ip) => { 426 SubInstruction::RelativeJumpIfGreaterThan(frame, ip) => {
420 if self.comparison_reg == 1 { 427 if self.frame.comparison_reg == 1 {
421 SubInstruction::RelativeJump(frame, ip); 428 SubInstruction::RelativeJump(frame, ip);
422 } 429 }
423 } 430 }
424 // 33 431 // 33
425 SubInstruction::RelativeJumpIfGreaterOrEqual(frame, ip) => { 432 SubInstruction::RelativeJumpIfGreaterOrEqual(frame, ip) => {
426 if self.comparison_reg != -1 { 433 if self.frame.comparison_reg != -1 {
427 SubInstruction::RelativeJump(frame, ip); 434 SubInstruction::RelativeJump(frame, ip);
428 } 435 }
429 } 436 }
430 // 34 437 // 34
431 SubInstruction::RelativeJumpIfNotEqual(frame, ip) => { 438 SubInstruction::RelativeJumpIfNotEqual(frame, ip) => {
432 if self.comparison_reg != 0 { 439 if self.frame.comparison_reg != 0 {
433 SubInstruction::RelativeJump(frame, ip); 440 SubInstruction::RelativeJump(frame, ip);
434 } 441 }
435 } 442 }
436 // 35 443 // 35
437 SubInstruction::Call(sub, param1, param2) => { 444 SubInstruction::Call(sub, param1, param2) => {
438 // does insane stuff with the stack, not implemented 445 self.stack.push(self.frame.clone());
439 unimplemented!() 446 self.frame.sub = sub as u16;
447 self.frame.ints1[0] = param1;
448 self.frame.floats[0] = param2;
449 self.frame.frame = 0;
450 self.frame.ip = 0;
440 } 451 }
441 452
442 // 36 453 // 36
443 SubInstruction::Return() => { 454 SubInstruction::Return() => {
444 // does insane stuff with the stack, not implemented 455 self.frame = self.stack.pop().unwrap();
445 unimplemented!()
446 } 456 }
447 // 37 457 // 37
448 SubInstruction::CallIfSuperior(sub, param1, param2, a, b) => { 458 SubInstruction::CallIfSuperior(sub, param1, param2, a, b) => {
449 if self.get_i32(a) < self.get_i32(b) { 459 if self.get_i32(a) < self.get_i32(b) {
450 SubInstruction::Call(sub, param1, param2); 460 self.run_instruction(SubInstruction::Call(sub, param1, param2));
451 } 461 }
452 } 462 }
453 // 38 463 // 38
454 SubInstruction::CallIfSuperiorOrEqual(sub, param1, param2, a, b) => { 464 SubInstruction::CallIfSuperiorOrEqual(sub, param1, param2, a, b) => {
455 if self.get_i32(a) <= self.get_i32(b) { 465 if self.get_i32(a) <= self.get_i32(b) {
456 SubInstruction::Call(sub, param1, param2); 466 self.run_instruction(SubInstruction::Call(sub, param1, param2));
457 } 467 }
458 } 468 }
459 // 39 469 // 39
460 SubInstruction::CallIfEqual(sub, param1, param2, a, b) => { 470 SubInstruction::CallIfEqual(sub, param1, param2, a, b) => {
461 if self.get_i32(a) == self.get_i32(b) { 471 if self.get_i32(a) == self.get_i32(b) {
462 SubInstruction::Call(sub, param1, param2); 472 self.run_instruction(SubInstruction::Call(sub, param1, param2));
463 } 473 }
464 } 474 }
465 // 40 475 // 40
466 SubInstruction::CallIfInferior(sub, param1, param2, a, b) => { 476 SubInstruction::CallIfInferior(sub, param1, param2, a, b) => {
467 if self.get_i32(b) < self.get_i32(a) { 477 if self.get_i32(b) < self.get_i32(a) {
468 SubInstruction::Call(sub, param1, param2); 478 self.run_instruction(SubInstruction::Call(sub, param1, param2));
469 } 479 }
470 } 480 }
471 481
472 // 41 482 // 41
473 SubInstruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) => { 483 SubInstruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) => {
474 if self.get_i32(b) <= self.get_i32(a) { 484 if self.get_i32(b) <= self.get_i32(a) {
475 SubInstruction::Call(sub, param1, param2); 485 self.run_instruction(SubInstruction::Call(sub, param1, param2));
476 } 486 }
477 } 487 }
478 //42 488 //42
479 SubInstruction::CallIfNotEqual(sub, param1, param2, a, b) => { 489 SubInstruction::CallIfNotEqual(sub, param1, param2, a, b) => {
480 if self.get_i32(a) != self.get_i32(b) { 490 if self.get_i32(a) != self.get_i32(b) {
481 SubInstruction::Call(sub, param1, param2); 491 self.run_instruction(SubInstruction::Call(sub, param1, param2));
482 } 492 }
483 } 493 }
484 494
485 // 43 495 // 43
486 SubInstruction::SetPosition(x, y, z) => { 496 SubInstruction::SetPosition(x, y, z) => {
727 // which, uhhhh, we are not going to reimplement for obvious reasons 737 // which, uhhhh, we are not going to reimplement for obvious reasons
728 // the correct implementation would be: if this laser does not exist have a 738 // the correct implementation would be: if this laser does not exist have a
729 // 1/100000 chance to continue, otherwise crash 739 // 1/100000 chance to continue, otherwise crash
730 if enemy.laser_by_id.contains_key(&laser_id) { 740 if enemy.laser_by_id.contains_key(&laser_id) {
731 // let's assume we gud 741 // let's assume we gud
732 self.comparison_reg = 1; 742 self.frame.comparison_reg = 1;
733 } 743 }
734 else{ 744 else{
735 self.comparison_reg = 0; 745 self.frame.comparison_reg = 0;
736 } 746 }
737 } 747 }
738 748
739 // 92 749 // 92
740 /* 750 /*