Lots of stuff.

This commit is contained in:
2025-06-23 15:35:36 -04:00
parent 87ae4e7890
commit 2939e1cac5
120 changed files with 9335 additions and 2178 deletions
+223
View File
@@ -0,0 +1,223 @@
/*
64tass -a -o instructions.bin -b instructions.asm &&
cargo run --bin de6502 -- -v instructions.bin instructions_produced.asm &&
64tass -a -b instructions_produced.asm -o instructions_produced.bin
*/
use std::collections::HashMap;
use std::fs;
use std::fs::File;
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;
use std::io::Write;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct CliOptions {
/// File to Decompile
input: PathBuf,
/// File to write
output: PathBuf,
/// Verbose output
#[arg(short, action = clap::ArgAction::Count)]
verbose: u8
}
#[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 parse_to_decompiled_lines(data: &[u8]) -> HashMap<u16, DecompiledLine> {
println!("PARSE GOT {}b", data.len());
let mut current_data_position = 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];
println!("Bytes = {bytes:?}");
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 = String::from(top.format_prefix);
let mut param = None;
if num_bytes_to_load == 1 {
bytes.push(data[current_data_position as usize + 1]);
formatted_asm = format!("{}{:02x}{}", formatted_asm, bytes[1], top.format_postfix);
};
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.
param = Some(((bytes[2] as u16) << 8) | bytes[1] as u16);
formatted_asm = format!("{}{:04x}{}", formatted_asm, param.unwrap(), top.format_postfix);
};
// figure out how long the instruction is and read that much more data
lines.insert(current_data_position, DecompiledLine {
offset: current_data_position,
text: String::from(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;
}
}
lines
}
fn decompile(data: &Vec<u8>) -> Vec<(u16, DecompiledLine)> {
println!("Preparing to decompile {}b", data.len());
let mut current_data_position: u16 = 0;
let mut lines: HashMap<u16, DecompiledLine> = parse_to_decompiled_lines(data);
println!("Found {} instructions in pass 1. Adding labels for jumps.", lines.len());
//let targets = vec![];
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>
// let mut jump_targets = vec![];
for (line_index, working_line) in &mut items {
if working_line.is_jump() {
println!("There are {}b in bytes", working_line.bytes.len());
let target = read_word(&working_line.bytes[1..=2]);
println!("Found a jump at index {line_index} / 0x{line_index} with target of 0x{:04x}", target);;
// Derp -> this doesnt work.
// items[target as usize].1.label = Some("Label1".parse().unwrap());
}
}
// // check the vectors to label those entrypoints.
// let (mut main, mut nmi, mut irq) = (0, 0, 0);
// match data.len() {
// SIZE_32KB | SIZE_64KB => {
// main = read_word(&data[OFFSET_RESET_VECTORS..=OFFSET_RESET_VECTORS + 1]);
// nmi = read_word(&data[OFFSET_NMI_VECTORS..=OFFSET_NMI_VECTORS + 1]);
// irq = read_word(&data[OFFSET_INT_VECTORS..=OFFSET_INT_VECTORS]);
// }
// _ => {
// // dont know where to look for our offsets. :(
// }
// }
// -> main
// -> NMI
// -> IRQ
items
}
/// read_word
///
/// Read a word from the provided data with first byte being
/// LSB
fn read_word(from: &[u8]) -> u16 {
(from[1] as u16) << 8 | from[0] as u16
}
/// read_word_swap
///
/// Read a word from the provided data with first byte being
/// MSB
fn read_word_swap(from: &[u8]) -> u16 {
(from[0] as u16) << 8 | from[1] as u16
}
/// format_bytes
///
/// formats data for stuff
fn format_bytes(from: &Vec<u8>) -> String {
let mut to_return = String::from("[");
for index in 0..from.len() {
to_return = format!("{} 0x{:02x}", to_return, from[index]);
}
to_return = format!("{} ]", to_return);
to_return
}
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);
let mut output_file = File::create(opts.output).unwrap();
// ...reap the decompiled code.
for (_, line) in &result {
let formatted_bytes = format_bytes(&line.bytes);
let output_line =format!("{:width$}; {}", line.text, formatted_bytes, width=30 );
// do we need a label
if let Some(label) = &line.label {
println!("There is a label - {label}");
}
if opts.verbose > 0 {
println!("{}", output_line);
}
writeln!(output_file, "{}", output_line).expect("cant write output file. you picked the red snapper.");
}
println!("OPTS = {}", opts.verbose);
}
+16 -5
View File
@@ -1,12 +1,23 @@
use core::instruction::Instruction;
use core::address_mode::AddressMode;
use core::isa::decoder::Decoder;
use core::instruction::Instruction;
use core::operand::Operand;
use core::operation::Operation;
fn main() {
println!("Taxation is Theft");
Decoder::decode(vec![0b11100011]);
let instructions = vec![(
Instruction {
op: Operation::NOP,
mode: AddressMode::Implied,
operand: Operand::None,
},
&[0xea],
)];
let instruction = Instruction::ADC(AddressMode::Immediate(0x45));
println!("Instruction = {:?}", instruction.to_string());
for (op, bytes) in instructions {
assert_eq!(Instruction::decode(bytes), Some(op));
}
// let instruction = Instruction::decode(&[0xea]);
// println!("NOP Decoded -> {:?}", instruction);
}
-5
View File
@@ -1,5 +0,0 @@
fn main() {
println!("Taxation is theft.");
println!("TODO:");
println!(" Load specified binary and parse it out to ASM");
}
+26
View File
@@ -0,0 +1,26 @@
use core::computers::kim1::Kim1;
fn main() {
println!("Taxation is theft.");
let mut kim = Kim1::new();
let mut num_ticks = 0;
kim.running = true;
while kim.running {
kim.tick();
num_ticks += 1;
if num_ticks == 11 {
println!("Got our 11 ticks. time to hotwire this pc.");
kim.running = true;
kim.dump();
}
if num_ticks == 15 {
kim.running = false;
kim.dump();
}
}
}
+21
View File
@@ -0,0 +1,21 @@
use std::fs;
fn main() {
println!("Taxation is Theft");
// let opts = CliOptions::parse();
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
let bytes = match fs::read(path) {
Ok(bytes) => {
println!("Read {} bytes.", bytes.len());
bytes
},
Err(e) => {
eprintln!("FAIL to read rom.");
panic!("No rom no run.");
vec![]
}
};
}
+47
View File
@@ -0,0 +1,47 @@
use std::fs;
use clap::Parser;
use core::computers::rom_only::backplane::RomOnlyComputer;
use core::periph::backplane::Backplane;
#[derive(Parser)]
struct CliOptions {
offset: u16,
bytes: u16,
filename: String
}
fn main() {
println!("Taxation is theft");
// let opts = CliOptions::parse();
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
let bytes = match fs::read(path) {
Ok(bytes) => {
println!("Read {} bytes.", bytes.len());
bytes
},
Err(e) => {
eprintln!("FAIL to read rom.");
panic!("No rom no run.");
vec![]
}
};
let mut rom_only = RomOnlyComputer::program((&bytes[..]).to_vec());
rom_only.set_read_mode(true);
rom_only.set_address_bus(0x05);
rom_only.tick();
println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ;
println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus());
println!("----");
rom_only.set_read_mode(true);
rom_only.set_address_bus(0x07);
rom_only.tick();
println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ;
println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus());
println!("----");
}
+5
View File
@@ -0,0 +1,5 @@
use core::mos6502cpu::cpu::Mos6502Cpu;
fn main() {
let x = Mos6502Cpu::default();
}