improved de6502 - needs to write to disk instead of cli
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::thread::current;
|
||||
use core::constants::constants_system::*;
|
||||
use core::constants::constants_isa_op::*;
|
||||
use clap::{Parser, Subcommand};
|
||||
use core::instruction_table::INSTRUCTION_TABLE;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct CliOptions {
|
||||
/// File to Decompile
|
||||
input: PathBuf,
|
||||
/// File to write
|
||||
output: PathBuf
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DecompiledLine {
|
||||
offset: u16,
|
||||
text: String,
|
||||
label: Option<String>,
|
||||
bytes: Vec<u8>
|
||||
}
|
||||
|
||||
impl DecompiledLine {
|
||||
/// is_jump
|
||||
///
|
||||
/// Check if the current line is a type of a jump
|
||||
pub fn is_jump(&self) -> bool {
|
||||
self.bytes[0] == ISA_OP_JMP_ABS || self.bytes[0] == ISA_OP_JMP_IND
|
||||
}
|
||||
|
||||
/// is_branch
|
||||
///
|
||||
/// Check if the current line is a branch
|
||||
pub fn is_branch(&self) -> bool {
|
||||
self.bytes[0] == ISA_OP_BCC || self.bytes[0] == ISA_OP_BCS ||
|
||||
self.bytes[0] == ISA_OP_BEQ || self.bytes[0] == ISA_OP_BMI ||
|
||||
self.bytes[0] == ISA_OP_BNE || self.bytes[0] == ISA_OP_BPL ||
|
||||
self.bytes[0] == ISA_OP_BVS || self.bytes[0] == ISA_OP_BVC
|
||||
}
|
||||
}
|
||||
|
||||
/// WorkingProgram
|
||||
///
|
||||
/// Where we keep the program being decompiled
|
||||
struct WorkingProgram {
|
||||
data: [u8; SIZE_64KB],
|
||||
lines: Vec<DecompiledLine>
|
||||
}
|
||||
|
||||
impl WorkingProgram {
|
||||
|
||||
}
|
||||
|
||||
fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> {
|
||||
println!("Preparing to decompile {}b", data.len());
|
||||
let mut current_data_position: u16 = 0;
|
||||
let mut lines: HashMap<u16, DecompiledLine> = HashMap::new();
|
||||
|
||||
while current_data_position < data.len() as u16 {
|
||||
// read the next byte.
|
||||
let next_byte = data[current_data_position as usize];
|
||||
let mut bytes = vec![next_byte];
|
||||
let target_op = INSTRUCTION_TABLE[next_byte as usize].clone();
|
||||
|
||||
if let Some(top) = target_op {
|
||||
println!("Instruction {:?}/{:?} needs {:?} bytes.", top.operation, top.mode, top.length);
|
||||
|
||||
let num_bytes_to_load = top.length - 1;
|
||||
println!("Need {num_bytes_to_load} more bytes.");
|
||||
let mut formatted_asm = format!("{}{}", top.format_prefix, top.format_postfix);
|
||||
if num_bytes_to_load == 1 {
|
||||
bytes.push(data[current_data_position as usize + 1]);
|
||||
formatted_asm = format!("{}{:02x}", formatted_asm, bytes[1]);
|
||||
};
|
||||
|
||||
if num_bytes_to_load == 2 {
|
||||
bytes.push(data[current_data_position as usize + 1]);
|
||||
bytes.push(data[current_data_position as usize + 2]);
|
||||
// 16 bit parameter.
|
||||
let param = ((bytes[2] as u16) << 8) | bytes[1] as u16;
|
||||
formatted_asm = format!("{} ${:04x}", formatted_asm, param);
|
||||
};
|
||||
|
||||
// figure out how long the instruction is and read that much more data
|
||||
lines.insert(current_data_position, DecompiledLine {
|
||||
offset: current_data_position,
|
||||
text: formatted_asm,
|
||||
label: None,
|
||||
bytes,
|
||||
});
|
||||
|
||||
current_data_position = current_data_position + top.length as u16;
|
||||
} else {
|
||||
// invalid instruction
|
||||
println!("Byte sequence 0x{} invalid.", next_byte);
|
||||
current_data_position += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("Found {} instructions in pass 1. Adding labels for jumps.", lines.len());
|
||||
|
||||
//let targets = vec![];
|
||||
|
||||
for (index, line) in &lines {
|
||||
|
||||
if line.bytes[0] == ISA_OP_JMP_ABS {
|
||||
// println!("ABS JUMP FOUND");
|
||||
}
|
||||
}
|
||||
|
||||
let mut items: Vec<_> = lines.into_iter().collect();
|
||||
items.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
|
||||
|
||||
// loop through the lines for JSR and label the 'target' as SUB<index>
|
||||
|
||||
// check the vectors to label those entrypoints.
|
||||
// -> main
|
||||
// -> NMI
|
||||
// -> IRQ
|
||||
|
||||
items
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opts = CliOptions::parse();
|
||||
println!("Taxation is theft.");
|
||||
|
||||
// Load program to an array...
|
||||
let data = vec![
|
||||
0xa9, 0xab, 0x4c, 0x00, 0x40, 0xa9, 0x54, 0x4c, 0x00, 0x40,
|
||||
ISA_OP_TYA, ISA_OP_TXA, ISA_OP_TSX
|
||||
];
|
||||
|
||||
let loaded_data = fs::read(opts.input).unwrap();
|
||||
println!("Loaded {}b", loaded_data.len());
|
||||
// ...load the array to the WorkingProgram structure...
|
||||
let result = decompile(&loaded_data);
|
||||
|
||||
// ...reap the decompiled code.
|
||||
for (_, line) in &result {
|
||||
println!("{:width$}; {:?}", line.text,line.bytes, width=30 );
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fn main() {
|
||||
println!("Taxation is theft.");
|
||||
println!("TODO:");
|
||||
println!(" Load specified binary and parse it out to ASM");
|
||||
}
|
||||
Reference in New Issue
Block a user