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