This commit is contained in:
Trevor Merritt 2025-07-09 10:36:21 -04:00
parent a5042383c9
commit 258e4dc59b
3 changed files with 64 additions and 41 deletions

View File

@ -1,11 +1,13 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::fs::File;
use std::path::PathBuf; use std::path::PathBuf;
use std::thread::current; use std::thread::current;
use core::constants::constants_system::*; use core::constants::constants_system::*;
use core::constants::constants_isa_op::*; use core::constants::constants_isa_op::*;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use core::instruction_table::INSTRUCTION_TABLE; use core::instruction_table::INSTRUCTION_TABLE;
use std::io::Write;
#[derive(Parser)] #[derive(Parser)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
@ -67,28 +69,29 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> {
let target_op = INSTRUCTION_TABLE[next_byte as usize].clone(); let target_op = INSTRUCTION_TABLE[next_byte as usize].clone();
if let Some(top) = target_op { if let Some(top) = target_op {
println!("Instruction {:?}/{:?} needs {:?} bytes.", top.operation, top.mode, top.length); // println!("Instruction {:?}/{:?} needs {:?} bytes.", top.operation, top.mode, top.length);
let num_bytes_to_load = top.length - 1; let num_bytes_to_load = top.length - 1;
println!("Need {num_bytes_to_load} more bytes."); println!("Need {num_bytes_to_load} more bytes.");
let mut formatted_asm = format!("{}{}", top.format_prefix, top.format_postfix); let mut formatted_asm = String::from(top.format_prefix);
let mut param = None;
if num_bytes_to_load == 1 { if num_bytes_to_load == 1 {
bytes.push(data[current_data_position as usize + 1]); bytes.push(data[current_data_position as usize + 1]);
formatted_asm = format!("{}{:02x}", formatted_asm, bytes[1]); formatted_asm = format!("{}{:02x}{}", formatted_asm, bytes[1], top.format_postfix);
}; };
if num_bytes_to_load == 2 { if num_bytes_to_load == 2 {
bytes.push(data[current_data_position as usize + 1]); bytes.push(data[current_data_position as usize + 1]);
bytes.push(data[current_data_position as usize + 2]); bytes.push(data[current_data_position as usize + 2]);
// 16 bit parameter. // 16 bit parameter.
let param = ((bytes[2] as u16) << 8) | bytes[1] as u16; param = Some(((bytes[2] as u16) << 8) | bytes[1] as u16);
formatted_asm = format!("{} ${:04x}", formatted_asm, param); formatted_asm = format!("{}{:04x}{}", formatted_asm, param.unwrap(), top.format_postfix);
}; };
// figure out how long the instruction is and read that much more data // figure out how long the instruction is and read that much more data
lines.insert(current_data_position, DecompiledLine { lines.insert(current_data_position, DecompiledLine {
offset: current_data_position, offset: current_data_position,
text: formatted_asm, text: String::from(formatted_asm),
label: None, label: None,
bytes, bytes,
}); });
@ -140,9 +143,12 @@ fn main() {
println!("Loaded {}b", loaded_data.len()); println!("Loaded {}b", loaded_data.len());
// ...load the array to the WorkingProgram structure... // ...load the array to the WorkingProgram structure...
let result = decompile(&loaded_data); let result = decompile(&loaded_data);
let mut output_file = File::create(opts.output).unwrap();
// ...reap the decompiled code. // ...reap the decompiled code.
for (_, line) in &result { for (_, line) in &result {
println!("{:width$}; {:?}", line.text,line.bytes, width=30 ); let line =format!("{:width$}; {:?}", line.text,line.bytes, width=30 );
println!("{}", line);
writeln!(output_file, "{}", line).expect("cant write output file. you picked the red snapper.");
} }
} }

View File

@ -112,7 +112,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Immediate, mode: AddressMode::Immediate,
length: 2, length: 2,
cycles: 2, cycles: 2,
format_prefix: "TBD", format_prefix: "AND #$",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_AND_Z as usize] = Some(OpInfo { table[ISA_OP_AND_Z as usize] = Some(OpInfo {
@ -120,7 +120,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPage, mode: AddressMode::ZeroPage,
length: 2, length: 2,
cycles: 3, cycles: 3,
format_prefix: "TBD", format_prefix: "AND $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_AND_ZX as usize] = Some(OpInfo { table[ISA_OP_AND_ZX as usize] = Some(OpInfo {
@ -128,15 +128,15 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPageX, mode: AddressMode::ZeroPageX,
length: 2, length: 2,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "AND $",
format_postfix: "", format_postfix: ",X",
}); });
table[ISA_OP_AND_ABS as usize] = Some(OpInfo { table[ISA_OP_AND_ABS as usize] = Some(OpInfo {
operation: AND, operation: AND,
mode: AddressMode::Absolute, mode: AddressMode::Absolute,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "AND $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_AND_ABSX as usize] = Some(OpInfo { table[ISA_OP_AND_ABSX as usize] = Some(OpInfo {
@ -144,16 +144,16 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::AbsoluteX, mode: AddressMode::AbsoluteX,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "AND $",
format_postfix: "", format_postfix: ",X",
}); });
table[ISA_OP_AND_ABSY as usize] = Some(OpInfo { table[ISA_OP_AND_ABSY as usize] = Some(OpInfo {
operation: AND, operation: AND,
mode: AddressMode::AbsoluteY, mode: AddressMode::AbsoluteY,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "AND $",
format_postfix: "", format_postfix: ",Y",
}); });
table[ISA_OP_AND_INDX as usize] = Some(OpInfo { table[ISA_OP_AND_INDX as usize] = Some(OpInfo {
operation: AND, operation: AND,
@ -1122,8 +1122,8 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::IndirectY, mode: AddressMode::IndirectY,
length: 2, length: 2,
cycles: 5, cycles: 5,
format_prefix: "TBD", format_prefix: "SBC ($",
format_postfix: "", format_postfix: "),Y",
}); });
table[ISA_OP_SEC as usize] = Some(OpInfo { table[ISA_OP_SEC as usize] = Some(OpInfo {
@ -1131,7 +1131,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Implied, mode: AddressMode::Implied,
length: 1, length: 1,
cycles: 2, cycles: 2,
format_prefix: "TBD", format_prefix: "SEC",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_SED as usize] = Some(OpInfo { table[ISA_OP_SED as usize] = Some(OpInfo {
@ -1139,7 +1139,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Implied, mode: AddressMode::Implied,
length: 1, length: 1,
cycles: 2, cycles: 2,
format_prefix: "TBD", format_prefix: "SED",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_SEI as usize] = Some(OpInfo { table[ISA_OP_SEI as usize] = Some(OpInfo {
@ -1147,7 +1147,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Implied, mode: AddressMode::Implied,
length: 1, length: 1,
cycles: 2, cycles: 2,
format_prefix: "TBD", format_prefix: "SEI",
format_postfix: "", format_postfix: "",
}); });
@ -1156,7 +1156,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPage, mode: AddressMode::ZeroPage,
length: 2, length: 2,
cycles: 3, cycles: 3,
format_prefix: "TBD", format_prefix: "STA $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_STA_ZPX as usize] = Some(OpInfo { table[ISA_OP_STA_ZPX as usize] = Some(OpInfo {
@ -1164,15 +1164,15 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPageX, mode: AddressMode::ZeroPageX,
length: 2, length: 2,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STA $",
format_postfix: "", format_postfix: ",X",
}); });
table[ISA_OP_STA_ABS as usize] = Some(OpInfo { table[ISA_OP_STA_ABS as usize] = Some(OpInfo {
operation: Operation::STA, operation: Operation::STA,
mode: AddressMode::Absolute, mode: AddressMode::Absolute,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STA $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_STA_ABSX as usize] = Some(OpInfo { table[ISA_OP_STA_ABSX as usize] = Some(OpInfo {
@ -1180,32 +1180,32 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::AbsoluteX, mode: AddressMode::AbsoluteX,
length: 3, length: 3,
cycles: 5, cycles: 5,
format_prefix: "TBD", format_prefix: "STA $",
format_postfix: "", format_postfix: ",X",
}); });
table[ISA_OP_STA_ABSY as usize] = Some(OpInfo { table[ISA_OP_STA_ABSY as usize] = Some(OpInfo {
operation: Operation::STA, operation: Operation::STA,
mode: AddressMode::AbsoluteY, mode: AddressMode::AbsoluteY,
length: 3, length: 3,
cycles: 5, cycles: 5,
format_prefix: "TBD", format_prefix: "STA $",
format_postfix: "", format_postfix: ",Y",
}); });
table[ISA_OP_STA_INDX as usize] = Some(OpInfo { table[ISA_OP_STA_INDX as usize] = Some(OpInfo {
operation: Operation::STA, operation: Operation::STA,
mode: AddressMode::IndirectX, mode: AddressMode::IndirectX,
length: 2, length: 2,
cycles: 6, cycles: 6,
format_prefix: "TBD", format_prefix: "STA ($",
format_postfix: "", format_postfix: ",X)",
}); });
table[ISA_OP_STA_INDY as usize] = Some(OpInfo { table[ISA_OP_STA_INDY as usize] = Some(OpInfo {
operation: Operation::STA, operation: Operation::STA,
mode: AddressMode::IndirectY, mode: AddressMode::IndirectY,
length: 2, length: 2,
cycles: 6, cycles: 6,
format_prefix: "TBD", format_prefix: "STA ($",
format_postfix: "", format_postfix: "),Y",
}); });
table[ISA_OP_STX_ZP as usize] = Some(OpInfo { table[ISA_OP_STX_ZP as usize] = Some(OpInfo {
@ -1213,7 +1213,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPage, mode: AddressMode::ZeroPage,
length: 2, length: 2,
cycles: 3, cycles: 3,
format_prefix: "TBD", format_prefix: "STX $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_STX_ZPY as usize] = Some(OpInfo { table[ISA_OP_STX_ZPY as usize] = Some(OpInfo {
@ -1221,7 +1221,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPageY, mode: AddressMode::ZeroPageY,
length: 2, length: 2,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STX",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_STX_ABS as usize] = Some(OpInfo { table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
@ -1229,7 +1229,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Absolute, mode: AddressMode::Absolute,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STX",
format_postfix: "", format_postfix: "",
}); });
@ -1238,7 +1238,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPage, mode: AddressMode::ZeroPage,
length: 2, length: 2,
cycles: 3, cycles: 3,
format_prefix: "TBD", format_prefix: "STY $",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_STY_ZPX as usize] = Some(OpInfo { table[ISA_OP_STY_ZPX as usize] = Some(OpInfo {
@ -1246,15 +1246,15 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::ZeroPageX, mode: AddressMode::ZeroPageX,
length: 2, length: 2,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STY $",
format_postfix: "", format_postfix: ",X",
}); });
table[ISA_OP_STY_ABS as usize] = Some(OpInfo { table[ISA_OP_STY_ABS as usize] = Some(OpInfo {
operation: Operation::STY, operation: Operation::STY,
mode: AddressMode::Absolute, mode: AddressMode::Absolute,
length: 3, length: 3,
cycles: 4, cycles: 4,
format_prefix: "TBD", format_prefix: "STY $",
format_postfix: "", format_postfix: "",
}); });
@ -1263,7 +1263,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
mode: AddressMode::Implied, mode: AddressMode::Implied,
length: 1, length: 1,
cycles: 2, cycles: 2,
format_prefix: "TBD", format_prefix: "TAX",
format_postfix: "", format_postfix: "",
}); });
table[ISA_OP_TAY as usize] = Some(OpInfo { table[ISA_OP_TAY as usize] = Some(OpInfo {

View File

@ -0,0 +1,17 @@
; Test of instructions for the decompiler
;
; This file is intended to be assembled and then
; used as an input to a test that decompiles the
; binary back to the text version of the instructions
ADC #$ab ; ADC Immediate
ADC $ab ; ADC ZeroPage
ADC $ab,X ; ADC ZeroPageX
ADC $abcd ; ADC Absolute
ADC $abcd,X; ADC AbsoluteX
ADC $abcd,Y; ADC AbsoluteY
ADC ($ab,X); ADC IndirectX
ADC ($ab),Y; ADC IndirectY
AND #$ab ; AND Immediate
AND $ab ; AND ZeroPage
AND $ab,X ; AND ZeroPageX