rustfmt cleanup
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
|
||||
/// Represents the various addressing modes of the 6502 CPU.
|
||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||
pub enum AddressMode {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
|
||||
/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer.
|
||||
/// This was built along watching the video series where Ben builds a
|
||||
/// 6502 on a breadboard and explains each step.
|
||||
///
|
||||
pub struct BenEater {
|
||||
|
||||
}
|
||||
|
||||
pub struct BenEater {}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
pub mod beneater;
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@ pub const ISA_OP_LDY_ZP: u8 = 0xa4;
|
||||
pub const ISA_OP_LDY_ZPX: u8 = 0xb4;
|
||||
pub const ISA_OP_LDY_ABS: u8 = 0xac;
|
||||
pub const ISA_OP_LDY_ABSX: u8 = 0xbc;
|
||||
|
||||
pub const ISA_OP_LSR_A: u8 = 0x4a;
|
||||
pub const ISA_OP_LSR_ZP: u8 = 0x46;
|
||||
pub const ISA_OP_LSR_ZPX: u8 = 0x56;
|
||||
@@ -167,4 +166,4 @@ pub const ISA_OP_TAY: u8 = 0xa8;
|
||||
pub const ISA_OP_TSX: u8 = 0xba;
|
||||
pub const ISA_OP_TXA: u8 = 0x8a;
|
||||
pub const ISA_OP_TXS: u8 = 0x9a;
|
||||
pub const ISA_OP_TYA: u8 = 0x98;
|
||||
pub const ISA_OP_TYA: u8 = 0x98;
|
||||
|
||||
@@ -54,4 +54,4 @@ pub const ISA_STUB_TAY: &str = "TAY";
|
||||
pub const ISA_STUB_TSX: &str = "TSX";
|
||||
pub const ISA_STUB_TXA: &str = "TXA";
|
||||
pub const ISA_STUB_TXS: &str = "TXS";
|
||||
pub const ISA_STUB_TYA: &str = "TYA";
|
||||
pub const ISA_STUB_TYA: &str = "TYA";
|
||||
|
||||
@@ -5,7 +5,6 @@ pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
||||
pub const OFFSET_RESET_VECTOR: u16 = 0xfffc;
|
||||
pub const OFFSET_INT_VECTOR: u16 = 0xfffe;
|
||||
|
||||
|
||||
pub const VIA6522_ORB: u8 = 0;
|
||||
pub const VIA6522_ORA: u8 = 1;
|
||||
pub const VIA6522_DDRB: u8 = 2;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod constants_isa_stub;
|
||||
pub mod constants_isa_op;
|
||||
pub mod constants_isa_stub;
|
||||
pub mod constants_system;
|
||||
|
||||
+1222
-165
File diff suppressed because it is too large
Load Diff
@@ -1,23 +0,0 @@
|
||||
use log::debug;
|
||||
use crate::address_mode::AddressMode::*;
|
||||
use crate::constants::constants_isa_op::*;
|
||||
|
||||
fn join_word(low: u8, high: u8) -> u16 {
|
||||
((high as u16) << 8) | low as u16
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_join_word() {
|
||||
let low: u8 = 0xcd;
|
||||
let high: u8 = 0xab;
|
||||
|
||||
assert_eq!(
|
||||
join_word(low, high),
|
||||
0xabcd
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
use crate::address_mode::AddressMode;
|
||||
use crate::address_mode::AddressMode::*;
|
||||
use crate::mos6502flags::Mos6502Flag::*;
|
||||
|
||||
mod from_bytes;
|
||||
mod to_bytes;
|
||||
mod to_string;
|
||||
@@ -1,38 +0,0 @@
|
||||
use crate::address_mode::AddressMode;
|
||||
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY};
|
||||
use crate::constants::constants_isa_op::*;
|
||||
|
||||
fn split_word_hl(to_split: u16) -> (u8, u8) {
|
||||
let low = (to_split & 0xff) as u8;
|
||||
let high = ((to_split & 0xff00) >> 8) as u8;
|
||||
(high, low)
|
||||
}
|
||||
|
||||
fn split_word_lh(to_split: u16) -> (u8, u8) {
|
||||
let low = (to_split & 0xff) as u8;
|
||||
let high = ((to_split & 0xff00) >> 8) as u8;
|
||||
(low, high)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn split_le() {
|
||||
let value = 0xabcd;
|
||||
let (high, low) = split_word_hl(value);
|
||||
|
||||
assert_eq!(low, 0xcd);
|
||||
assert_eq!(high, 0xab);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_be() {
|
||||
let value = 0xabcd;
|
||||
let (low, high) = split_word_lh(value);
|
||||
|
||||
assert_eq!(low, 0xcd);
|
||||
assert_eq!(high, 0xab);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
fn format(mode: &AddressMode, prefix: &str) -> String {
|
||||
// let suffix = match mode {
|
||||
// AddressMode::Implied => "",
|
||||
// AddressMode::Accumulator => " A",
|
||||
// AddressMode::Immediate(value) => &*format!(" #${value:02x}"),
|
||||
// AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"),
|
||||
// AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"),
|
||||
// AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"),
|
||||
// AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"),
|
||||
// AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"),
|
||||
// AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"),
|
||||
// AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"),
|
||||
// AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y")
|
||||
// };
|
||||
// format!("{}{}", prefix, suffix)
|
||||
prefix.to_string()
|
||||
}
|
||||
@@ -1,10 +1,36 @@
|
||||
use crate::address_mode::AddressMode;
|
||||
use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA};
|
||||
use crate::constants::constants_isa_op::{
|
||||
ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX,
|
||||
ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY,
|
||||
ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A,
|
||||
ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS,
|
||||
ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK,
|
||||
ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS,
|
||||
ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY,
|
||||
ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS,
|
||||
ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX,
|
||||
ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I,
|
||||
ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS,
|
||||
ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS,
|
||||
ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I,
|
||||
ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY,
|
||||
ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I,
|
||||
ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP,
|
||||
ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I,
|
||||
ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP,
|
||||
ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP,
|
||||
ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX,
|
||||
ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I,
|
||||
ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED,
|
||||
ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY,
|
||||
ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS,
|
||||
ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS,
|
||||
ISA_OP_TYA,
|
||||
};
|
||||
use crate::op_info::OpInfo;
|
||||
use crate::operation::Operation;
|
||||
use crate::operation::Operation::*;
|
||||
|
||||
|
||||
pub fn INSTRUCTION_CYCLES(instruction: u8) -> u8 {
|
||||
INSTRUCTION_TABLE[instruction as usize].unwrap().cycles
|
||||
}
|
||||
@@ -723,7 +749,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
||||
operation: Operation::ROR,
|
||||
mode: AddressMode::Accumulator,
|
||||
length: 1,
|
||||
cycles: 2
|
||||
cycles: 2,
|
||||
});
|
||||
table[ISA_OP_ROR_ZP as usize] = Some(OpInfo {
|
||||
operation: Operation::ROR,
|
||||
@@ -996,4 +1022,4 @@ mod test {
|
||||
defined_count
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
pub mod periph;
|
||||
pub mod address_mode;
|
||||
pub mod mos6502cpu;
|
||||
pub mod instruction;
|
||||
pub mod mos6502flags;
|
||||
pub mod computers;
|
||||
pub mod constants;
|
||||
pub mod operation;
|
||||
pub mod instruction;
|
||||
pub mod instruction_table;
|
||||
pub mod mos6502cpu;
|
||||
pub mod mos6502flags;
|
||||
pub mod op_info;
|
||||
pub mod operand;
|
||||
pub mod instruction_table;
|
||||
pub mod computers;
|
||||
pub mod operation;
|
||||
pub mod periph;
|
||||
|
||||
+186
-141
@@ -1,14 +1,14 @@
|
||||
use log::trace;
|
||||
use crate::address_mode::AddressMode;
|
||||
use crate::constants::constants_isa_op::ISA_OP_NOP;
|
||||
use crate::constants::constants_system::*;
|
||||
use crate::instruction::Instruction;
|
||||
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags};
|
||||
use crate::instruction_table::INSTRUCTION_TABLE;
|
||||
use crate::mos6502flags::Mos6502Flag::*;
|
||||
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags};
|
||||
use crate::op_info::OpInfo;
|
||||
use crate::operand::Operand;
|
||||
use crate::operation::Operation;
|
||||
use crate::constants::constants_system::*;
|
||||
use crate::instruction_table::INSTRUCTION_TABLE;
|
||||
use log::trace;
|
||||
|
||||
pub struct Mos6502Cpu {
|
||||
memory: [u8; SIZE_64KB],
|
||||
@@ -30,15 +30,14 @@ pub struct Mos6502Cpu {
|
||||
ir: Instruction, // Instruction Register
|
||||
oi: OpInfo,
|
||||
has_reset: bool,
|
||||
iv: u16, // Interrupt Vector
|
||||
iv: u16, // Interrupt Vector
|
||||
cycle_carry: u16, // Value to hold between microsteps
|
||||
ir_bytes: [u8; 4],
|
||||
/// CPU Read signal
|
||||
pub read_signal: bool
|
||||
pub read_signal: bool,
|
||||
}
|
||||
|
||||
impl Mos6502Cpu {
|
||||
|
||||
/// set_data_bus
|
||||
///
|
||||
/// Sets data on the data bus.
|
||||
@@ -71,7 +70,7 @@ impl Default for Mos6502Cpu {
|
||||
iv: 0xfffe,
|
||||
cycle_carry: 0x0000,
|
||||
ir_bytes: [0x00; 4],
|
||||
read_signal: true
|
||||
read_signal: true,
|
||||
};
|
||||
working.reset_cpu();
|
||||
working
|
||||
@@ -108,7 +107,10 @@ impl Mos6502Cpu {
|
||||
self.iv = self.read_word(&OFFSET_INT_VECTOR);
|
||||
self.address_bus = self.pc;
|
||||
self.read_signal = true;
|
||||
println!("PC and IV are now set from ROM addresses / AB = {:016b}", self.address_bus);
|
||||
println!(
|
||||
"PC and IV are now set from ROM addresses / AB = {:016b}",
|
||||
self.address_bus
|
||||
);
|
||||
}
|
||||
|
||||
fn read_word(&self, offset: &u16) -> u16 {
|
||||
@@ -126,7 +128,11 @@ impl Mos6502Cpu {
|
||||
self.flags.flag(flag_to_read)
|
||||
}
|
||||
pub fn poke_flag(&mut self, flag_to_set: Mos6502Flag, new_value: bool) {
|
||||
if new_value { self.flags.set_flag(flag_to_set) } else { self.flags.clear_flag(flag_to_set) }
|
||||
if new_value {
|
||||
self.flags.set_flag(flag_to_set)
|
||||
} else {
|
||||
self.flags.clear_flag(flag_to_set)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek(&self, offset: u16) -> u8 {
|
||||
@@ -142,10 +148,9 @@ impl Mos6502Cpu {
|
||||
self.a
|
||||
}
|
||||
pub fn poke_a(&mut self, new_a: u8) {
|
||||
println!("Updating register A from [{}] to [{}]", self.a, new_a);
|
||||
|
||||
println!("Updating register A from [{}] to [{}]", self.a, new_a);
|
||||
|
||||
self.a = new_a;
|
||||
self.a = new_a;
|
||||
}
|
||||
|
||||
pub fn peek_x(&self) -> u8 {
|
||||
@@ -175,7 +180,6 @@ impl Mos6502Cpu {
|
||||
|
||||
/// Ticks the CPU
|
||||
pub fn tick(&mut self) {
|
||||
|
||||
println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc);
|
||||
if self.microcode_step == 0 {
|
||||
println!("OUT OF MICROSTEPS. Decoding the next instruction");
|
||||
@@ -190,28 +194,27 @@ impl Mos6502Cpu {
|
||||
// set the counter to the number of steps left
|
||||
} else {
|
||||
// run 1 microcode step
|
||||
println!("Microstep {}/{} for {:?}", self.microcode_step, self.oi.cycles, self.ir.op);
|
||||
println!(
|
||||
"Microstep {}/{} for {:?}",
|
||||
self.microcode_step, self.oi.cycles, self.ir.op
|
||||
);
|
||||
match self.ir.op {
|
||||
Operation::ADC => {
|
||||
match self.microcode_step {
|
||||
1 => {
|
||||
match self.ir.mode {
|
||||
AddressMode::Immediate => {}
|
||||
AddressMode::ZeroPage => {}
|
||||
AddressMode::ZeroPageX => {}
|
||||
AddressMode::Absolute => {}
|
||||
AddressMode::AbsoluteX => {}
|
||||
AddressMode::AbsoluteY => {}
|
||||
AddressMode::Indirect => {}
|
||||
AddressMode::IndirectX => {}
|
||||
AddressMode::IndirectY => {}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
2 => {},
|
||||
Operation::ADC => match self.microcode_step {
|
||||
1 => match self.ir.mode {
|
||||
AddressMode::Immediate => {}
|
||||
AddressMode::ZeroPage => {}
|
||||
AddressMode::ZeroPageX => {}
|
||||
AddressMode::Absolute => {}
|
||||
AddressMode::AbsoluteX => {}
|
||||
AddressMode::AbsoluteY => {}
|
||||
AddressMode::Indirect => {}
|
||||
AddressMode::IndirectX => {}
|
||||
AddressMode::IndirectY => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
2 => {}
|
||||
_ => {}
|
||||
},
|
||||
Operation::AND => {}
|
||||
Operation::ASL => {}
|
||||
Operation::BCC => {}
|
||||
@@ -247,10 +250,8 @@ impl Mos6502Cpu {
|
||||
AddressMode::ZeroPage => {
|
||||
// read from
|
||||
let offset = match self.ir.operand {
|
||||
Operand::Byte(z) => {
|
||||
z
|
||||
}
|
||||
_ => { 0x00 }
|
||||
Operand::Byte(z) => z,
|
||||
_ => 0x00,
|
||||
};
|
||||
trace!("READING FROM MEMORY AT 0x{offset:04x}");
|
||||
self.memory[offset as usize]
|
||||
@@ -258,37 +259,29 @@ impl Mos6502Cpu {
|
||||
}
|
||||
AddressMode::ZeroPageX => {
|
||||
let offset = match self.ir.operand {
|
||||
Operand::Byte(z) => {
|
||||
z
|
||||
}
|
||||
_ => { 0x00 }
|
||||
Operand::Byte(z) => z,
|
||||
_ => 0x00,
|
||||
};
|
||||
// self.memory.peek(offset + self.x);
|
||||
self.memory[offset as usize]
|
||||
}
|
||||
AddressMode::Absolute => {
|
||||
let offset = match self.ir.operand {
|
||||
Operand::Word(offset) => {
|
||||
offset
|
||||
}
|
||||
_ => { 0x00 }
|
||||
Operand::Word(offset) => offset,
|
||||
_ => 0x00,
|
||||
};
|
||||
// self.memory.peek(offset)
|
||||
self.memory[offset as usize]
|
||||
}
|
||||
AddressMode::AbsoluteX => {
|
||||
let offset = match self.ir.operand {
|
||||
Operand::Word(offset) => {
|
||||
offset
|
||||
}
|
||||
_ => { 0x00 }
|
||||
Operand::Word(offset) => offset,
|
||||
_ => 0x00,
|
||||
};
|
||||
// self.memory.peek(offset + self.x);
|
||||
self.memory[offset as usize]
|
||||
}
|
||||
_ => {
|
||||
0x00
|
||||
}
|
||||
_ => 0x00,
|
||||
};
|
||||
}
|
||||
// DEC write memory
|
||||
@@ -310,8 +303,8 @@ impl Mos6502Cpu {
|
||||
(self.y, _) = self.y.overflowing_sub(1);
|
||||
}
|
||||
}
|
||||
Operation::EOR => { }
|
||||
Operation::INC => { }
|
||||
Operation::EOR => {}
|
||||
Operation::INC => {}
|
||||
Operation::INX => {
|
||||
if self.microcode_step == 1 {
|
||||
let (new_x, new_carry) = self.x.overflowing_add(1);
|
||||
@@ -328,75 +321,67 @@ impl Mos6502Cpu {
|
||||
self.poke_flag(Carry, new_carry);
|
||||
self.address_bus = self.pc;
|
||||
self.data_bus = 0x00;
|
||||
} }
|
||||
Operation::JMP => {
|
||||
match self.ir.operand {
|
||||
Operand::Word(offset) => {
|
||||
self.pc = offset;
|
||||
self.address_bus = self.pc;
|
||||
self.data_bus = 0x00;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Operation::JMP => match self.ir.operand {
|
||||
Operand::Word(offset) => {
|
||||
self.pc = offset;
|
||||
self.address_bus = self.pc;
|
||||
self.data_bus = 0x00;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Operation::JSR => {
|
||||
// push pc to stack.
|
||||
// jump to the subroutine.
|
||||
}
|
||||
Operation::LDA => {
|
||||
match self.oi.mode {
|
||||
AddressMode::Immediate => {
|
||||
match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
println!("Loading 0x{value:02x} ({value}) into A");
|
||||
self.a = value;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Operation::LDA => match self.oi.mode {
|
||||
AddressMode::Immediate => match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
println!("Loading 0x{value:02x} ({value}) into A");
|
||||
self.a = value;
|
||||
}
|
||||
AddressMode::ZeroPage => {
|
||||
match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
println!("Loading from zero page at 0x{value:02x} ({value})");
|
||||
self.a = self.memory[value as usize];
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AddressMode::ZeroPage => match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
println!("Loading from zero page at 0x{value:02x} ({value})");
|
||||
self.a = self.memory[value as usize];
|
||||
}
|
||||
AddressMode::ZeroPageX => {
|
||||
match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
let x_offset = self.x;
|
||||
self.a = self.memory[(value + x_offset) as usize];
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AddressMode::ZeroPageX => match self.ir.operand {
|
||||
Operand::Byte(value) => {
|
||||
let x_offset = self.x;
|
||||
self.a = self.memory[(value + x_offset) as usize];
|
||||
}
|
||||
AddressMode::Absolute => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
println!("Loading from absolute address 0x{offset:04x}");
|
||||
self.a = self.memory[offset as usize];
|
||||
}
|
||||
|
||||
}
|
||||
AddressMode::AbsoluteX => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
self.a = self.memory[(offset + self.x as u16) as usize];
|
||||
}
|
||||
}
|
||||
AddressMode::AbsoluteY => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
self.a = self.memory[(offset + self.y as u16) as usize];
|
||||
}
|
||||
}
|
||||
AddressMode::Indirect => {}
|
||||
AddressMode::IndirectX => {}
|
||||
AddressMode::IndirectY => {}
|
||||
_ => {
|
||||
println!("INVALID ADDRESS MODE FOR LDA");
|
||||
_ => {}
|
||||
},
|
||||
AddressMode::Absolute => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
println!("Loading from absolute address 0x{offset:04x}");
|
||||
self.a = self.memory[offset as usize];
|
||||
}
|
||||
}
|
||||
}
|
||||
AddressMode::AbsoluteX => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
self.a = self.memory[(offset + self.x as u16) as usize];
|
||||
}
|
||||
}
|
||||
AddressMode::AbsoluteY => {
|
||||
if let Operand::Word(offset) = self.ir.operand {
|
||||
let real_offset = offset + self.y as u16;
|
||||
println!("offset: {offset:04x} + {:02x}", self.y);
|
||||
self.a = self.memory[(offset + self.y as u16) as usize];
|
||||
}
|
||||
}
|
||||
AddressMode::Indirect => {}
|
||||
AddressMode::IndirectX => {}
|
||||
AddressMode::IndirectY => {}
|
||||
_ => {
|
||||
println!("INVALID ADDRESS MODE FOR LDA");
|
||||
}
|
||||
},
|
||||
Operation::LDX => {}
|
||||
Operation::LDY => {}
|
||||
Operation::LSR => {}
|
||||
@@ -501,13 +486,11 @@ impl Mos6502Cpu {
|
||||
Operation::TAY => {
|
||||
self.y = self.a;
|
||||
}
|
||||
Operation::TSX => {
|
||||
}
|
||||
Operation::TSX => {}
|
||||
Operation::TXA => {
|
||||
self.a = self.x;
|
||||
}
|
||||
Operation::TXS => {
|
||||
}
|
||||
Operation::TXS => {}
|
||||
Operation::TYA => {
|
||||
self.y = self.a;
|
||||
}
|
||||
@@ -517,25 +500,41 @@ impl Mos6502Cpu {
|
||||
}
|
||||
|
||||
pub fn dump(&self) {
|
||||
println!("CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}",
|
||||
self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step, self.flags.dump());
|
||||
println!(
|
||||
"CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}",
|
||||
self.pc,
|
||||
self.a,
|
||||
self.x,
|
||||
self.y,
|
||||
self.address_bus,
|
||||
self.data_bus,
|
||||
self.microcode_step,
|
||||
self.flags.dump()
|
||||
);
|
||||
}
|
||||
|
||||
/// dump_data
|
||||
///
|
||||
/// returns
|
||||
/// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step
|
||||
pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8, u8) {
|
||||
(self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step)
|
||||
pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8) {
|
||||
(
|
||||
self.pc,
|
||||
self.a,
|
||||
self.x,
|
||||
self.y,
|
||||
self.address_bus,
|
||||
self.data_bus,
|
||||
self.microcode_step,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::constants::constants_isa_op::*;
|
||||
use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn clc() {
|
||||
@@ -548,7 +547,9 @@ mod test {
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
// Tick the CPU through the instruction
|
||||
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLC as usize].unwrap().cycles { cpu.tick(); }
|
||||
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLC) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert!(!cpu.peek_flag(Carry));
|
||||
}
|
||||
@@ -560,7 +561,9 @@ mod test {
|
||||
cpu.memory[0x6000] = ISA_OP_CLD;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLD as usize].unwrap().cycles { cpu.tick(); }
|
||||
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLD) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert!(!cpu.peek_flag(Decimal));
|
||||
}
|
||||
@@ -572,10 +575,11 @@ mod test {
|
||||
cpu.memory[0x6000] = ISA_OP_CLI;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert!(!cpu.peek_flag(Interrupt));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -585,7 +589,9 @@ mod test {
|
||||
cpu.memory[0x6000] = ISA_OP_CLV;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert!(!cpu.peek_flag(Overflow));
|
||||
}
|
||||
@@ -597,7 +603,9 @@ mod test {
|
||||
cpu.memory[0x6001] = 0xab;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.a, 0xab);
|
||||
}
|
||||
@@ -611,7 +619,9 @@ mod test {
|
||||
cpu.memory[0x00ac] = 0xbe;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) { cpu.tick(); };
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
// println!("MEMORY AT 0x00aa, ab, ac, ad, ae -> {:02x} {:02x} {:02x} {:02x} {:02x}", cpu.memory[0x00aa], cpu.memory[0x00ab], cpu.memory[0x00ac], cpu.memory[0x00ad], cpu.memory[0x00ae]);
|
||||
// cpu.dump();
|
||||
@@ -630,7 +640,9 @@ mod test {
|
||||
cpu.memory[0x00ab] = 0xbe;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) { cpu.tick(); }
|
||||
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.a, 0xbe);
|
||||
}
|
||||
@@ -644,7 +656,9 @@ mod test {
|
||||
cpu.memory[0x0eef] = 0xab;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.a, 0xab);
|
||||
}
|
||||
@@ -659,7 +673,9 @@ mod test {
|
||||
cpu.memory[0x0ef0] = 0xab;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.a, 0xab);
|
||||
}
|
||||
@@ -669,12 +685,14 @@ mod test {
|
||||
let mut cpu = Mos6502Cpu::default();
|
||||
cpu.memory[0x6000] = ISA_OP_LDA_ABSY;
|
||||
cpu.memory[0x6001] = 0xef;
|
||||
cpu.memory[0x6002] = 0xbe;
|
||||
cpu.memory[0x6002] = 0x0e;
|
||||
cpu.poke_y(0x01);
|
||||
cpu.memory[0x0ef0] = 0xab;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.a, 0xab);
|
||||
}
|
||||
@@ -687,9 +705,13 @@ mod test {
|
||||
cpu.memory[0x6001] = ISA_OP_INX;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(0xaa, cpu.x);
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(0xab, cpu.x);
|
||||
}
|
||||
|
||||
@@ -701,9 +723,13 @@ mod test {
|
||||
cpu.memory[0x6001] = ISA_OP_INY;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(0xaa, cpu.peek_y());
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(0xab, cpu.peek_y());
|
||||
}
|
||||
|
||||
@@ -715,9 +741,28 @@ mod test {
|
||||
cpu.memory[0x6001] = ISA_OP_ROR_A;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(cpu.peek_a(), 0b0101_0101);
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) { cpu.tick(); }
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) {
|
||||
cpu.tick();
|
||||
}
|
||||
assert_eq!(cpu.peek_a(), 0b1010_1010);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rol_zp_ror_zp() {
|
||||
let mut cpu = Mos6502Cpu::default();
|
||||
cpu.memory[0x00ab] = 0b0101_0101;
|
||||
cpu.memory[0x6000] = ISA_OP_ROL_ZP;
|
||||
cpu.memory[0x6001] = 0xab;
|
||||
cpu.pc = 0x6000;
|
||||
|
||||
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_ZP) {
|
||||
cpu.tick();
|
||||
}
|
||||
|
||||
assert_eq!(cpu.memory[0xab], 0b1010_1010);;
|
||||
}
|
||||
}
|
||||
|
||||
+41
-24
@@ -1,4 +1,6 @@
|
||||
use crate::mos6502flags::Mos6502Flag::{Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero};
|
||||
use crate::mos6502flags::Mos6502Flag::{
|
||||
Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero,
|
||||
};
|
||||
|
||||
pub const BIT_NEGATIVE: u8 = 7;
|
||||
pub const BIT_OVERFLOW: u8 = 6;
|
||||
@@ -59,7 +61,7 @@ impl Mos6502Flag {
|
||||
Decimal => BIT_DECIMAL,
|
||||
Break => BIT_BREAK,
|
||||
Overflow => BIT_OVERFLOW,
|
||||
Negative => BIT_NEGATIVE
|
||||
Negative => BIT_NEGATIVE,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,14 +79,15 @@ pub struct Mos6502Flags {
|
||||
|
||||
impl Mos6502Flags {
|
||||
pub fn dump(&self) -> String {
|
||||
format!("{}{}{}{}{}{}{}",
|
||||
if self.carry { 'C' } else { 'c' },
|
||||
if self.zero { 'Z' } else { 'z' },
|
||||
if self.interrupt { 'I' } else { 'i' },
|
||||
if self.decimal { 'D' } else { 'd' },
|
||||
if self.break_flag { 'B' } else { 'b' },
|
||||
if self.overflow { 'O' } else { 'o' },
|
||||
if self.negative { 'N' } else { 'n' }
|
||||
format!(
|
||||
"{}{}{}{}{}{}{}",
|
||||
if self.carry { 'C' } else { 'c' },
|
||||
if self.zero { 'Z' } else { 'z' },
|
||||
if self.interrupt { 'I' } else { 'i' },
|
||||
if self.decimal { 'D' } else { 'd' },
|
||||
if self.break_flag { 'B' } else { 'b' },
|
||||
if self.overflow { 'O' } else { 'o' },
|
||||
if self.negative { 'N' } else { 'n' }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -113,7 +116,8 @@ impl Mos6502Flags {
|
||||
Break => self.break_flag = false,
|
||||
Overflow => self.overflow = false,
|
||||
Negative => self.negative = false,
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
fn change_flag(&mut self, flag_to_change: Mos6502Flag, new_value: bool) {
|
||||
if new_value {
|
||||
@@ -139,25 +143,37 @@ impl Mos6502Flags {
|
||||
pub fn as_byte(&self) -> u8 {
|
||||
let mut working = 0x00;
|
||||
|
||||
if self.flag(Negative) { working += 1 << Negative.index(); }
|
||||
if self.flag(Overflow) { working += 1 << Overflow.index(); }
|
||||
working += 1 << 5; // Always Set
|
||||
if self.flag(Break) { working += 1 << Break.index(); }
|
||||
if self.flag(Decimal) { working += 1 << Decimal.index(); }
|
||||
if self.flag(Interrupt) { working += 1 << Interrupt.index(); }
|
||||
if self.flag(Zero) { working += 1 << Zero.index(); }
|
||||
if self.flag(Carry) { working += 1 << Carry.index(); }
|
||||
if self.flag(Negative) {
|
||||
working += 1 << Negative.index();
|
||||
}
|
||||
if self.flag(Overflow) {
|
||||
working += 1 << Overflow.index();
|
||||
}
|
||||
working += 1 << 5; // Always Set
|
||||
if self.flag(Break) {
|
||||
working += 1 << Break.index();
|
||||
}
|
||||
if self.flag(Decimal) {
|
||||
working += 1 << Decimal.index();
|
||||
}
|
||||
if self.flag(Interrupt) {
|
||||
working += 1 << Interrupt.index();
|
||||
}
|
||||
if self.flag(Zero) {
|
||||
working += 1 << Zero.index();
|
||||
}
|
||||
if self.flag(Carry) {
|
||||
working += 1 << Carry.index();
|
||||
}
|
||||
|
||||
working
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn from_byte(src: u8) -> Self {
|
||||
let mut working = Self::default();
|
||||
|
||||
working.change_flag(Negative, Self::bit(src, Negative.index()));
|
||||
working.change_flag(Overflow, Self::bit(src, Overflow.index()));
|
||||
working.change_flag(Overflow, Self::bit(src, Overflow.index()));
|
||||
working.change_flag(Break, Self::bit(src, Break.index()));
|
||||
working.change_flag(Decimal, Self::bit(src, Decimal.index()));
|
||||
working.change_flag(Interrupt, Self::bit(src, Interrupt.index()));
|
||||
@@ -182,14 +198,15 @@ impl Mos6502Flags {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
fn smoke() {
|
||||
assert!(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity() {
|
||||
|
||||
@@ -356,5 +356,4 @@ pub enum Operation {
|
||||
///
|
||||
/// Addressing Modes: Implied
|
||||
TYA,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ impl Default for At28C256 {
|
||||
fn default() -> Self {
|
||||
let vec = vec![0xea; SIZE_32KB];
|
||||
let boxed_slice: Box<[u8]> = vec.into_boxed_slice();
|
||||
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Failed to convert Vec to boxed array");
|
||||
At28C256 {
|
||||
data: boxed_array,
|
||||
}
|
||||
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice
|
||||
.try_into()
|
||||
.expect("Failed to convert Vec to boxed array");
|
||||
At28C256 { data: boxed_array }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,5 +18,7 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
fn smoke() {
|
||||
assert!(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
mod default;
|
||||
mod rom_chip;
|
||||
|
||||
use std::io::Read;
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use std::io::Read;
|
||||
|
||||
/// At28C256
|
||||
///
|
||||
@@ -25,8 +25,8 @@ impl At28C256 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
use super::*;
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
@@ -40,9 +40,8 @@ mod test {
|
||||
data.data[i] = 0xea;
|
||||
}
|
||||
for offset in 0..SIZE_32KB {
|
||||
if offset.is_multiple_of(SIZE_1KB) {
|
||||
};
|
||||
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||
if offset.is_multiple_of(SIZE_1KB) {};
|
||||
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
|
||||
impl RomChip for At28C256 {
|
||||
|
||||
fn read(&self, offset: &u16) -> u8 {
|
||||
self.data[*offset as usize]
|
||||
}
|
||||
@@ -21,7 +20,7 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
|
||||
|
||||
}
|
||||
fn smoke() {
|
||||
assert!(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
// HM62256 Static Ram
|
||||
|
||||
use log::debug;
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::ram_chip::RamChip;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use log::debug;
|
||||
|
||||
pub struct Hm62256 {
|
||||
pub(crate) base_offset: u16,
|
||||
pub(crate) data: Box<[u8]>
|
||||
pub(crate) data: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl Default for Hm62256 {
|
||||
fn default() -> Self {
|
||||
let vec = vec![0x00; SIZE_32KB];
|
||||
let boxed_slice: Box<[u8]> = vec.into_boxed_slice();
|
||||
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Unable to box the ram");
|
||||
let boxed_array: Box<[u8; SIZE_32KB]> =
|
||||
boxed_slice.try_into().expect("Unable to box the ram");
|
||||
Hm62256 {
|
||||
base_offset: 0x0000,
|
||||
data: boxed_array
|
||||
data: boxed_array,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +26,7 @@ impl Default for Hm62256 {
|
||||
impl RomChip for Hm62256 {
|
||||
fn read(&self, offset: &u16) -> u8 {
|
||||
// loops memory around past 32k
|
||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||
self.data[effective as usize]
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ impl RomChip for Hm62256 {
|
||||
|
||||
impl RamChip for Hm62256 {
|
||||
fn write(&mut self, offset: &u16, value: &u8) {
|
||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||
println!("Writing at E[{effective:04x}] / O[{offset:04x}]");
|
||||
self.data[effective as usize] = *value;
|
||||
}
|
||||
@@ -45,11 +46,13 @@ impl RamChip for Hm62256 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use rand::random;
|
||||
use super::*;
|
||||
use rand::random;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true) }
|
||||
fn smoke() {
|
||||
assert!(true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn written_data_comes_back() {
|
||||
@@ -59,7 +62,7 @@ mod test {
|
||||
for _ in 0..100_000 {
|
||||
let mut offset: u16 = random();
|
||||
println!("SIze = {SIZE_32KB}");
|
||||
let value: u8 =random();
|
||||
let value: u8 = random();
|
||||
println!("Wrote [{value:02x}] to [{offset:04x}]");
|
||||
ram.write(&offset, &value);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
pub mod rom_chip;
|
||||
|
||||
pub mod at28c256;
|
||||
pub mod ram_chip;
|
||||
pub mod hm62256;
|
||||
|
||||
pub mod ram_chip;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
Reference in New Issue
Block a user