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 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 pub fn init_stack(&mut self, parser: &mut Parser) -> Result<()> {
412 let addr = self.get_pc() as u32;
413 self.cursor += 1;
414
415 let args_count = parser.read_i8(self.cursor)?;
417 self.cursor += size_of::<i8>();
418
419 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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#[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}