From 802aaf51eb599f3696ac16329c48eacc6397a954 Mon Sep 17 00:00:00 2001 From: Kline Gareth Date: Sat, 27 Jan 2024 18:51:38 -0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 7 + Cargo.toml | 8 + src/main.rs | 1848 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1864 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7d6e16a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "georgeemu" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..529e5b1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "georgeemu" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fd43716 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,1848 @@ +#[allow(warnings)] +use core::panic; +use std::collections::HashMap; + +type Byte = u8; +type Word = u16; + +#[derive(Debug)] +struct MemArea { + start: Word, + end: Word, + pages: usize, + page: usize, + data: Vec, + label: String, +} + +impl MemArea { + fn new(start: Word, end: Word, pages: usize, label: String) -> Self { + Self { + start, + end, + pages, + page: 0, + data: vec![0x00; end as usize - start as usize], + label, + } + } + fn contains(&self, address: Word) -> bool { + self.start <= address && self.end >= address + } + fn swap_page(&mut self, page: usize) -> Result<(), MappingError> { + match page > self.pages { + true => Err(MappingError::InvalidPage), + false => Ok(self.page = page), + } + } + fn translate_address(&self, address: Word) -> Word { + address - self.start + } // This needs to translate memory address from CPU land to local land, so + // for rom an address like 0xFFFF needs to be translated to Page X, 0xFFF +} + +#[derive(Debug)] +struct Mem { + areas: Vec, +} + +#[derive(Debug)] +enum MemoryError { + Unmapped, + NoDataAtAddress, +} + +#[derive(Debug)] +enum MappingError { + RegionOccupied, + InvalidPage, +} + +impl Mem { + fn new(area: MemArea) -> Self { + Self { areas: vec![area] } + } + fn add_area(&mut self, area: MemArea) -> Result<(), MappingError> { + for existing_area in &self.areas { + if existing_area.contains(area.end) || existing_area.contains(area.start) { + return Err(MappingError::RegionOccupied); + } + } + Ok(self.areas.push(area)) + } + fn read(&self, address: Word) -> Result { + for area in &self.areas { + if area.contains(address) { + let translated_address = area.translate_address(address); + match area.data.get(translated_address as usize) { + Some(data) => return Ok(data.clone()), + None => return Err(MemoryError::NoDataAtAddress), + } + } + } + Err(MemoryError::Unmapped) + } + + fn write(&mut self, address: Word, data: Byte) -> Result<(), MemoryError> { + let mut contains = false; + for area in self.areas.iter_mut() { + if area.contains(address) { + contains = true; + println!("Writing to area {label}", label = area.label); + let translated_address = area.translate_address(address); + area.data[translated_address as usize] = data; + }; + } + println!("{:?}", contains); + match contains { + true => return Ok(()), + false => Err(MemoryError::Unmapped), + } + } +} + +struct Cpu { + a: Byte, // Accumulator Register + x: Byte, // X Register + y: Byte, // Y Register + pc: Word, // Program Counter + s: Byte, // Stack Pointer + p: Byte, // Status Register + irq: bool, + nmi: bool, + memory: Mem, +} + +#[derive(Debug)] +enum ExecutionError { + InvalidInstruction, + InterruptsDisabled, + NoInterrupt, + StackOverflow, + MemoryError(MemoryError), +} + +impl Cpu { + fn new(memory: Mem) -> Self { + Cpu { + a: 0x00, + x: 0x00, + y: 0x00, + pc: 0x0000, + s: 0xFF, + p: 0b0010_0100, + irq: false, + nmi: false, + memory, + } + } + fn reset(&mut self) -> Result<(), ExecutionError> { + match self.read_word(0xFFFC) { + Ok(word) => match self.read(word) { + Ok(_byte) => Ok(self.pc = word), + Err(error) => Err(ExecutionError::MemoryError(error)), + }, + Err(error) => Err(ExecutionError::MemoryError(error)), + } + } + fn read(&self, address: Word) -> Result { + self.memory.read(address) + } + fn read_word(&self, address: Word) -> Result { + let low_byte = self.read(address); + let high_byte = self.read(address + 0x1); + match high_byte { + Err(error) => Err(error), + Ok(high) => match low_byte { + Err(error) => Err(error), + Ok(low) => Ok((high as u16) << 8 | (low as u16)), + }, + } + } + + fn stack_addr(&self) -> Word { + // Dunno if this is necessary, i just don't like adding the 0x0100 every time + 0x0100 + self.s as u16 + } + + fn push_stack(&mut self, data: Byte) -> Result<(), ExecutionError> { + self.s -= 0x1; + match self.write(self.stack_addr(), data) { + Ok(()) => Ok(()), + Err(error) => Err(ExecutionError::MemoryError(error)), + } + } + + fn pop_stack(&self) -> Result { + match self.read(self.stack_addr()) { + Ok(byte) => Ok(byte), + Err(error) => Err(ExecutionError::MemoryError(error)), + } + } + + fn write(&mut self, address: Word, data: Byte) -> Result<(), MemoryError> { + self.memory.write(address, data) + } + + fn execute(&self, opcode: Byte) -> Result<(), ExecutionError> { + let instruction: Instruction = get_instruction(opcode); + match instruction { + Instruction::Valid(valid_instruction) => Ok(valid_instruction.opcode.call()), + Instruction::Invalid => Err(ExecutionError::InvalidInstruction), + } + } + + fn handle_interrupt(&self) -> Result<(), ExecutionError> { + match self.p & 0b0000_0100 { + // Check that interrupts aren't disabled + 0b0000_0100 => Err(ExecutionError::InterruptsDisabled), + 0b0000_0000 => { + if self.irq { + let irq_vector = 0xFFFC; + match self.read_word(irq_vector) { + Err(error) => Err(ExecutionError::MemoryError(error)), + Ok(address) => { + let isr_address = address; + match self.read(isr_address) { + Ok(opcode) => self.execute(opcode), + Err(error) => Err(ExecutionError::MemoryError(error)), + } + } + } + } else { + Ok(()) + } + } + _ => Ok(()), + } + } + fn tick(&mut self) -> Result<(), ExecutionError> { + // `cycle` is a reserved word :/ + self.pc += 1; + match self.read(self.pc) { + Ok(instruction) => self.execute(instruction), + Err(error) => Err(ExecutionError::MemoryError(error)), + } + } +} + +#[derive(Clone)] +enum Instruction { + Valid(ValidInstruction), + Invalid, +} + +#[derive(Clone)] +struct ValidInstruction { + opcode: Opcode, +} + +#[derive(Clone)] +enum AddressingMode { + AbsoluteA, // a + AbsoluteIndexedIndirect, // (a,x) (4) + AbsoluteIndexedWithX, // a, x + AbsoluteIndexedWithY, // a, y + AbsoluteIndirect, // (a) + Accumulator, // A + Immediate, // # + Implied, // i + ProgramCounterRelative, // r + Stack, // s + ZeroPage, // zp + ZeroPageIndexedIndirect, // (zp, x) + ZeroPageIndexedWithX, // zp, x + ZeroPageIndexedWithY, // zp, y + ZeroPageIndirect, // (zp) (4) + ZeroPageIndirectIndexedWithY, // (zp), y +} + +// if you want to optimize this later https://llx.com/Neil/a2/opcodes.html +fn get_instruction(opcode: u8) -> Instruction { + let opcodes: HashMap = HashMap::from([ + ( + 0x00, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BRK(AddressingMode::Stack), + }), + ), + ( + 0x01, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0x02, Instruction::Invalid), + (0x03, Instruction::Invalid), + ( + 0x04, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TSB(AddressingMode::ZeroPage), + }), + ), + ( + 0x05, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::ZeroPage), + }), + ), + ( + 0x06, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ASL(AddressingMode::ZeroPage), + }), + ), + ( + 0x07, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB0(AddressingMode::ZeroPage), + }), + ), + ( + 0x08, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PHP(AddressingMode::Stack), + }), + ), + ( + 0x09, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::Immediate), + }), + ), + ( + 0x0a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ASL(AddressingMode::Accumulator), + }), + ), + (0x0b, Instruction::Invalid), + ( + 0x0c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TSB(AddressingMode::AbsoluteA), + }), + ), + ( + 0x0d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::AbsoluteA), + }), + ), + ( + 0x0e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ASL(AddressingMode::AbsoluteA), + }), + ), + ( + 0x0f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR0(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x10, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BPL(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x11, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x12, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::ZeroPageIndirect), + }), + ), + (0x13, Instruction::Invalid), + ( + 0x14, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TRB(AddressingMode::ZeroPage), + }), + ), + ( + 0x15, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x16, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ASL(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x17, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB1(AddressingMode::ZeroPage), + }), + ), + ( + 0x18, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CLC(AddressingMode::Implied), + }), + ), + ( + 0x19, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x1a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INC(AddressingMode::Accumulator), + }), + ), + (0x1b, Instruction::Invalid), + ( + 0x1c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TRB(AddressingMode::AbsoluteA), + }), + ), + ( + 0x1d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x1e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ASL(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x1f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR1(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x20, + Instruction::Valid(ValidInstruction { + opcode: Opcode::JSR(AddressingMode::AbsoluteA), + }), + ), + ( + 0x21, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0x22, Instruction::Invalid), + (0x23, Instruction::Invalid), + ( + 0x24, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BIT(AddressingMode::ZeroPage), + }), + ), + ( + 0x25, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::ZeroPage), + }), + ), + ( + 0x26, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROL(AddressingMode::ZeroPage), + }), + ), + ( + 0x27, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB2(AddressingMode::ZeroPage), + }), + ), + ( + 0x28, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PLP(AddressingMode::Stack), + }), + ), + ( + 0x29, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::Immediate), + }), + ), + ( + 0x2a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROL(AddressingMode::Accumulator), + }), + ), + (0x2b, Instruction::Invalid), + ( + 0x2c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BIT(AddressingMode::AbsoluteA), + }), + ), + ( + 0x2d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::AbsoluteA), + }), + ), + ( + 0x2e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROL(AddressingMode::AbsoluteA), + }), + ), + ( + 0x2f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR2(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x30, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BMI(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x31, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0x32, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::ZeroPageIndirect), + }), + ), + (0x33, Instruction::Invalid), + ( + 0x34, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BIT(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x35, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x36, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROL(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x37, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB3(AddressingMode::ZeroPage), + }), + ), + ( + 0x38, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SEC(AddressingMode::Implied), + }), + ), + ( + 0x39, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x3a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEC(AddressingMode::Accumulator), + }), + ), + (0x3b, Instruction::Invalid), + ( + 0x3c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BIT(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x3d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::AND(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x3e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROL(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x3f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR3(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x40, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RTI(AddressingMode::Stack), + }), + ), + ( + 0x41, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0x42, Instruction::Invalid), + (0x43, Instruction::Invalid), + (0x44, Instruction::Invalid), + ( + 0x45, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::ZeroPage), + }), + ), + ( + 0x46, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LSR(AddressingMode::ZeroPage), + }), + ), + ( + 0x47, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB4(AddressingMode::ZeroPage), + }), + ), + ( + 0x48, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PHA(AddressingMode::Stack), + }), + ), + ( + 0x49, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::Immediate), + }), + ), + ( + 0x4a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LSR(AddressingMode::Accumulator), + }), + ), + (0x4b, Instruction::Invalid), + ( + 0x4c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::JMP(AddressingMode::AbsoluteA), + }), + ), + ( + 0x4d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::AbsoluteA), + }), + ), + ( + 0x4e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LSR(AddressingMode::AbsoluteA), + }), + ), + ( + 0x4f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR4(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x50, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BVC(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x51, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0x52, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::ZeroPageIndirect), + }), + ), + (0x53, Instruction::Invalid), + (0x54, Instruction::Invalid), + ( + 0x55, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x56, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LSR(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x57, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB5(AddressingMode::ZeroPage), + }), + ), + ( + 0x58, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CLI(AddressingMode::Implied), + }), + ), + ( + 0x59, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x5a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PHY(AddressingMode::Stack), + }), + ), + (0x5b, Instruction::Invalid), + (0x5c, Instruction::Invalid), + ( + 0x5d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::EOR(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x5e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LSR(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x5f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR5(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x60, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RTS(AddressingMode::Stack), + }), + ), + ( + 0x61, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0x62, Instruction::Invalid), + (0x63, Instruction::Invalid), + ( + 0x64, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STZ(AddressingMode::ZeroPage), + }), + ), + ( + 0x65, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::ZeroPage), + }), + ), + ( + 0x66, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROR(AddressingMode::ZeroPage), + }), + ), + ( + 0x67, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB6(AddressingMode::ZeroPage), + }), + ), + ( + 0x68, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PLA(AddressingMode::Stack), + }), + ), + ( + 0x69, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::Immediate), + }), + ), + ( + 0x6a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROR(AddressingMode::Accumulator), + }), + ), + (0x6b, Instruction::Invalid), + ( + 0x6c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::JMP(AddressingMode::AbsoluteIndirect), + }), + ), + ( + 0x6d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::AbsoluteA), + }), + ), + ( + 0x6e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROR(AddressingMode::AbsoluteA), + }), + ), + ( + 0x6f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR6(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x70, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BVS(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x71, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0x72, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::ZeroPageIndirect), + }), + ), + (0x73, Instruction::Invalid), + ( + 0x74, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STZ(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x75, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x76, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROR(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x77, + Instruction::Valid(ValidInstruction { + opcode: Opcode::RMB7(AddressingMode::ZeroPage), + }), + ), + ( + 0x78, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SEI(AddressingMode::Implied), + }), + ), + ( + 0x79, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x7a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PLY(AddressingMode::Stack), + }), + ), + (0x7b, Instruction::Invalid), + ( + 0x7c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::JMP(AddressingMode::AbsoluteIndexedIndirect), + }), + ), + ( + 0x7d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ADC(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x7e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::ROR(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x7f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBR7(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x80, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BRA(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x81, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0x82, Instruction::Invalid), + (0x83, Instruction::Invalid), + ( + 0x84, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STY(AddressingMode::ZeroPage), + }), + ), + ( + 0x85, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::ZeroPage), + }), + ), + ( + 0x86, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STX(AddressingMode::ZeroPage), + }), + ), + ( + 0x87, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB0(AddressingMode::ZeroPage), + }), + ), + ( + 0x88, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEY(AddressingMode::Implied), + }), + ), + ( + 0x89, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BIT(AddressingMode::Immediate), + }), + ), + ( + 0x8a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TXA(AddressingMode::Implied), + }), + ), + (0x8b, Instruction::Invalid), + ( + 0x8c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STY(AddressingMode::AbsoluteA), + }), + ), + ( + 0x8d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::AbsoluteA), + }), + ), + ( + 0x8e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STX(AddressingMode::AbsoluteA), + }), + ), + ( + 0x8f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS0(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x90, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BCC(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0x91, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0x92, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::ZeroPageIndirect), + }), + ), + (0x93, Instruction::Invalid), + ( + 0x94, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STY(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x95, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0x96, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STX(AddressingMode::ZeroPageIndexedWithY), + }), + ), + ( + 0x97, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB1(AddressingMode::ZeroPage), + }), + ), + ( + 0x98, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TYA(AddressingMode::Implied), + }), + ), + ( + 0x99, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0x9a, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TXS(AddressingMode::Implied), + }), + ), + (0x9b, Instruction::Invalid), + ( + 0x9c, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STZ(AddressingMode::AbsoluteA), + }), + ), + ( + 0x9d, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STA(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x9e, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STZ(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0x9f, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS1(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xa0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDY(AddressingMode::Immediate), + }), + ), + ( + 0xa1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + ( + 0xa2, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDX(AddressingMode::Immediate), + }), + ), + (0xa3, Instruction::Invalid), + ( + 0xa4, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDY(AddressingMode::ZeroPage), + }), + ), + ( + 0xa5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::ZeroPage), + }), + ), + ( + 0xa6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDX(AddressingMode::ZeroPage), + }), + ), + ( + 0xa7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB2(AddressingMode::ZeroPage), + }), + ), + ( + 0xa8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TAY(AddressingMode::Implied), + }), + ), + ( + 0xa9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::Immediate), + }), + ), + ( + 0xaa, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TAX(AddressingMode::Implied), + }), + ), + (0xab, Instruction::Invalid), + ( + 0xac, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDY(AddressingMode::AbsoluteA), + }), + ), + ( + 0xad, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::AbsoluteA), + }), + ), + ( + 0xae, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDX(AddressingMode::AbsoluteA), + }), + ), + ( + 0xaf, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS2(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xb0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BCS(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xb1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0xb2, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::ZeroPageIndirect), + }), + ), + (0xb3, Instruction::Invalid), + ( + 0xb4, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDY(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xb5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xb6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDX(AddressingMode::ZeroPageIndexedWithY), + }), + ), + ( + 0xb7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB3(AddressingMode::ZeroPage), + }), + ), + ( + 0xb8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CLV(AddressingMode::Implied), + }), + ), + ( + 0xb9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0xba, + Instruction::Valid(ValidInstruction { + opcode: Opcode::TSX(AddressingMode::Implied), + }), + ), + (0xbb, Instruction::Invalid), + ( + 0xbc, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDY(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xbd, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDA(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xbe, + Instruction::Valid(ValidInstruction { + opcode: Opcode::LDX(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0xbf, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS3(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xc0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPY(AddressingMode::Immediate), + }), + ), + ( + 0xc1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0xc2, Instruction::Invalid), + (0xc3, Instruction::Invalid), + ( + 0xc4, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPY(AddressingMode::ZeroPage), + }), + ), + ( + 0xc5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::ZeroPage), + }), + ), + ( + 0xc6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEC(AddressingMode::ZeroPage), + }), + ), + ( + 0xc7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB4(AddressingMode::ZeroPage), + }), + ), + ( + 0xc8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INY(AddressingMode::Implied), + }), + ), + ( + 0xc9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::Immediate), + }), + ), + ( + 0xca, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEX(AddressingMode::Implied), + }), + ), + ( + 0xcb, + Instruction::Valid(ValidInstruction { + opcode: Opcode::WAI(AddressingMode::Implied), + }), + ), + ( + 0xcc, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPY(AddressingMode::AbsoluteA), + }), + ), + ( + 0xcd, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::AbsoluteA), + }), + ), + ( + 0xce, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEC(AddressingMode::AbsoluteA), + }), + ), + ( + 0xcf, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS4(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xd0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BNE(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xd1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0xd2, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::ZeroPageIndirect), + }), + ), + (0xd3, Instruction::Invalid), + (0xd4, Instruction::Invalid), + ( + 0xd5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xd6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEC(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xd7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB5(AddressingMode::ZeroPage), + }), + ), + ( + 0xd8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CLD(AddressingMode::Implied), + }), + ), + ( + 0xd9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0xda, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PHX(AddressingMode::Stack), + }), + ), + ( + 0xdb, + Instruction::Valid(ValidInstruction { + opcode: Opcode::STP(AddressingMode::Implied), + }), + ), + (0xdc, Instruction::Invalid), + ( + 0xdd, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CMP(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xde, + Instruction::Valid(ValidInstruction { + opcode: Opcode::DEC(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xdf, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS5(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xe0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPX(AddressingMode::Immediate), + }), + ), + ( + 0xe1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::ZeroPageIndexedIndirect), + }), + ), + (0xe2, Instruction::Invalid), + (0xe3, Instruction::Invalid), + ( + 0xe4, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPX(AddressingMode::ZeroPage), + }), + ), + ( + 0xe5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::ZeroPage), + }), + ), + ( + 0xe6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INC(AddressingMode::ZeroPage), + }), + ), + ( + 0xe7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB6(AddressingMode::ZeroPage), + }), + ), + ( + 0xe8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INX(AddressingMode::Implied), + }), + ), + ( + 0xe9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::Immediate), + }), + ), + ( + 0xea, + Instruction::Valid(ValidInstruction { + opcode: Opcode::NOP(AddressingMode::Implied), + }), + ), + (0xeb, Instruction::Invalid), + ( + 0xec, + Instruction::Valid(ValidInstruction { + opcode: Opcode::CPX(AddressingMode::AbsoluteA), + }), + ), + ( + 0xed, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::AbsoluteA), + }), + ), + ( + 0xee, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INC(AddressingMode::AbsoluteA), + }), + ), + ( + 0xef, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS6(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xf0, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BEQ(AddressingMode::ProgramCounterRelative), + }), + ), + ( + 0xf1, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::ZeroPageIndirectIndexedWithY), + }), + ), + ( + 0xf2, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::ZeroPageIndirect), + }), + ), + (0xf3, Instruction::Invalid), + (0xf4, Instruction::Invalid), + ( + 0xf5, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xf6, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INC(AddressingMode::ZeroPageIndexedWithX), + }), + ), + ( + 0xf7, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SMB7(AddressingMode::ZeroPage), + }), + ), + ( + 0xf8, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SED(AddressingMode::Implied), + }), + ), + ( + 0xf9, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::AbsoluteIndexedWithY), + }), + ), + ( + 0xfa, + Instruction::Valid(ValidInstruction { + opcode: Opcode::PLX(AddressingMode::Stack), + }), + ), + (0xfb, Instruction::Invalid), + (0xfc, Instruction::Invalid), + ( + 0xfd, + Instruction::Valid(ValidInstruction { + opcode: Opcode::SBC(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xfe, + Instruction::Valid(ValidInstruction { + opcode: Opcode::INC(AddressingMode::AbsoluteIndexedWithX), + }), + ), + ( + 0xff, + Instruction::Valid(ValidInstruction { + opcode: Opcode::BBS7(AddressingMode::ProgramCounterRelative), + }), + ), + ]); + opcodes.get(&opcode).unwrap().clone() +} + +#[derive(Clone)] +enum Opcode { + ADC(AddressingMode), + AND(AddressingMode), + ASL(AddressingMode), + BBR0(AddressingMode), + BBR1(AddressingMode), + BBR2(AddressingMode), + BBR3(AddressingMode), + BBR4(AddressingMode), + BBR5(AddressingMode), + BBR6(AddressingMode), + BBR7(AddressingMode), + BBS0(AddressingMode), + BBS1(AddressingMode), + BBS2(AddressingMode), + BBS3(AddressingMode), + BBS4(AddressingMode), + BBS5(AddressingMode), + BBS6(AddressingMode), + BBS7(AddressingMode), + BCC(AddressingMode), + BCS(AddressingMode), + BEQ(AddressingMode), + BIT(AddressingMode), + BMI(AddressingMode), + BNE(AddressingMode), + BPL(AddressingMode), + BRA(AddressingMode), + BRK(AddressingMode), + BVC(AddressingMode), + BVS(AddressingMode), + CLC(AddressingMode), + CLD(AddressingMode), + CLI(AddressingMode), + CLV(AddressingMode), + CMP(AddressingMode), + CPX(AddressingMode), + CPY(AddressingMode), + DEC(AddressingMode), + DEX(AddressingMode), + DEY(AddressingMode), + EOR(AddressingMode), + INC(AddressingMode), + INX(AddressingMode), + INY(AddressingMode), + JMP(AddressingMode), + JSR(AddressingMode), + LDA(AddressingMode), + LDX(AddressingMode), + LDY(AddressingMode), + LSR(AddressingMode), + NOP(AddressingMode), + ORA(AddressingMode), + PHA(AddressingMode), + PHP(AddressingMode), + PHX(AddressingMode), + PHY(AddressingMode), + PLA(AddressingMode), + PLP(AddressingMode), + PLX(AddressingMode), + PLY(AddressingMode), + RMB0(AddressingMode), + RMB1(AddressingMode), + RMB2(AddressingMode), + RMB3(AddressingMode), + RMB4(AddressingMode), + RMB5(AddressingMode), + RMB6(AddressingMode), + RMB7(AddressingMode), + ROL(AddressingMode), + ROR(AddressingMode), + RTI(AddressingMode), + RTS(AddressingMode), + SBC(AddressingMode), + SEC(AddressingMode), + SED(AddressingMode), + SEI(AddressingMode), + SMB0(AddressingMode), + SMB1(AddressingMode), + SMB2(AddressingMode), + SMB3(AddressingMode), + SMB4(AddressingMode), + SMB5(AddressingMode), + SMB6(AddressingMode), + SMB7(AddressingMode), + STA(AddressingMode), + STP(AddressingMode), + STX(AddressingMode), + STY(AddressingMode), + STZ(AddressingMode), + TAX(AddressingMode), + TAY(AddressingMode), + TRB(AddressingMode), + TSB(AddressingMode), + TSX(AddressingMode), + TXA(AddressingMode), + TXS(AddressingMode), + TYA(AddressingMode), + WAI(AddressingMode), +} + +impl Opcode { + fn call(&self) { + match self { + Opcode::ADC(_addressing_mode) => {} + Opcode::AND(_addressing_mode) => {} + Opcode::ASL(_addressing_mode) => {} + Opcode::BBR0(_addressing_mode) => {} + Opcode::BBR1(_addressing_mode) => {} + Opcode::BBR2(_addressing_mode) => {} + Opcode::BBR3(_addressing_mode) => {} + Opcode::BBR4(_addressing_mode) => {} + Opcode::BBR5(_addressing_mode) => {} + Opcode::BBR6(_addressing_mode) => {} + Opcode::BBR7(_addressing_mode) => {} + Opcode::BBS0(_addressing_mode) => {} + Opcode::BBS1(_addressing_mode) => {} + Opcode::BBS2(_addressing_mode) => {} + Opcode::BBS3(_addressing_mode) => {} + Opcode::BBS4(_addressing_mode) => {} + Opcode::BBS5(_addressing_mode) => {} + Opcode::BBS6(_addressing_mode) => {} + Opcode::BBS7(_addressing_mode) => {} + Opcode::BCC(_addressing_mode) => {} + Opcode::BCS(_addressing_mode) => {} + Opcode::BEQ(_addressing_mode) => {} + Opcode::BIT(_addressing_mode) => {} + Opcode::BMI(_addressing_mode) => {} + Opcode::BNE(_addressing_mode) => {} + Opcode::BPL(_addressing_mode) => {} + Opcode::BRA(_addressing_mode) => {} + Opcode::BRK(_addressing_mode) => {} + Opcode::BVC(_addressing_mode) => {} + Opcode::BVS(_addressing_mode) => {} + Opcode::CLC(_addressing_mode) => {} + Opcode::CLD(_addressing_mode) => {} + Opcode::CLI(_addressing_mode) => {} + Opcode::CLV(_addressing_mode) => {} + Opcode::CMP(_addressing_mode) => {} + Opcode::CPX(_addressing_mode) => {} + Opcode::CPY(_addressing_mode) => {} + Opcode::DEC(_addressing_mode) => {} + Opcode::DEX(_addressing_mode) => {} + Opcode::DEY(_addressing_mode) => {} + Opcode::EOR(_addressing_mode) => {} + Opcode::INC(_addressing_mode) => {} + Opcode::INX(_addressing_mode) => {} + Opcode::INY(_addressing_mode) => {} + Opcode::JMP(_addressing_mode) => {} + Opcode::JSR(_addressing_mode) => {} + Opcode::LDA(_addressing_mode) => {} + Opcode::LDX(_addressing_mode) => {} + Opcode::LDY(_addressing_mode) => {} + Opcode::LSR(_addressing_mode) => {} + Opcode::NOP(_addressing_mode) => {} + Opcode::ORA(_addressing_mode) => {} + Opcode::PHA(_addressing_mode) => {} + Opcode::PHP(_addressing_mode) => {} + Opcode::PHX(_addressing_mode) => {} + Opcode::PHY(_addressing_mode) => {} + Opcode::PLA(_addressing_mode) => {} + Opcode::PLP(_addressing_mode) => {} + Opcode::PLX(_addressing_mode) => {} + Opcode::PLY(_addressing_mode) => {} + Opcode::RMB0(_addressing_mode) => {} + Opcode::RMB1(_addressing_mode) => {} + Opcode::RMB2(_addressing_mode) => {} + Opcode::RMB3(_addressing_mode) => {} + Opcode::RMB4(_addressing_mode) => {} + Opcode::RMB5(_addressing_mode) => {} + Opcode::RMB6(_addressing_mode) => {} + Opcode::RMB7(_addressing_mode) => {} + Opcode::ROL(_addressing_mode) => {} + Opcode::ROR(_addressing_mode) => {} + Opcode::RTI(_addressing_mode) => {} + Opcode::RTS(_addressing_mode) => {} + Opcode::SBC(_addressing_mode) => {} + Opcode::SEC(_addressing_mode) => {} + Opcode::SED(_addressing_mode) => {} + Opcode::SEI(_addressing_mode) => {} + Opcode::SMB0(_addressing_mode) => {} + Opcode::SMB1(_addressing_mode) => {} + Opcode::SMB2(_addressing_mode) => {} + Opcode::SMB3(_addressing_mode) => {} + Opcode::SMB4(_addressing_mode) => {} + Opcode::SMB5(_addressing_mode) => {} + Opcode::SMB6(_addressing_mode) => {} + Opcode::SMB7(_addressing_mode) => {} + Opcode::STA(_addressing_mode) => {} + Opcode::STP(_addressing_mode) => {} + Opcode::STX(_addressing_mode) => {} + Opcode::STY(_addressing_mode) => {} + Opcode::STZ(_addressing_mode) => {} + Opcode::TAX(_addressing_mode) => {} + Opcode::TAY(_addressing_mode) => {} + Opcode::TRB(_addressing_mode) => {} + Opcode::TSB(_addressing_mode) => {} + Opcode::TSX(_addressing_mode) => {} + Opcode::TXA(_addressing_mode) => {} + Opcode::TXS(_addressing_mode) => {} + Opcode::TYA(_addressing_mode) => {} + Opcode::WAI(_addressing_mode) => {} + } + } +} + +fn main() { + let ram = MemArea::new(0x0000, 0x3FFF, 2, "ram".into()); + let rom = MemArea::new(0xE000, 0xFFFF, 4, "rom".into()); + let vram = MemArea::new(0x6000, 0xDFFF, 1, "vram".into()); + let mut memory = Mem::new(ram); + match memory.add_area(rom) { + Err(error) => println!("Error adding rom: {:?}", error), + Ok(()) => {} + }; + match memory.add_area(vram) { + Err(error) => println!("Error adding vram: {:?}", error), + Ok(()) => {} + }; + match memory.write(0xFFFC, 0x00) { + Err(error) => println!("Error writing to memory at address 0xFFFC: {:?}", error), + Ok(()) => {} + }; + match memory.write(0xFFFD, 0x00) { + Err(error) => println!("Error writing to memory at address 0xFFFD: {:?}", error), + Ok(()) => {} + }; + match memory.write(0x0000, 0xAE) { + Err(error) => println!("Error writing to memory at address 0x0000: {:?}", error), + Ok(()) => {} + }; + match memory.write(0x0001, 0xAE) { + Err(error) => println!("Error writing to memory: {:?}", error), + Ok(()) => {} + }; + let mut cpu = Cpu::new(memory); + match cpu.reset() { + Err(error) => println!("{error:?}"), + Ok(()) => { + println!("accumulator: {a:?}, x: {x:?}, y: {y:?}, program counter: {pc:?}, stack pointer: {s:?}, status register: {p:?}, irq pin: {irq:?}, nmi pin: {nmi:?}", a = cpu.a, x = cpu.x, y = cpu.y, pc = cpu.pc, s = cpu.s, p = cpu.p, irq = cpu.irq, nmi = cpu.nmi); + } + } + match cpu.tick() { + Ok(()) => { + println!("accumulator: {a:?}, x: {x:?}, y: {y:?}, program counter: {pc:?}, stack pointer: {s:?}, status register: {p:?}, irq pin: {irq:?}, nmi pin: {nmi:?}", a = cpu.a, x = cpu.x, y = cpu.y, pc = cpu.pc, s = cpu.s, p = cpu.p, irq = cpu.irq, nmi = cpu.nmi); + cpu.tick().unwrap() + } + Err(error) => match error { + ExecutionError::InvalidInstruction => {} + ExecutionError::StackOverflow => panic!("Stack overflowed!"), + ExecutionError::NoInterrupt => {} + ExecutionError::MemoryError(error) => match error { + MemoryError::Unmapped => panic!( + "Cpu tried to access memory that hasn't yet been mapped at {:?}", + cpu.pc + ), + MemoryError::NoDataAtAddress => panic!( + "Cpu tried to read from address {:?} but there was no data", + cpu.pc + ), + }, + ExecutionError::InterruptsDisabled => (), + }, + }; +}