Skip to main content

disassembler/
main.rs

1use anyhow::{bail, Result};
2use clap::Parser as ClapParser;
3use rfvp::script::inst::nop::NopInst;
4use rfvp::script::inst::*;
5use rfvp::script::opcode::*;
6use rfvp::script::parser::{Nls, Parser};
7use serde::{Deserialize, Serialize};
8use std::mem::size_of;
9use std::path::{Path, PathBuf};
10
11use std::io::Write;
12
13#[derive(Debug, Serialize, Deserialize)]
14pub struct Function {
15    address: u32,
16    args_count: u8,
17    locals_count: u8,
18    insts: Vec<Inst>,
19}
20
21#[derive(Debug, Serialize, Deserialize)]
22pub struct Inst {
23    address: u32,
24    mnemonic: String,
25    operands: Vec<String>,
26}
27
28impl Inst {
29    pub fn from_nop(inst: NopInst) -> Self {
30        Self {
31            address: inst.address(),
32            mnemonic: inst.opcode().to_string(),
33            operands: Vec::new(),
34        }
35    }
36
37    pub fn from_init_stack(inst: InitStackInst) -> Self {
38        Self {
39            address: inst.address(),
40            mnemonic: inst.opcode().to_string(),
41            operands: vec![
42                inst.get_arg_count().to_string(),
43                inst.get_local_count().to_string(),
44            ],
45        }
46    }
47
48    pub fn from_call(inst: CallInst) -> Self {
49        Self {
50            address: inst.address(),
51            mnemonic: inst.opcode().to_string(),
52            operands: vec![inst.get_target().to_string()],
53        }
54    }
55
56    pub fn from_syscall(inst: SyscallInst) -> Self {
57        Self {
58            address: inst.address(),
59            mnemonic: inst.opcode().to_string(),
60            operands: vec![inst.get_syscall_name().to_string()],
61        }
62    }
63
64    pub fn from_ret(inst: RetInst) -> Self {
65        Self {
66            address: inst.address(),
67            mnemonic: inst.opcode().to_string(),
68            operands: Vec::new(),
69        }
70    }
71
72    pub fn from_ret_value(inst: RetValueInst) -> Self {
73        Self {
74            address: inst.address(),
75            mnemonic: inst.opcode().to_string(),
76            operands: Vec::new(),
77        }
78    }
79
80    pub fn from_jmp(inst: JmpInst) -> Self {
81        Self {
82            address: inst.address(),
83            mnemonic: inst.opcode().to_string(),
84            operands: vec![inst.get_target().to_string()],
85        }
86    }
87
88    pub fn from_jz(inst: JzInst) -> Self {
89        Self {
90            address: inst.address(),
91            mnemonic: inst.opcode().to_string(),
92            operands: vec![inst.get_target().to_string()],
93        }
94    }
95
96    pub fn from_push_nil(inst: PushNilInst) -> Self {
97        Self {
98            address: inst.address(),
99            mnemonic: inst.opcode().to_string(),
100            operands: Vec::new(),
101        }
102    }
103
104    pub fn from_push_true(inst: PushTrueInst) -> Self {
105        Self {
106            address: inst.address(),
107            mnemonic: inst.opcode().to_string(),
108            operands: Vec::new(),
109        }
110    }
111
112    pub fn from_push_i32(inst: PushI32Inst) -> Self {
113        Self {
114            address: inst.address(),
115            mnemonic: inst.opcode().to_string(),
116            operands: vec![inst.get_value().to_string()],
117        }
118    }
119
120    pub fn from_push_i16(inst: PushI16Inst) -> Self {
121        Self {
122            address: inst.address(),
123            mnemonic: inst.opcode().to_string(),
124            operands: vec![inst.get_value().to_string()],
125        }
126    }
127
128    pub fn from_push_i8(inst: PushI8Inst) -> Self {
129        Self {
130            address: inst.address(),
131            mnemonic: inst.opcode().to_string(),
132            operands: vec![inst.get_value().to_string()],
133        }
134    }
135
136    pub fn from_push_f32(inst: PushF32Inst) -> Self {
137        Self {
138            address: inst.address(),
139            mnemonic: inst.opcode().to_string(),
140            operands: vec![inst.get_value().to_string()],
141        }
142    }
143
144    pub fn from_push_string(inst: PushStringInst) -> Self {
145        Self {
146            address: inst.address(),
147            mnemonic: inst.opcode().to_string(),
148            operands: vec![inst.get_value().to_string()],
149        }
150    }
151
152    pub fn from_push_global(inst: PushGlobalInst) -> Self {
153        Self {
154            address: inst.address(),
155            mnemonic: inst.opcode().to_string(),
156            operands: vec![inst.get_idx().to_string()],
157        }
158    }
159
160    pub fn from_push_stack(inst: PushStackInst) -> Self {
161        Self {
162            address: inst.address(),
163            mnemonic: inst.opcode().to_string(),
164            operands: vec![inst.get_idx().to_string()],
165        }
166    }
167
168    pub fn from_push_global_table(inst: PushGlobalTableInst) -> Self {
169        Self {
170            address: inst.address(),
171            mnemonic: inst.opcode().to_string(),
172            operands: vec![inst.get_idx().to_string()],
173        }
174    }
175
176    pub fn from_push_local_table(inst: PushLocalTableInst) -> Self {
177        Self {
178            address: inst.address(),
179            mnemonic: inst.opcode().to_string(),
180            operands: vec![inst.get_idx().to_string()],
181        }
182    }
183
184    pub fn from_push_top(inst: PushTopInst) -> Self {
185        Self {
186            address: inst.address(),
187            mnemonic: inst.opcode().to_string(),
188            operands: Vec::new(),
189        }
190    }
191
192    pub fn from_push_return(inst: PushReturnInst) -> Self {
193        Self {
194            address: inst.address(),
195            mnemonic: inst.opcode().to_string(),
196            operands: Vec::new(),
197        }
198    }
199
200    pub fn from_pop_global(inst: PopGlobalInst) -> Self {
201        Self {
202            address: inst.address(),
203            mnemonic: inst.opcode().to_string(),
204            operands: vec![inst.get_idx().to_string()],
205        }
206    }
207
208    pub fn from_pop_stack(inst: PopStackInst) -> Self {
209        Self {
210            address: inst.address(),
211            mnemonic: inst.opcode().to_string(),
212            operands: vec![inst.get_idx().to_string()],
213        }
214    }
215
216    pub fn from_pop_global_table(inst: PopGlobalTableInst) -> Self {
217        Self {
218            address: inst.address(),
219            mnemonic: inst.opcode().to_string(),
220            operands: vec![inst.get_idx().to_string()],
221        }
222    }
223
224    pub fn from_pop_local_table(inst: PopLocalTableInst) -> Self {
225        Self {
226            address: inst.address(),
227            mnemonic: inst.opcode().to_string(),
228            operands: vec![inst.get_idx().to_string()],
229        }
230    }
231
232    pub fn from_neg(inst: NegInst) -> Self {
233        Self {
234            address: inst.address(),
235            mnemonic: inst.opcode().to_string(),
236            operands: Vec::new(),
237        }
238    }
239
240    pub fn from_add(inst: AddInst) -> Self {
241        Self {
242            address: inst.address(),
243            mnemonic: inst.opcode().to_string(),
244            operands: Vec::new(),
245        }
246    }
247
248    pub fn from_sub(inst: SubInst) -> Self {
249        Self {
250            address: inst.address(),
251            mnemonic: inst.opcode().to_string(),
252            operands: Vec::new(),
253        }
254    }
255
256    pub fn from_mul(inst: MulInst) -> Self {
257        Self {
258            address: inst.address(),
259            mnemonic: inst.opcode().to_string(),
260            operands: Vec::new(),
261        }
262    }
263
264    pub fn from_div(inst: DivInst) -> Self {
265        Self {
266            address: inst.address(),
267            mnemonic: inst.opcode().to_string(),
268            operands: Vec::new(),
269        }
270    }
271
272    pub fn from_mod(inst: ModInst) -> Self {
273        Self {
274            address: inst.address(),
275            mnemonic: inst.opcode().to_string(),
276            operands: Vec::new(),
277        }
278    }
279
280    pub fn from_bittest(inst: BitTestInst) -> Self {
281        Self {
282            address: inst.address(),
283            mnemonic: inst.opcode().to_string(),
284            operands: Vec::new(),
285        }
286    }
287
288    pub fn from_and(inst: AndInst) -> Self {
289        Self {
290            address: inst.address(),
291            mnemonic: inst.opcode().to_string(),
292            operands: Vec::new(),
293        }
294    }
295
296    pub fn from_or(inst: OrInst) -> Self {
297        Self {
298            address: inst.address(),
299            mnemonic: inst.opcode().to_string(),
300            operands: Vec::new(),
301        }
302    }
303
304    pub fn from_sete(inst: SeteInst) -> Self {
305        Self {
306            address: inst.address(),
307            mnemonic: inst.opcode().to_string(),
308            operands: Vec::new(),
309        }
310    }
311
312    pub fn from_setne(inst: SetneInst) -> Self {
313        Self {
314            address: inst.address(),
315            mnemonic: inst.opcode().to_string(),
316            operands: Vec::new(),
317        }
318    }
319
320    pub fn from_setg(inst: SetgInst) -> Self {
321        Self {
322            address: inst.address(),
323            mnemonic: inst.opcode().to_string(),
324            operands: Vec::new(),
325        }
326    }
327
328    pub fn from_setle(inst: SetleInst) -> Self {
329        Self {
330            address: inst.address(),
331            mnemonic: inst.opcode().to_string(),
332            operands: Vec::new(),
333        }
334    }
335
336    pub fn from_setl(inst: SetlInst) -> Self {
337        Self {
338            address: inst.address(),
339            mnemonic: inst.opcode().to_string(),
340            operands: Vec::new(),
341        }
342    }
343
344    pub fn from_setge(inst: SetgeInst) -> Self {
345        Self {
346            address: inst.address(),
347            mnemonic: inst.opcode().to_string(),
348            operands: Vec::new(),
349        }
350    }
351}
352
353#[derive(Debug, Serialize, Deserialize)]
354pub struct SyscallEntry {
355    id: u32,
356    name: String,
357    args_count: u8,
358}
359
360#[derive(Debug, Serialize, Deserialize)]
361pub struct ProjectConfig {
362    entry_point: u32,
363    non_volatile_global_count: u16,
364    volatile_global_count: u16,
365    game_mode: u8,
366    game_mode_reserved: u8,
367    game_title: String,
368    syscalls: Vec<SyscallEntry>,
369    custom_syscall_count: u16,
370}
371
372pub struct Disassembler {
373    parser: Parser,
374    cursor: usize,
375    functions: Vec<Function>,
376}
377
378impl Disassembler {
379    pub fn new(path: impl AsRef<Path>, nls: Nls) -> Result<Self> {
380        let parser = Parser::new(path, nls.clone())?;
381        Ok(Self {
382            parser,
383            cursor: 4,
384            functions: Vec::new(),
385        })
386    }
387
388    pub fn get_parser(&self) -> &Parser {
389        &self.parser
390    }
391
392    pub fn get_pc(&self) -> usize {
393        self.cursor
394    }
395
396    /// 0x00 nop instruction
397    /// nop, no operation
398    pub fn nop(&mut self) -> Result<()> {
399        let addr = self.get_pc() as u32;
400        self.cursor += 1;
401        let inst = NopInst::new(addr);
402        let inst = Inst::from_nop(inst);
403        self.functions.last_mut().unwrap().insts.push(inst);
404
405        Ok(())
406    }
407
408    /// 0x01 init stack instruction
409    /// initialize the local routine stack, as well as
410    /// the post-phase of perforimg call instruction or launching a new routine
411    pub fn init_stack(&mut self, parser: &mut Parser) -> Result<()> {
412        let addr = self.get_pc() as u32;
413        self.cursor += 1;
414
415        // how many arguments are passed to the routine
416        let args_count = parser.read_i8(self.cursor)?;
417        self.cursor += size_of::<i8>();
418
419        // how many locals are declared in the routine
420        let locals_count = parser.read_i8(self.cursor)?;
421        self.cursor += size_of::<i8>();
422
423        self.functions.push(Function {
424            address: addr,
425            args_count: args_count as u8,
426            locals_count: locals_count as u8,
427            insts: Vec::new(),
428        });
429
430        let inst = InitStackInst::new(addr, args_count as u8, locals_count as u8);
431        let inst = Inst::from_init_stack(inst);
432        self.functions.last_mut().unwrap().insts.push(inst);
433
434        Ok(())
435    }
436
437    /// 0x02 call instruction
438    /// call a routine
439    pub fn call(&mut self, parser: &mut Parser) -> Result<()> {
440        let addr = self.get_pc() as u32;
441        self.cursor += 1;
442        let target = parser.read_u32(self.cursor)?;
443        self.cursor += size_of::<u32>();
444
445        let inst = CallInst::new(addr, target);
446        let inst = Inst::from_call(inst);
447        self.functions.last_mut().unwrap().insts.push(inst);
448
449        Ok(())
450    }
451
452    /// 0x03 syscall
453    /// call a system call
454    pub fn syscall(&mut self, parser: &mut Parser) -> Result<()> {
455        let addr = self.get_pc() as u32;
456        self.cursor += 1;
457        let id = parser.read_u16(self.cursor)?;
458        self.cursor += size_of::<u16>();
459
460        if let Some(syscall) = parser.get_syscall(id) {
461            let inst = SyscallInst::new(addr, syscall.name.clone());
462            let inst = Inst::from_syscall(inst);
463            self.functions.last_mut().unwrap().insts.push(inst);
464        } else {
465            bail!("syscall not found: {}", id);
466        }
467
468        Ok(())
469    }
470
471    /// 0x04 ret instruction
472    /// return from a routine
473    pub fn ret(&mut self) -> Result<()> {
474        let addr = self.get_pc() as u32;
475        self.cursor += 1;
476
477        let inst = RetInst::new(addr);
478        let inst = Inst::from_ret(inst);
479        self.functions.last_mut().unwrap().insts.push(inst);
480
481        Ok(())
482    }
483
484    /// 0x05 retv instruction
485    /// return from a routine with a value
486    pub fn retv(&mut self) -> Result<()> {
487        let addr = self.get_pc() as u32;
488        self.cursor += 1;
489
490        let inst = RetValueInst::new(addr);
491        let inst = Inst::from_ret_value(inst);
492        self.functions.last_mut().unwrap().insts.push(inst);
493
494        Ok(())
495    }
496
497    /// 0x06 jmp instruction
498    /// jump to the address
499    pub fn jmp(&mut self, parser: &mut Parser) -> Result<()> {
500        let addr = self.get_pc() as u32;
501        self.cursor += 1;
502        let target = parser.read_u32(self.cursor)?;
503        self.cursor += size_of::<u32>();
504
505        let inst = JmpInst::new(addr, target);
506        let inst = Inst::from_jmp(inst);
507        self.functions.last_mut().unwrap().insts.push(inst);
508
509        Ok(())
510    }
511
512    /// 0x07 jz instruction
513    /// jump to the address if the top of the stack is zero
514    pub fn jz(&mut self, parser: &mut Parser) -> Result<()> {
515        let addr = self.get_pc() as u32;
516        self.cursor += 1;
517        let target = parser.read_u32(self.cursor)?;
518        self.cursor += size_of::<u32>();
519
520        let inst = JzInst::new(addr, target);
521        let inst = Inst::from_jz(inst);
522        self.functions.last_mut().unwrap().insts.push(inst);
523
524        Ok(())
525    }
526
527    /// 0x08 push nil
528    /// push a nil value onto the stack
529    pub fn push_nil(&mut self) -> Result<()> {
530        let addr = self.get_pc() as u32;
531        self.cursor += 1;
532
533        let inst = PushNilInst::new(addr);
534        let inst = Inst::from_push_nil(inst);
535        self.functions.last_mut().unwrap().insts.push(inst);
536
537        Ok(())
538    }
539
540    /// 0x09 push true
541    /// push a true value onto the stack
542    pub fn push_true(&mut self) -> Result<()> {
543        let addr = self.get_pc() as u32;
544        self.cursor += 1;
545
546        let inst = PushTrueInst::new(addr);
547        let inst = Inst::from_push_true(inst);
548        self.functions.last_mut().unwrap().insts.push(inst);
549
550        Ok(())
551    }
552
553    /// 0x0A push i32
554    /// push an i32 value onto the stack
555    pub fn push_i32(&mut self, parser: &mut Parser) -> Result<()> {
556        let addr = self.get_pc() as u32;
557        self.cursor += 1;
558
559        let value = parser.read_i32(self.cursor)?;
560        self.cursor += size_of::<i32>();
561
562        let inst = PushI32Inst::new(addr, value);
563        let inst = Inst::from_push_i32(inst);
564        self.functions.last_mut().unwrap().insts.push(inst);
565
566        Ok(())
567    }
568
569    /// 0x0B push i16
570    /// push an i16 value onto the stack
571    pub fn push_i16(&mut self, parser: &mut Parser) -> Result<()> {
572        let addr = self.get_pc() as u32;
573        self.cursor += 1;
574        let value = parser.read_i16(self.cursor)?;
575        self.cursor += size_of::<i16>();
576
577        let inst = PushI16Inst::new(addr, value);
578        let inst = Inst::from_push_i16(inst);
579        self.functions.last_mut().unwrap().insts.push(inst);
580
581        Ok(())
582    }
583
584    /// 0x0C push i8
585    /// push an i8 value onto the stack
586    pub fn push_i8(&mut self, parser: &mut Parser) -> Result<()> {
587        let addr = self.get_pc() as u32;
588        self.cursor += 1;
589        let value = parser.read_i8(self.cursor)?;
590        self.cursor += size_of::<i8>();
591
592        let inst = PushI8Inst::new(addr, value);
593        let inst = Inst::from_push_i8(inst);
594        self.functions.last_mut().unwrap().insts.push(inst);
595
596        Ok(())
597    }
598
599    /// 0x0D push f32
600    /// push an f32 value onto the stack
601    pub fn push_f32(&mut self, parser: &mut Parser) -> Result<()> {
602        let addr = self.get_pc() as u32;
603        self.cursor += 1;
604        let value = parser.read_f32(self.cursor)?;
605        self.cursor += size_of::<f32>();
606
607        let inst = PushF32Inst::new(addr, value);
608        let inst = Inst::from_push_f32(inst);
609        self.functions.last_mut().unwrap().insts.push(inst);
610
611        Ok(())
612    }
613
614    /// 0x0E push string
615    /// push a string onto the stack
616    pub fn push_string(&mut self, parser: &mut Parser) -> Result<()> {
617        let addr = self.get_pc() as u32;
618        self.cursor += 1;
619        let len = parser.read_u8(self.cursor)? as usize;
620        self.cursor += size_of::<u8>();
621
622        let s = parser.read_cstring(self.cursor, len)?;
623        self.cursor += len;
624
625        let inst = PushStringInst::new(addr, s);
626        let inst = Inst::from_push_string(inst);
627        self.functions.last_mut().unwrap().insts.push(inst);
628
629        Ok(())
630    }
631
632    /// 0x0F push global
633    /// push a global variable onto the stack
634    pub fn push_global(&mut self, parser: &mut Parser) -> Result<()> {
635        let addr = self.get_pc() as u32;
636        self.cursor += 1;
637        let key = parser.read_u16(self.cursor)?;
638        self.cursor += size_of::<u16>();
639
640        let inst = PushGlobalInst::new(addr, key as u32);
641        let inst = Inst::from_push_global(inst);
642        self.functions.last_mut().unwrap().insts.push(inst);
643
644        Ok(())
645    }
646
647    /// 0x10 push stack
648    /// push a stack variable onto the stack
649    pub fn push_stack(&mut self, parser: &mut Parser) -> Result<()> {
650        let addr = self.get_pc() as u32;
651        self.cursor += 1;
652        let offset = parser.read_i8(self.cursor)?;
653        self.cursor += size_of::<i8>();
654
655        let inst = PushStackInst::new(addr, offset);
656        let inst = Inst::from_push_stack(inst);
657        self.functions.last_mut().unwrap().insts.push(inst);
658
659        Ok(())
660    }
661
662    /// 0x11 push global table
663    /// push a value than stored in the global table by immediate key onto the stack
664    /// we assume that if any failure occurs, such as the key not found,
665    /// we will push a nil value onto the stack for compatibility reasons.
666    pub fn push_global_table(&mut self, parser: &mut Parser) -> Result<()> {
667        let addr = self.get_pc() as u32;
668        self.cursor += 1;
669        let key = parser.read_u16(self.cursor)?;
670        self.cursor += size_of::<u16>();
671
672        let inst = PushGlobalTableInst::new(addr, key as u32);
673        let inst = Inst::from_push_global_table(inst);
674        self.functions.last_mut().unwrap().insts.push(inst);
675
676        Ok(())
677    }
678
679    /// 0x12 push local table
680    /// push a value than stored in the local table by key onto the stack
681    pub fn push_local_table(&mut self, parser: &mut Parser) -> Result<()> {
682        let addr = self.get_pc() as u32;
683        self.cursor += 1;
684        let idx = parser.read_i8(self.cursor)?;
685        self.cursor += size_of::<i8>();
686
687        let inst = PushLocalTableInst::new(addr, idx);
688        let inst = Inst::from_push_local_table(inst);
689        self.functions.last_mut().unwrap().insts.push(inst);
690
691        Ok(())
692    }
693
694    /// 0x13 push top
695    /// push the top of the stack onto the stack
696    pub fn push_top(&mut self) -> Result<()> {
697        let addr = self.get_pc() as u32;
698        self.cursor += 1;
699
700        let inst = PushTopInst::new(addr);
701        let inst = Inst::from_push_top(inst);
702        self.functions.last_mut().unwrap().insts.push(inst);
703
704        Ok(())
705    }
706
707    /// 0x14 push return value
708    /// push the return value onto the stack
709    pub fn push_return_value(&mut self) -> Result<()> {
710        let addr = self.get_pc() as u32;
711        self.cursor += 1;
712
713        let inst = PushReturnInst::new(addr);
714        let inst = Inst::from_push_return(inst);
715        self.functions.last_mut().unwrap().insts.push(inst);
716
717        Ok(())
718    }
719
720    /// 0x15 pop global
721    /// pop the top of the stack and store it in the global table
722    pub fn pop_global(&mut self, parser: &mut Parser) -> Result<()> {
723        let addr = self.get_pc() as u32;
724        self.cursor += 1;
725        let key = parser.read_u16(self.cursor)?;
726        self.cursor += size_of::<u16>();
727
728        let inst = PopGlobalInst::new(addr, key as u32);
729        let inst = Inst::from_pop_global(inst);
730        self.functions.last_mut().unwrap().insts.push(inst);
731
732        Ok(())
733    }
734
735    /// 0x16 local copy
736    /// copy the top of the stack to the local variable
737    pub fn local_copy(&mut self, parser: &mut Parser) -> Result<()> {
738        let addr = self.get_pc() as u32;
739        self.cursor += 1;
740        let idx = parser.read_i8(self.cursor)?;
741        self.cursor += size_of::<i8>();
742
743        let inst = PopStackInst::new(addr, idx);
744        let inst = Inst::from_pop_stack(inst);
745        self.functions.last_mut().unwrap().insts.push(inst);
746
747        Ok(())
748    }
749
750    /// 0x17 pop global table
751    /// pop the top of the stack and store it in the global table by key
752    pub fn pop_global_table(&mut self, parser: &mut Parser) -> Result<()> {
753        let addr = self.get_pc() as u32;
754        self.cursor += 1;
755        let key = parser.read_u16(self.cursor)?;
756        self.cursor += size_of::<u16>();
757
758        let inst = PopGlobalTableInst::new(addr, key as u32);
759        let inst = Inst::from_pop_global_table(inst);
760        self.functions.last_mut().unwrap().insts.push(inst);
761
762        Ok(())
763    }
764
765    /// 0x18 pop local table
766    /// pop the top of the stack and store it in the local table by key
767    pub fn pop_local_table(&mut self, parser: &mut Parser) -> Result<()> {
768        let addr = self.get_pc() as u32;
769        self.cursor += 1;
770        let idx = parser.read_i8(self.cursor)?;
771        self.cursor += size_of::<i8>();
772
773        let inst = PopLocalTableInst::new(addr, idx);
774        let inst = Inst::from_pop_local_table(inst);
775        self.functions.last_mut().unwrap().insts.push(inst);
776
777        Ok(())
778    }
779
780    /// 0x19 neg
781    /// negate the top of the stack, only works for integers and floats
782    pub fn neg(&mut self) -> Result<()> {
783        let addr = self.get_pc() as u32;
784        self.cursor += 1;
785
786        let inst = NegInst::new(addr);
787        let inst = Inst::from_neg(inst);
788        self.functions.last_mut().unwrap().insts.push(inst);
789
790        Ok(())
791    }
792
793    /// 0x1A add
794    /// add the top two values on the stack
795    pub fn add(&mut self) -> Result<()> {
796        let addr = self.get_pc() as u32;
797        self.cursor += 1;
798
799        let inst = AddInst::new(addr);
800        let inst = Inst::from_add(inst);
801        self.functions.last_mut().unwrap().insts.push(inst);
802
803        Ok(())
804    }
805
806    /// 0x1B sub
807    /// subtract the top two values on the stack
808    pub fn sub(&mut self) -> Result<()> {
809        let addr = self.get_pc() as u32;
810        self.cursor += 1;
811
812        let inst = SubInst::new(addr);
813        let inst = Inst::from_sub(inst);
814        self.functions.last_mut().unwrap().insts.push(inst);
815
816        Ok(())
817    }
818
819    /// 0x1C mul
820    /// multiply the top two values on the stack
821    pub fn mul(&mut self) -> Result<()> {
822        let addr = self.get_pc() as u32;
823        self.cursor += 1;
824
825        let inst = MulInst::new(addr);
826        let inst = Inst::from_mul(inst);
827        self.functions.last_mut().unwrap().insts.push(inst);
828
829        Ok(())
830    }
831
832    /// 0x1D div
833    /// divide the top two values on the stack
834    pub fn div(&mut self) -> Result<()> {
835        let addr = self.get_pc() as u32;
836        self.cursor += 1;
837
838        let inst = DivInst::new(addr);
839        let inst = Inst::from_div(inst);
840        self.functions.last_mut().unwrap().insts.push(inst);
841
842        Ok(())
843    }
844
845    /// 0x1E modulo
846    /// modulo the top two values on the stack
847    pub fn modulo(&mut self) -> Result<()> {
848        let addr = self.get_pc() as u32;
849        self.cursor += 1;
850
851        let inst = ModInst::new(addr);
852        let inst = Inst::from_mod(inst);
853        self.functions.last_mut().unwrap().insts.push(inst);
854
855        Ok(())
856    }
857
858    /// 0x1F bittest
859    /// test with the top two values on the stack
860    pub fn bittest(&mut self) -> Result<()> {
861        let addr = self.get_pc() as u32;
862        self.cursor += 1;
863
864        let inst = BitTestInst::new(addr);
865        let inst = Inst::from_bittest(inst);
866        self.functions.last_mut().unwrap().insts.push(inst);
867
868        Ok(())
869    }
870
871    /// 0x20 and
872    /// push true if both the top two values on the stack are none-nil
873    pub fn and(&mut self) -> Result<()> {
874        let addr = self.get_pc() as u32;
875        self.cursor += 1;
876
877        let inst = AndInst::new(addr);
878        let inst = Inst::from_and(inst);
879        self.functions.last_mut().unwrap().insts.push(inst);
880
881        Ok(())
882    }
883
884    /// 0x21 or
885    /// push true if either of the top two values on the stack is none-nil
886    pub fn or(&mut self) -> Result<()> {
887        let addr = self.get_pc() as u32;
888        self.cursor += 1;
889
890        let inst = OrInst::new(addr);
891        let inst = Inst::from_or(inst);
892        self.functions.last_mut().unwrap().insts.push(inst);
893
894        Ok(())
895    }
896
897    /// 0x22 sete
898    /// set the top of the stack to true if the top two values on the stack are equal
899    pub fn sete(&mut self) -> Result<()> {
900        let addr = self.get_pc() as u32;
901        self.cursor += 1;
902
903        let inst = SeteInst::new(addr);
904        let inst = Inst::from_sete(inst);
905        self.functions.last_mut().unwrap().insts.push(inst);
906
907        Ok(())
908    }
909
910    /// 0x23 setne
911    /// set the top of the stack to true if the top two values on the stack are not equal
912    pub fn setne(&mut self) -> Result<()> {
913        let addr = self.get_pc() as u32;
914        self.cursor += 1;
915
916        let inst = SetneInst::new(addr);
917        let inst = Inst::from_setne(inst);
918        self.functions.last_mut().unwrap().insts.push(inst);
919
920        Ok(())
921    }
922
923    /// 0x24 setg
924    /// set the top of the stack to true if the top two values on the stack are greater
925    pub fn setg(&mut self) -> Result<()> {
926        let addr = self.get_pc() as u32;
927        self.cursor += 1;
928
929        let inst = SetgInst::new(addr);
930        let inst = Inst::from_setg(inst);
931        self.functions.last_mut().unwrap().insts.push(inst);
932
933        Ok(())
934    }
935
936    /// 0x25 setle
937    /// set the top of the stack to true if the top two values on the stack are less or equal
938    pub fn setle(&mut self) -> Result<()> {
939        let addr = self.get_pc() as u32;
940        self.cursor += 1;
941
942        let inst = SetleInst::new(addr);
943        let inst = Inst::from_setle(inst);
944        self.functions.last_mut().unwrap().insts.push(inst);
945
946        Ok(())
947    }
948
949    /// 0x26 setl
950    /// set the top of the stack to true if the top two values on the stack are less
951    pub fn setl(&mut self) -> Result<()> {
952        let addr = self.get_pc() as u32;
953        self.cursor += 1;
954
955        let inst = SetlInst::new(addr);
956        let inst = Inst::from_setl(inst);
957        self.functions.last_mut().unwrap().insts.push(inst);
958
959        Ok(())
960    }
961
962    /// 0x27 setge
963    /// set the top of the stack to true if the top two values on the stack are greater or equal
964    pub fn setge(&mut self) -> Result<()> {
965        let addr = self.get_pc() as u32;
966        self.cursor += 1;
967
968        let inst = SetgeInst::new(addr);
969        let inst = Inst::from_setge(inst);
970        self.functions.last_mut().unwrap().insts.push(inst);
971
972        Ok(())
973    }
974
975    fn disassemble_opcode(&mut self, parser: &mut Parser) -> Result<()> {
976        let opcode = parser.read_u8(self.get_pc())? as i32;
977
978        match opcode.try_into() {
979            Ok(Opcode::Nop) => {
980                self.nop()?;
981            }
982            Ok(Opcode::InitStack) => {
983                self.init_stack(parser)?;
984            }
985            Ok(Opcode::Call) => {
986                self.call(parser)?;
987            }
988            Ok(Opcode::Syscall) => {
989                self.syscall(parser)?;
990            }
991            Ok(Opcode::Ret) => {
992                self.ret()?;
993            }
994            Ok(Opcode::RetV) => {
995                self.retv()?;
996            }
997            Ok(Opcode::Jmp) => {
998                self.jmp(parser)?;
999            }
1000            Ok(Opcode::Jz) => {
1001                self.jz(parser)?;
1002            }
1003            Ok(Opcode::PushNil) => {
1004                self.push_nil()?;
1005            }
1006            Ok(Opcode::PushTrue) => {
1007                self.push_true()?;
1008            }
1009            Ok(Opcode::PushI32) => {
1010                self.push_i32(parser)?;
1011            }
1012            Ok(Opcode::PushI16) => {
1013                self.push_i16(parser)?;
1014            }
1015            Ok(Opcode::PushI8) => {
1016                self.push_i8(parser)?;
1017            }
1018            Ok(Opcode::PushF32) => {
1019                self.push_f32(parser)?;
1020            }
1021            Ok(Opcode::PushString) => {
1022                self.push_string(parser)?;
1023            }
1024            Ok(Opcode::PushGlobal) => {
1025                self.push_global(parser)?;
1026            }
1027            Ok(Opcode::PushStack) => {
1028                self.push_stack(parser)?;
1029            }
1030            Ok(Opcode::PushGlobalTable) => {
1031                self.push_global_table(parser)?;
1032            }
1033            Ok(Opcode::PushLocalTable) => {
1034                self.push_local_table(parser)?;
1035            }
1036            Ok(Opcode::PushTop) => {
1037                self.push_top()?;
1038            }
1039            Ok(Opcode::PushReturn) => {
1040                self.push_return_value()?;
1041            }
1042            Ok(Opcode::PopGlobal) => {
1043                self.pop_global(parser)?;
1044            }
1045            Ok(Opcode::PopStack) => {
1046                self.local_copy(parser)?;
1047            }
1048            Ok(Opcode::PopGlobalTable) => {
1049                self.pop_global_table(parser)?;
1050            }
1051            Ok(Opcode::PopLocalTable) => {
1052                self.pop_local_table(parser)?;
1053            }
1054            Ok(Opcode::Neg) => {
1055                self.neg()?;
1056            }
1057            Ok(Opcode::Add) => {
1058                self.add()?;
1059            }
1060            Ok(Opcode::Sub) => {
1061                self.sub()?;
1062            }
1063            Ok(Opcode::Mul) => {
1064                self.mul()?;
1065            }
1066            Ok(Opcode::Div) => {
1067                self.div()?;
1068            }
1069            Ok(Opcode::Mod) => {
1070                self.modulo()?;
1071            }
1072            Ok(Opcode::BitTest) => {
1073                self.bittest()?;
1074            }
1075            Ok(Opcode::And) => {
1076                self.and()?;
1077            }
1078            Ok(Opcode::Or) => {
1079                self.or()?;
1080            }
1081            Ok(Opcode::SetE) => {
1082                self.sete()?;
1083            }
1084            Ok(Opcode::SetNE) => {
1085                self.setne()?;
1086            }
1087            Ok(Opcode::SetG) => {
1088                self.setg()?;
1089            }
1090            Ok(Opcode::SetLE) => {
1091                self.setle()?;
1092            }
1093            Ok(Opcode::SetL) => {
1094                self.setl()?;
1095            }
1096            Ok(Opcode::SetGE) => {
1097                self.setge()?;
1098            }
1099            _ => {
1100                self.nop()?;
1101                log::error!("unknown opcode: {}", opcode);
1102            }
1103        };
1104
1105        Ok(())
1106    }
1107
1108    pub fn disassemble(&mut self) -> Result<()> {
1109        let mut parser = self.parser.clone();
1110        while self.get_pc() < parser.get_sys_desc_offset() as usize {
1111            self.disassemble_opcode(&mut parser)?;
1112        }
1113
1114        Ok(())
1115    }
1116
1117    pub fn write_insts(&self, path: impl AsRef<Path>) -> Result<()> {
1118        // create a new directory
1119        let output = path.as_ref();
1120        if !output.exists() {
1121            std::fs::create_dir_all(output)?;
1122        }
1123
1124        let disassembly_path = output.join("disassembly.yaml");
1125        let mut writer = std::fs::File::create(disassembly_path)?;
1126        serde_yaml::to_writer(&mut writer, &self.functions)?;
1127
1128        let config = ProjectConfig {
1129            entry_point: self.get_parser().get_entry_point(),
1130            non_volatile_global_count: self.get_parser().get_non_volatile_global_count(),
1131            volatile_global_count: self.get_parser().get_volatile_global_count(),
1132            game_mode: self.get_parser().get_game_mode(),
1133            game_mode_reserved: self.get_parser().get_game_mode_reserved(),
1134            game_title: self.get_parser().get_title(),
1135            syscalls: self
1136                .get_parser()
1137                .get_all_syscalls()
1138                .iter()
1139                .map(|(id, sys)| SyscallEntry {
1140                    id: *id as u32,
1141                    name: sys.name.clone(),
1142                    args_count: sys.args,
1143                })
1144                .collect(),
1145            custom_syscall_count: self.get_parser().get_custom_syscall_count(),
1146        };
1147
1148        let yaml_config = output.join("config.yaml");
1149        let mut writer = std::fs::File::create(yaml_config)?;
1150        serde_yaml::to_writer(&mut writer, &config)?;
1151
1152        let project = FVPProject {
1153            config_file: PathBuf::from("config.yaml"),
1154            disassembly_file: PathBuf::from("disassembly.yaml"),
1155        };
1156
1157        let toml_project = output.join("project.toml");
1158        let mut writer = std::fs::File::create(toml_project)?;
1159        let serialized_string = toml::to_string_pretty(&project)?;
1160        writer.write_all(serialized_string.as_bytes())?;
1161
1162        Ok(())
1163    }
1164}
1165
1166#[derive(Debug, Serialize, Deserialize)]
1167pub struct FVPProject {
1168    config_file: PathBuf,
1169    disassembly_file: PathBuf,
1170}
1171
1172/// Simple program to greet a person
1173#[derive(ClapParser, Debug)]
1174#[command(version, about, long_about = None)]
1175struct Args {
1176    #[arg(short, long, required = true)]
1177    input: PathBuf,
1178
1179    #[arg(short, long, required = true)]
1180    output: PathBuf,
1181
1182    #[arg(short, long, default_value = "sjis")]
1183    lang: Nls,
1184}
1185
1186fn main() -> Result<()> {
1187    let args = Args::parse();
1188    let mut disassembler = Disassembler::new(args.input, args.lang)?;
1189    disassembler.disassemble()?;
1190    disassembler.write_insts(args.output)?;
1191
1192    Ok(())
1193}
1194
1195#[cfg(test)]
1196mod tests {
1197    use super::*;
1198
1199    #[test]
1200    fn test_disassembler() -> Result<()> {
1201        let input = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/testcase/Snow.hcb"));
1202        let output = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/testcase/Snow"));
1203        let mut disassembler = Disassembler::new(input, Nls::ShiftJIS)?;
1204        disassembler.disassemble()?;
1205        disassembler.write_insts(output)?;
1206
1207        Ok(())
1208    }
1209}