diff --git a/beneater/src/bin/make_rom.rs b/beneater/src/bin/make_rom.rs index 3125846..e4a97ed 100644 --- a/beneater/src/bin/make_rom.rs +++ b/beneater/src/bin/make_rom.rs @@ -21,24 +21,34 @@ fn main() { // Fill with 0xea -> NOP let mut vec: [u8; SIZE_32KB] = [ISA_OP_NOP; SIZE_32KB]; + // Load to A vec[0] = ISA_OP_LDA_I; // LDA #$ab vec[1] = 0b1010_1011; // 1010 1011 + // Jump to rotate cycle vec[2] = 0x02; // -- vec[3] = 0x03; // -- + // Jump to Main + vec[0x2210] = ISA_OP_JMP_ABS; + vec[0x2211] = 0x00; + vec[0x2212] = 0x40; + + // load to a vec[0x4000] = ISA_OP_LDA_I; vec[0x4001] = 0b0101_0100; + // jump to top of load to a vec[0x4002] = ISA_OP_JMP_ABS; vec[0x4003] = 0x00; vec[0x4004] = 0x40; vec[0x4005] = ISA_OP_NOP; + vec[0x7ffa] = 0x22; // NMI Vector + vec[0x7ffb] = 0x11; vec[0x7ffc] = 0x12; // Reset Vector vec[0x7ffd] = 0x34; vec[0x7ffe] = 0x43; // Interrupt Vector vec[0x7fff] = 0x21; - vec = le_swap(&vec); // write the rom to disk diff --git a/cli/src/bin/de6502.rs b/cli/src/bin/de6502.rs new file mode 100644 index 0000000..fa77aef --- /dev/null +++ b/cli/src/bin/de6502.rs @@ -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, + bytes: Vec +} + +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 +} + +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 = 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 + + // 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 ); + } +} diff --git a/cli/src/bin/disasm.rs b/cli/src/bin/disasm.rs deleted file mode 100644 index 0616903..0000000 --- a/cli/src/bin/disasm.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("Taxation is theft."); - println!("TODO:"); - println!(" Load specified binary and parse it out to ASM"); -} diff --git a/core/src/instruction.rs b/core/src/instruction.rs index 6ec93f2..7813a67 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction.rs @@ -19,7 +19,7 @@ impl Instruction { pub fn opinfo(bytes: &[u8]) -> Option { trace!("DECODING : {bytes:?}"); let opcode = bytes.get(0).copied()?; - Some(INSTRUCTION_TABLE[opcode as usize])? + Some(INSTRUCTION_TABLE[opcode as usize].clone())? } pub fn decode(bytes: &[u8]) -> Option { diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs index 1b10b18..bca036f 100644 --- a/core/src/instruction_table.rs +++ b/core/src/instruction_table.rs @@ -32,63 +32,79 @@ use crate::operation::Operation; use crate::operation::Operation::*; pub fn instruction_cycles(instruction: u8) -> u8 { - INSTRUCTION_TABLE[instruction as usize].unwrap().cycles + INSTRUCTION_TABLE[instruction as usize].clone().unwrap().cycles } pub fn instruction_length(instruction: u8) -> u8 { - INSTRUCTION_TABLE[instruction as usize].unwrap().length + INSTRUCTION_TABLE[instruction as usize].clone().unwrap().length } + pub const INSTRUCTION_TABLE: [Option; 256] = { let mut table: [Option; 256] = [const { None }; 256]; - table[ISA_OP_ADC_I as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "ADC #$", + format_postfix: "", }); table[ISA_OP_ADC_Z as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "ADC $", + format_postfix: "", }); table[ISA_OP_ADC_ZX as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "ADC $", + format_postfix: ",X", }); table[ISA_OP_ADC_ABS as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "ADC $", + format_postfix: "", }); table[ISA_OP_ADC_ABSX as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "ADC $", + format_postfix: ",X", }); table[ISA_OP_ADC_ABSY as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "ADC $", + format_postfix: ",Y", }); table[ISA_OP_ADC_INDX as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "ADC ($", + format_postfix: ",X)", }); table[ISA_OP_ADC_INDY as usize] = Some(OpInfo { operation: ADC, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "ADC ($", + format_postfix: "),Y", }); table[ISA_OP_AND_I as usize] = Some(OpInfo { @@ -96,78 +112,105 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_Z as usize] = Some(OpInfo { operation: AND, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_ZX as usize] = Some(OpInfo { operation: AND, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_ABS as usize] = Some(OpInfo { operation: AND, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_ABSX as usize] = Some(OpInfo { operation: AND, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_ABSY as usize] = Some(OpInfo { operation: AND, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_INDX as usize] = Some(OpInfo { operation: AND, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_AND_INDY as usize] = Some(OpInfo { operation: AND, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ASL_A as usize] = Some(OpInfo { operation: ASL, mode: AddressMode::Accumulator, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ASL_Z as usize] = Some(OpInfo { operation: ASL, mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ASL_ZX as usize] = Some(OpInfo { operation: ASL, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ASL_ABS as usize] = Some(OpInfo { operation: ASL, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ASL_ABSX as usize] = Some(OpInfo { operation: ASL, mode: AddressMode::AbsoluteX, length: 3, + cycles: 7, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_BCC as usize] = Some(OpInfo { @@ -175,18 +218,27 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BCS as usize] = Some(OpInfo { operation: BCS, mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BEQ as usize] = Some(OpInfo { operation: BEQ, mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BIT_ZP as usize] = Some(OpInfo { @@ -194,12 +246,18 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BIT_ABS as usize] = Some(OpInfo { operation: BIT, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BMI as usize] = Some(OpInfo { @@ -207,6 +265,9 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BNE as usize] = Some(OpInfo { @@ -214,54 +275,81 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BPL as usize] = Some(OpInfo { operation: Operation::BPL, mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BRK as usize] = Some(OpInfo { operation: BRK, mode: AddressMode::Implied, length: 1, cycles: 7, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BVC as usize] = Some(OpInfo { operation: BVC, mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_BVS as usize] = Some(OpInfo { operation: BVS, mode: AddressMode::Implied, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CLC as usize] = Some(OpInfo { operation: CLC, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CLD as usize] = Some(OpInfo { operation: CLD, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CLI as usize] = Some(OpInfo { operation: CLI, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CLV as usize] = Some(OpInfo { operation: CLV, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_I as usize] = Some(OpInfo { @@ -269,48 +357,72 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_ZP as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_ZPX as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_ABS as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_INDX as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CMP_INDY as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CPX_I as usize] = Some(OpInfo { @@ -318,36 +430,52 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CPX_ZP as usize] = Some(OpInfo { operation: CPX, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CPX_ABS as usize] = Some(OpInfo { operation: CPX, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CPY_I as usize] = Some(OpInfo { operation: CPY, mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_CPY_ZP as usize] = Some(OpInfo { operation: CPY, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_CPY_ABS as usize] = Some(OpInfo { operation: CPY, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_DEC_ZP as usize] = Some(OpInfo { @@ -355,84 +483,114 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_DEC_ZPX as usize] = Some(OpInfo { operation: DEC, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", + }); table[ISA_OP_DEC_ABS as usize] = Some(OpInfo { operation: DEC, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_DEC_ABSX as usize] = Some(OpInfo { operation: DEC, mode: AddressMode::AbsoluteX, length: 3, cycles: 7, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_DEX as usize] = Some(OpInfo { operation: DEX, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_DEY as usize] = Some(OpInfo { operation: DEY, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_I as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_ZP as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_ZPX as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_ABS as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_INDX as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_EOR_INDY as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INC_ZP as usize] = Some(OpInfo { @@ -440,54 +598,72 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INC_ZPX as usize] = Some(OpInfo { operation: INC, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INC_ABS as usize] = Some(OpInfo { operation: INC, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INC_ABSX as usize] = Some(OpInfo { operation: INC, mode: AddressMode::AbsoluteX, length: 3, cycles: 7, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INX as usize] = Some(OpInfo { operation: INX, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_INY as usize] = Some(OpInfo { operation: INY, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_JMP_ABS as usize] = Some(OpInfo { operation: JMP, mode: AddressMode::Absolute, length: 3, cycles: 3, + format_prefix: "JMP", + format_postfix: "", }); table[ISA_OP_JMP_IND as usize] = Some(OpInfo { operation: JMP, mode: AddressMode::Indirect, length: 3, cycles: 5, + format_prefix: "JMP ($", + format_postfix: ")", }); table[ISA_OP_JSR as usize] = Some(OpInfo { operation: JSR, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "JSR $", + format_postfix: "", }); table[ISA_OP_LDA_I as usize] = Some(OpInfo { @@ -495,48 +671,64 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "LDA #$", + format_postfix: "", }); table[ISA_OP_LDA_Z as usize] = Some(OpInfo { operation: LDA, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_ZX as usize] = Some(OpInfo { operation: LDA, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_ABS as usize] = Some(OpInfo { operation: Operation::LDA, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_ABSX as usize] = Some(OpInfo { operation: LDA, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_ABSY as usize] = Some(OpInfo { operation: LDA, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_INDX as usize] = Some(OpInfo { operation: Operation::LDA, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDA_INDY as usize] = Some(OpInfo { operation: LDA, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDX_I as usize] = Some(OpInfo { @@ -544,30 +736,40 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDX_ZP as usize] = Some(OpInfo { operation: Operation::LDX, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDX_ZPY as usize] = Some(OpInfo { operation: LDX, mode: AddressMode::ZeroPageY, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDX_ABS as usize] = Some(OpInfo { operation: Operation::LDX, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDX_ABSY as usize] = Some(OpInfo { operation: Operation::LDX, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDY_I as usize] = Some(OpInfo { @@ -575,30 +777,40 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDY_ZP as usize] = Some(OpInfo { operation: LDY, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDY_ZPX as usize] = Some(OpInfo { operation: Operation::LDY, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDY_ABS as usize] = Some(OpInfo { operation: LDY, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo { operation: LDY, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LSR_A as usize] = Some(OpInfo { @@ -606,30 +818,40 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Accumulator, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LSR_ZP as usize] = Some(OpInfo { operation: LSR, mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo { operation: LSR, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LSR_ABS as usize] = Some(OpInfo { operation: Operation::LSR, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_LSR_ABSX as usize] = Some(OpInfo { operation: Operation::LSR, mode: AddressMode::AbsoluteX, length: 3, cycles: 7, + format_prefix: "LSR $(", + format_postfix: ",X)", }); table[ISA_OP_NOP as usize] = Some(OpInfo { @@ -637,6 +859,8 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "NOP", + format_postfix: "", }); table[ISA_OP_ORA_I as usize] = Some(OpInfo { @@ -644,24 +868,32 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_ZP as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_ZPX as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_ABS as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_ABSX as usize] = Some(OpInfo { @@ -669,24 +901,32 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_INDX as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ORA_INDY as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_PHA as usize] = Some(OpInfo { @@ -694,24 +934,32 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 1, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_PHP as usize] = Some(OpInfo { operation: Operation::PHP, mode: AddressMode::Implied, length: 1, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_PLA as usize] = Some(OpInfo { operation: Operation::PLA, mode: AddressMode::Implied, length: 1, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_PLP as usize] = Some(OpInfo { operation: Operation::PLP, mode: AddressMode::Implied, length: 1, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROL_A as usize] = Some(OpInfo { @@ -719,30 +967,40 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Accumulator, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROL_ZP as usize] = Some(OpInfo { operation: Operation::ROL, mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROL_ZPX as usize] = Some(OpInfo { operation: Operation::ROL, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROL_ABS as usize] = Some(OpInfo { operation: Operation::ROL, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROL_ABSX as usize] = Some(OpInfo { operation: Operation::ROL, mode: AddressMode::AbsoluteX, length: 3, cycles: 7, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROR_A as usize] = Some(OpInfo { @@ -750,30 +1008,40 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Accumulator, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROR_ZP as usize] = Some(OpInfo { operation: Operation::ROR, mode: AddressMode::ZeroPage, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROR_ZPX as usize] = Some(OpInfo { operation: Operation::ROR, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROR_ABS as usize] = Some(OpInfo { operation: Operation::ROR, mode: AddressMode::Absolute, length: 3, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_ROR_ABSX as usize] = Some(OpInfo { operation: Operation::ROR, mode: AddressMode::AbsoluteX, length: 3, cycles: 7, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_RTI as usize] = Some(OpInfo { @@ -781,12 +1049,16 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_RTS as usize] = Some(OpInfo { operation: Operation::RTS, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_I as usize] = Some(OpInfo { @@ -794,48 +1066,64 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Immediate, length: 2, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_ZP as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_ZPX as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_ABS as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_ABSX as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_ABSY as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::AbsoluteY, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_INDX as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SBC_INDY as usize] = Some(OpInfo { operation: Operation::SBC, mode: AddressMode::IndirectY, length: 2, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SEC as usize] = Some(OpInfo { @@ -843,18 +1131,24 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SED as usize] = Some(OpInfo { operation: Operation::SED, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_SEI as usize] = Some(OpInfo { operation: Operation::SEI, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_ZP as usize] = Some(OpInfo { @@ -862,42 +1156,56 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_ZPX as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_ABS as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_ABSX as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::AbsoluteX, length: 3, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_ABSY as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::AbsoluteY, length: 3, cycles: 5, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_INDX as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::IndirectX, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STA_INDY as usize] = Some(OpInfo { operation: Operation::STA, mode: AddressMode::IndirectY, length: 2, cycles: 6, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STX_ZP as usize] = Some(OpInfo { @@ -905,18 +1213,24 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STX_ZPY as usize] = Some(OpInfo { operation: Operation::STX, mode: AddressMode::ZeroPageY, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STX_ABS as usize] = Some(OpInfo { operation: Operation::STX, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STY_ZP as usize] = Some(OpInfo { @@ -924,18 +1238,24 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPage, length: 2, cycles: 3, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STY_ZPX as usize] = Some(OpInfo { operation: Operation::STY, mode: AddressMode::ZeroPageX, length: 2, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_STY_ABS as usize] = Some(OpInfo { operation: Operation::STY, mode: AddressMode::Absolute, length: 3, cycles: 4, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_TAX as usize] = Some(OpInfo { @@ -943,36 +1263,48 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TBD", + format_postfix: "", }); table[ISA_OP_TAY as usize] = Some(OpInfo { operation: TAY, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TAY", + format_postfix: "", }); table[ISA_OP_TSX as usize] = Some(OpInfo { operation: TSX, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TSX", + format_postfix: "", }); table[ISA_OP_TXA as usize] = Some(OpInfo { operation: Operation::TXA, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TXA", + format_postfix: "", }); table[ISA_OP_TXS as usize] = Some(OpInfo { operation: Operation::TXS, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TXS", + format_postfix: "", }); table[ISA_OP_TYA as usize] = Some(OpInfo { operation: TYA, mode: AddressMode::Implied, length: 1, cycles: 2, + format_prefix: "TYA", + format_postfix: "", }); table diff --git a/core/src/mos6502cpu/cpu.rs b/core/src/mos6502cpu/cpu.rs index 5a40ad3..a2f84ad 100644 --- a/core/src/mos6502cpu/cpu.rs +++ b/core/src/mos6502cpu/cpu.rs @@ -67,7 +67,7 @@ impl Default for Mos6502Cpu { mode: AddressMode::Implied, operand: Operand::None, }, - oi: INSTRUCTION_TABLE[ISA_OP_NOP as usize].unwrap(), + oi: INSTRUCTION_TABLE[ISA_OP_NOP as usize].clone().unwrap(), has_reset: false, iv: 0xfffe, cycle_carry: 0x0000, diff --git a/core/src/op_info.rs b/core/src/op_info.rs index 0626d04..f74e466 100644 --- a/core/src/op_info.rs +++ b/core/src/op_info.rs @@ -1,7 +1,7 @@ use crate::address_mode::AddressMode; use crate::operation::Operation; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct OpInfo { /// What is the operation pub operation: Operation, @@ -11,4 +11,7 @@ pub struct OpInfo { pub length: u8, /// CPU Cycles to complete the instruction pub cycles: u8, -} + /// Format string for disassembly + pub format_prefix: &'static str, + pub format_postfix: &'static str +} \ No newline at end of file diff --git a/resources/beneater/README b/resources/beneater/README new file mode 100644 index 0000000..9acfff9 --- /dev/null +++ b/resources/beneater/README @@ -0,0 +1,3 @@ +To Build + +64tass -a -b -o diff --git a/resources/beneater/asm/lda_loop.asm b/resources/beneater/asm/lda_loop.asm new file mode 100644 index 0000000..d949095 --- /dev/null +++ b/resources/beneater/asm/lda_loop.asm @@ -0,0 +1,26 @@ + * = $A000 + .fill Reset - *, $ea +Reset: + SEI + CLD + LDX #$FF + TXS + ; Drop to the start of our main loop +MainLoop: + LDA #$AA + ROR + JMP MainLoop + +; What to do when we get a NMI +NMI: + RTI + +; What do we get when we get an interrupt +IRQ: + RTI + +; setup the requirements for the CPU + * = $FFF8 + .word NMI + .word Reset + .word IRQ diff --git a/resources/beneater/asm/nop_1.asm b/resources/beneater/asm/nop_1.asm deleted file mode 100644 index e69de29..0000000 diff --git a/resources/beneater/asm/skeleton.asm b/resources/beneater/asm/skeleton.asm new file mode 100644 index 0000000..d1d18b3 --- /dev/null +++ b/resources/beneater/asm/skeleton.asm @@ -0,0 +1,22 @@ + * = $0000 + .fill Reset - *, $ea + +Reset: + SEI + CLD + LDX #$FF + TXS + +MainLoop: + NOP + JMP MainLoop + +NMI: + RTI +IRQ: + RTI + + * = $FFF8 + .word NMI + .word RESET + .word IRQ