disassembler/
main.rs

1use anyhow::{bail, Result};
2use clap::Parser as ClapParser;
3use serde::{Deserialize, Serialize};
4use rfvp::script::inst::nop::NopInst;
5use std::mem::size_of;
6use std::path::{PathBuf, Path};
7use rfvp::script::inst::*;
8use rfvp::script::opcode::*;
9use rfvp::script::parser::{Nls, Parser};
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![inst.get_arg_count().to_string(), inst.get_local_count().to_string()],
42        }
43    }
44
45    pub fn from_call(inst: CallInst) -> Self {
46        Self {
47            address: inst.address(),
48            mnemonic: inst.opcode().to_string(),
49            operands: vec![inst.get_target().to_string()],
50        }
51    }
52
53    pub fn from_syscall(inst: SyscallInst) -> Self {
54        Self {
55            address: inst.address(),
56            mnemonic: inst.opcode().to_string(),
57            operands: vec![inst.get_syscall_name().to_string()],
58        }
59    }
60
61    pub fn from_ret(inst: RetInst) -> Self {
62        Self {
63            address: inst.address(),
64            mnemonic: inst.opcode().to_string(),
65            operands: Vec::new(),
66        }
67    }
68
69    pub fn from_ret_value(inst: RetValueInst) -> Self {
70        Self {
71            address: inst.address(),
72            mnemonic: inst.opcode().to_string(),
73            operands: Vec::new(),
74        }
75    }
76
77    pub fn from_jmp(inst: JmpInst) -> Self {
78        Self {
79            address: inst.address(),
80            mnemonic: inst.opcode().to_string(),
81            operands: vec![inst.get_target().to_string()],
82        }
83    }
84
85    pub fn from_jz(inst: JzInst) -> Self {
86        Self {
87            address: inst.address(),
88            mnemonic: inst.opcode().to_string(),
89            operands: vec![inst.get_target().to_string()],
90        }
91    }
92
93    pub fn from_push_nil(inst: PushNilInst) -> Self {
94        Self {
95            address: inst.address(),
96            mnemonic: inst.opcode().to_string(),
97            operands: Vec::new(),
98        }
99    }
100
101    pub fn from_push_true(inst: PushTrueInst) -> Self {
102        Self {
103            address: inst.address(),
104            mnemonic: inst.opcode().to_string(),
105            operands: Vec::new(),
106        }
107    }
108
109    pub fn from_push_i32(inst: PushI32Inst) -> Self {
110        Self {
111            address: inst.address(),
112            mnemonic: inst.opcode().to_string(),
113            operands: vec![inst.get_value().to_string()],
114        }
115    }
116
117    pub fn from_push_i16(inst: PushI16Inst) -> Self {
118        Self {
119            address: inst.address(),
120            mnemonic: inst.opcode().to_string(),
121            operands: vec![inst.get_value().to_string()],
122        }
123    }
124
125    pub fn from_push_i8(inst: PushI8Inst) -> Self {
126        Self {
127            address: inst.address(),
128            mnemonic: inst.opcode().to_string(),
129            operands: vec![inst.get_value().to_string()],
130        }
131    }
132
133    pub fn from_push_f32(inst: PushF32Inst) -> Self {
134        Self {
135            address: inst.address(),
136            mnemonic: inst.opcode().to_string(),
137            operands: vec![inst.get_value().to_string()],
138        }
139    }
140
141    pub fn from_push_string(inst: PushStringInst) -> Self {
142        Self {
143            address: inst.address(),
144            mnemonic: inst.opcode().to_string(),
145            operands: vec![inst.get_value().to_string()],
146        }
147    }
148
149    pub fn from_push_global(inst: PushGlobalInst) -> Self {
150        Self {
151            address: inst.address(),
152            mnemonic: inst.opcode().to_string(),
153            operands: vec![inst.get_idx().to_string()],
154        }
155    }
156
157    pub fn from_push_stack(inst: PushStackInst) -> Self {
158        Self {
159            address: inst.address(),
160            mnemonic: inst.opcode().to_string(),
161            operands: vec![inst.get_idx().to_string()],
162        }
163    }
164
165    pub fn from_push_global_table(inst: PushGlobalTableInst) -> Self {
166        Self {
167            address: inst.address(),
168            mnemonic: inst.opcode().to_string(),
169            operands: vec![inst.get_idx().to_string()],
170        }
171    }
172
173    pub fn from_push_local_table(inst: PushLocalTableInst) -> Self {
174        Self {
175            address: inst.address(),
176            mnemonic: inst.opcode().to_string(),
177            operands: vec![inst.get_idx().to_string()],
178        }
179    }
180
181    pub fn from_push_top(inst: PushTopInst) -> Self {
182        Self {
183            address: inst.address(),
184            mnemonic: inst.opcode().to_string(),
185            operands: Vec::new(),
186        }
187    }
188
189    pub fn from_push_return(inst: PushReturnInst) -> Self {
190        Self {
191            address: inst.address(),
192            mnemonic: inst.opcode().to_string(),
193            operands: Vec::new(),
194        }
195    }
196    
197    pub fn from_pop_global(inst: PopGlobalInst) -> Self {
198        Self {
199            address: inst.address(),
200            mnemonic: inst.opcode().to_string(),
201            operands: vec![inst.get_idx().to_string()],
202        }
203    }
204
205    pub fn from_pop_stack(inst: PopStackInst) -> Self {
206        Self {
207            address: inst.address(),
208            mnemonic: inst.opcode().to_string(),
209            operands: vec![inst.get_idx().to_string()],
210        }
211    }
212
213    pub fn from_pop_global_table(inst: PopGlobalTableInst) -> Self {
214        Self {
215            address: inst.address(),
216            mnemonic: inst.opcode().to_string(),
217            operands: vec![inst.get_idx().to_string()],
218        }
219    }
220
221    pub fn from_pop_local_table(inst: PopLocalTableInst) -> Self {
222        Self {
223            address: inst.address(),
224            mnemonic: inst.opcode().to_string(),
225            operands: vec![inst.get_idx().to_string()],
226        }
227    }
228
229    pub fn from_neg(inst: NegInst) -> Self {
230        Self {
231            address: inst.address(),
232            mnemonic: inst.opcode().to_string(),
233            operands: Vec::new(),
234        }
235    }
236
237    pub fn from_add(inst: AddInst) -> Self {
238        Self {
239            address: inst.address(),
240            mnemonic: inst.opcode().to_string(),
241            operands: Vec::new(),
242        }
243    }
244
245    pub fn from_sub(inst: SubInst) -> Self {
246        Self {
247            address: inst.address(),
248            mnemonic: inst.opcode().to_string(),
249            operands: Vec::new(),
250        }
251    }
252
253    pub fn from_mul(inst: MulInst) -> Self {
254        Self {
255            address: inst.address(),
256            mnemonic: inst.opcode().to_string(),
257            operands: Vec::new(),
258        }
259    }
260
261    pub fn from_div(inst: DivInst) -> Self {
262        Self {
263            address: inst.address(),
264            mnemonic: inst.opcode().to_string(),
265            operands: Vec::new(),
266        }
267    }
268
269    pub fn from_mod(inst: ModInst) -> Self {
270        Self {
271            address: inst.address(),
272            mnemonic: inst.opcode().to_string(),
273            operands: Vec::new(),
274        }
275    }
276
277    pub fn from_bittest(inst: BitTestInst) -> Self {
278        Self {
279            address: inst.address(),
280            mnemonic: inst.opcode().to_string(),
281            operands: Vec::new(),
282        }
283    }
284
285    pub fn from_and(inst: AndInst) -> Self {
286        Self {
287            address: inst.address(),
288            mnemonic: inst.opcode().to_string(),
289            operands: Vec::new(),
290        }
291    }
292
293    pub fn from_or(inst: OrInst) -> Self {
294        Self {
295            address: inst.address(),
296            mnemonic: inst.opcode().to_string(),
297            operands: Vec::new(),
298        }
299    }
300
301    pub fn from_sete(inst: SeteInst) -> Self {
302        Self {
303            address: inst.address(),
304            mnemonic: inst.opcode().to_string(),
305            operands: Vec::new(),
306        }
307    }
308
309    pub fn from_setne(inst: SetneInst) -> Self {
310        Self {
311            address: inst.address(),
312            mnemonic: inst.opcode().to_string(),
313            operands: Vec::new(),
314        }
315    }
316
317    pub fn from_setg(inst: SetgInst) -> Self {
318        Self {
319            address: inst.address(),
320            mnemonic: inst.opcode().to_string(),
321            operands: Vec::new(),
322        }
323    }
324
325    pub fn from_setle(inst: SetleInst) -> Self {
326        Self {
327            address: inst.address(),
328            mnemonic: inst.opcode().to_string(),
329            operands: Vec::new(),
330        }
331    }
332
333    pub fn from_setl(inst: SetlInst) -> Self {
334        Self {
335            address: inst.address(),
336            mnemonic: inst.opcode().to_string(),
337            operands: Vec::new(),
338        }
339    }
340
341    pub fn from_setge(inst: SetgeInst) -> Self {
342        Self {
343            address: inst.address(),
344            mnemonic: inst.opcode().to_string(),
345            operands: Vec::new(),
346        }
347    }
348
349}
350
351#[derive(Debug, Serialize, Deserialize)]
352pub struct SyscallEntry {
353    id: u32,
354    name: String,
355    args_count: u8,
356}
357
358#[derive(Debug, Serialize, Deserialize)]
359pub struct ProjectConfig {
360    entry_point: u32,
361    non_volatile_global_count: u16,
362    volatile_global_count: u16,
363    game_mode: u8,
364    game_mode_reserved: u8,
365    game_title: String,
366    syscalls: Vec<SyscallEntry>,
367    custom_syscall_count: u16,
368}
369
370pub struct Disassembler {
371    parser: Parser,
372    cursor: usize,
373    functions: Vec<Function>,
374}
375
376impl Disassembler {
377    pub fn new(path: impl AsRef<Path>, nls: Nls) -> Result<Self> {
378        let parser = Parser::new(path, nls.clone())?;
379        Ok(Self {
380            parser,
381            cursor: 4,
382            functions: Vec::new(),
383        })
384    }
385
386    pub fn get_parser(&self) -> &Parser {
387        &self.parser
388    }
389
390    pub fn get_pc(&self) -> usize {
391        self.cursor
392    }
393
394    /// 0x00 nop instruction
395    /// nop, no operation
396    pub fn nop(&mut self) -> Result<()> {
397        let addr = self.get_pc() as u32;
398        self.cursor += 1;
399        let inst = NopInst::new(addr);
400        let inst = Inst::from_nop(inst);
401        self.functions.last_mut().unwrap().insts.push(inst);
402
403        Ok(())
404    }
405
406    /// 0x01 init stack instruction
407    /// initialize the local routine stack, as well as
408    /// the post-phase of perforimg call instruction or launching a new routine
409    pub fn init_stack(&mut self, parser: &mut Parser) -> Result<()> {
410        let addr = self.get_pc() as u32;
411        self.cursor += 1;
412
413        // how many arguments are passed to the routine
414        let args_count = parser.read_i8(self.cursor)?;
415        self.cursor += size_of::<i8>();
416
417        // how many locals are declared in the routine
418        let locals_count = parser.read_i8(self.cursor)?;
419        self.cursor += size_of::<i8>();
420
421        self.functions.push(Function {
422            address: addr,
423            args_count: args_count as u8,
424            locals_count: locals_count as u8,
425            insts: Vec::new(),
426        });
427
428        let inst = InitStackInst::new(addr, args_count as u8, locals_count as u8);
429        let inst = Inst::from_init_stack(inst);
430        self.functions.last_mut().unwrap().insts.push(inst);
431        
432        Ok(())
433    }
434
435
436    /// 0x02 call instruction
437    /// call a routine
438    pub fn call(&mut self, parser: &mut Parser) -> Result<()> {
439        let addr = self.get_pc() as u32;
440        self.cursor += 1;
441        let target = parser.read_u32(self.cursor)?;
442        self.cursor += size_of::<u32>();
443
444        let inst = CallInst::new(addr, target);
445        let inst = Inst::from_call(inst);
446        self.functions.last_mut().unwrap().insts.push(inst);
447
448        Ok(())
449    }
450
451    /// 0x03 syscall
452    /// call a system call
453    pub fn syscall(&mut self, parser: &mut Parser) -> Result<()> {
454        let addr = self.get_pc() as u32;
455        self.cursor += 1;
456        let id = parser.read_u16(self.cursor)?;
457        self.cursor += size_of::<u16>();
458
459        if let Some(syscall) = parser.get_syscall(id) {
460            let inst = SyscallInst::new(addr, syscall.name.clone());
461            let inst = Inst::from_syscall(inst);
462            self.functions.last_mut().unwrap().insts.push(inst);
463
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.get_parser().get_all_syscalls().iter().map(|(id, sys)| {
1136                SyscallEntry {
1137                    id: *id as u32,
1138                    name: sys.name.clone(),
1139                    args_count: sys.args,
1140                }
1141            }).collect(),
1142            custom_syscall_count: self.get_parser().get_custom_syscall_count(),
1143        };
1144
1145        let yaml_config = output.join("config.yaml");
1146        let mut writer = std::fs::File::create(yaml_config)?;
1147        serde_yaml::to_writer(&mut writer, &config)?;
1148
1149        let project = FVPProject {
1150            config_file: PathBuf::from("config.yaml"),
1151            disassembly_file: PathBuf::from("disassembly.yaml"),
1152        };
1153
1154        let toml_project = output.join("project.toml");
1155        let mut writer = std::fs::File::create(toml_project)?;
1156        let serialized_string = toml::to_string_pretty(&project)?;
1157        writer.write_all(serialized_string.as_bytes())?;
1158
1159        Ok(())
1160    }
1161}
1162
1163
1164#[derive(Debug, Serialize, Deserialize)]
1165pub struct FVPProject {
1166    config_file: PathBuf,
1167    disassembly_file: PathBuf,
1168}
1169
1170/// Simple program to greet a person
1171#[derive(ClapParser, Debug)]
1172#[command(version, about, long_about = None)]
1173struct Args {
1174    #[arg(short, long, required = true)]
1175    input: PathBuf,
1176
1177    #[arg(short, long, required = true)]
1178    output: PathBuf,
1179
1180    #[arg(short, long, default_value = "sjis")]
1181    lang: Nls,
1182}
1183
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}