Compare commits

..

4 Commits

@ -7,7 +7,7 @@ use super::{R6502, Bus};
pub enum ModeID pub enum ModeID
{ {
IMP, // Implied IMP, // Implied
ACM, // Accumulator - Not using, IMP might cover this ACM, // Accumulator
IMM, // Immediate IMM, // Immediate
ZP0, // Zero Page ZP0, // Zero Page
ZPX, // Zero Page, X ZPX, // Zero Page, X
@ -19,6 +19,7 @@ pub enum ModeID
IND, // Indirect IND, // Indirect
IZX, // Indirect, X IZX, // Indirect, X
IZY, // Indirect, Y IZY, // Indirect, Y
ERR, // Error mode - this is an invalid mode
} }
@ -38,9 +39,11 @@ pub enum ModeID
// GROUP TWO ADDRESS MODES // GROUP TWO ADDRESS MODES
// 000 #immediate IMM // 000 #immediate IMM
// 001 zero page ZP0 // 001 zero page ZP0
// 010 accumulator IMP // 010 accumulator ACM
// 011 absolute ABS // 011 absolute ABS
// 100 NONE ERR
// 101 zero page,X ZPX // 101 zero page,X ZPX
// 110 NONE ERR
// 111 absolute,X ABX // 111 absolute,X ABX
pub struct AddressingModes; pub struct AddressingModes;
@ -57,18 +60,37 @@ impl AddressingModes
AddressingModes::ABX, AddressingModes::ABX,
]; ];
pub const GROUP_TWO_ADDRS: [fn(&mut R6502, &mut dyn Bus) -> ModeID; 8] = [
AddressingModes::IMM,
AddressingModes::ZP0,
AddressingModes::ACM,
AddressingModes::ABS,
AddressingModes::ERR,
AddressingModes::ZPX,
AddressingModes::ERR,
AddressingModes::ABX,
];
} }
impl AddressingModes impl AddressingModes
{ {
// This is also the accumulator mode
pub fn ERR(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{
ModeID::ERR
}
pub fn IMP(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID pub fn IMP(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = cpu.a as u16;
ModeID::IMP ModeID::IMP
} }
pub fn ACM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{
cpu.working_data = cpu.a as u16;
ModeID::ACM
}
pub fn IMM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID pub fn IMM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_data = bus.read(cpu.pc) as u16;
@ -168,15 +190,70 @@ impl AddressingModes
ModeID::IND ModeID::IND
} }
// Indexed Indirect Addressing (IND, X)
// In indexed indirect addressing (referred to as (Indirect, X)), the second byte of the
// instruction is added to the contents of the X register, discarding the carry.
// The result of the addition points to a memory location on the Zero Page which contains
// the low order byte of the effective address. The next memory location in page zero,
// contains the high order byte of the effective address. Both memory locations specifying
// the effective address must be in the Zero Page.
//
// Info from:
// https://web.archive.org/web/20221112231348if_/http://archive.6502.org/datasheets/rockwell_r650x_r651x.pdf
pub fn IZX(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID pub fn IZX(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
let offset = bus.read(cpu.pc) as u16;
cpu.pc += 1;
let mut pointer = cpu.x as u16 + offset;
// discard the carry and wrap
// If the addition goes beyond the Zero Page
// it should wrap around back to the beginning
pointer = pointer & 0x00FF;
let lo_byte = bus.read(pointer) as u16;
let hi_byte = bus.read(pointer + 1) as u16;
cpu.working_addr = (hi_byte << 0x08) | lo_byte;
cpu.working_data = bus.read(cpu.working_addr) as u16 & 0x00FF;
ModeID::IZX ModeID::IZX
} }
// Indirect Indexed Addressing (IND), Y
// In indirect indexed addressing, the second byte of the instruction points to
// a memory location in page zero. The contents of this memory location are added to
// the contents of the Y register. The result is the low order byte of the effective address.
// The carry from this addition is added to the contents of the next page zero memory
// location, to form the high order byte of the effective address.
//
// Info from:
// https://web.archive.org/web/20221112231348if_/http://archive.6502.org/datasheets/rockwell_r650x_r651x.pdf
pub fn IZY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID pub fn IZY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
// zp_pointer points to a location in zero page
let zp_pointer = bus.read(cpu.pc) as u16;
cpu.pc += 1;
// The value at zp_pointer is added to the Y register
let zp_value = bus.read(zp_pointer) as u16;
let sum = zp_value + cpu.y as u16;
// The sum with the carry discarded is the lo byte
let lo_byte = sum & 0x00FF;
// The carry plus the value at the next zero page address is the hi byte
let zp_next = bus.read(zp_pointer + 1) as u16;
let temp = (sum & 0xFF00) >> 0x08;
let temp2 = temp + zp_next;
let hi_byte: u8 = (((sum & 0xFF00) >> 0x08) + zp_next) as u8;
// Store the final address and read the data
cpu.working_addr = ((hi_byte as u16) << 0x08) | lo_byte;
cpu.working_data = bus.read(cpu.working_addr) as u16;
ModeID::IZY ModeID::IZY
} }
} }

@ -2,7 +2,7 @@
#![allow(dead_code, non_snake_case)] #![allow(dead_code, non_snake_case)]
use super::{R6502, Bus, Flags}; use super::{R6502, Bus, Flags, addressing_modes::{AddressingModes, ModeID}};
// Instruction decoding: // Instruction decoding:
// https://llx.com/Neil/a2/opcodes.html // https://llx.com/Neil/a2/opcodes.html
@ -22,14 +22,25 @@ pub struct Instructions;
impl Instructions impl Instructions
{ {
pub const GROUP_ONE_OPS: [fn(&mut R6502, &mut dyn Bus); 8] = [ pub const GROUP_ONE_OPS: [fn(&mut R6502, &mut dyn Bus); 8] = [
Instructions::ORA, Instructions::ORA,
Instructions::AND, Instructions::AND,
Instructions::EOR, Instructions::EOR,
Instructions::ADC, Instructions::ADC,
Instructions::STA, Instructions::STA,
Instructions::LDA, Instructions::LDA,
Instructions::CMP, Instructions::CMP,
Instructions::SBC, Instructions::SBC,
];
pub const GROUP_TWO_OPS: [fn(&mut R6502, &mut dyn Bus); 8] = [
Instructions::ASL, // 000
Instructions::ROL, // 001
Instructions::LSR, // 010
Instructions::ROR, // 011
Instructions::STX, // 100
Instructions::LDX, // 101
Instructions::DEC, // 110
Instructions::INC, // 111
]; ];
} }
@ -173,19 +184,23 @@ impl Instructions
// Using a technique written javidx9 // Using a technique written javidx9
// The code in this function falls under the License (OLC-3) SEE LICENSE FILE // The code in this function falls under the License (OLC-3) SEE LICENSE FILE
// https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L714 // https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L714
//
// More info about the carry bit:
// http://forum.6502.org/viewtopic.php?t=18
pub fn SBC(cpu: &mut R6502, bus: &mut dyn Bus) pub fn SBC(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
// Seem to need the + 1 here for javidx9's algorithm to work let value = cpu.working_data ^ 0x00FF;
let value = (cpu.working_data ^ 0x00FF) + 1;
let carry = cpu.check_flag(Flags::C) as u16; let carry = cpu.check_flag(Flags::C) as u16;
let temp: u16 = cpu.a as u16 + value + carry; let temp: u16 = cpu.a as u16 + value + carry;
cpu.clear_flag(Flags::C);
if temp > 255 if temp > 255
{ {
cpu.set_flag(Flags::C); cpu.set_flag(Flags::C);
} }
cpu.clear_flag(Flags::Z);
if temp == 0 if temp == 0
{ {
cpu.set_flag(Flags::Z); cpu.set_flag(Flags::Z);
@ -209,6 +224,71 @@ impl Instructions
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// GROUP TWO // GROUP TWO
pub fn ASL(cpu: &mut R6502, bus: &mut dyn Bus)
{
cpu.clear_flag(Flags::C);
if cpu.working_data as u8 & 0x80 > 0
{
cpu.set_flag(Flags::C);
}
let result = cpu.working_data << 1;
cpu.clear_flag(Flags::Z);
if result == 0
{
cpu.set_flag(Flags::Z);
}
if result as u8 & 0x80 > 0
{
cpu.set_flag(Flags::N);
}
if cpu.addr_mode == ModeID::ACM
{
cpu.a = result as u8;
}
else
{
bus.write(cpu.working_addr, result as u8);
}
}
pub fn ROL(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn LSR(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn ROR(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn STX(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn LDX(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn DEC(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
pub fn INC(cpu: &mut R6502, bus: &mut dyn Bus)
{
}
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// GROUP THREE // GROUP THREE

@ -199,6 +199,41 @@ fn exe_group_one(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus)
fn exe_group_two(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus) fn exe_group_two(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus)
{ {
let addr_mask = (instruction & 0x1C) >> 2;
let op_mask = (instruction & 0xE0) >> 5;
// With STX and LDX, "zero page,X" addressing becomes "zero page,Y", and with LDX, "absolute,X" becomes "absolute,Y".
const STX_ZPX: u8 = 0x96;
const LDX_ZPX: u8 = 0xB6;
const LDX_ABX: u8 = 0xBE;
match instruction
{
STX_ZPX =>
{
cpu.addr_mode = AddressingModes::ZPY(cpu, bus);
Instructions::STX(cpu, bus);
},
LDX_ZPX =>
{
cpu.addr_mode = AddressingModes::ZPY(cpu, bus);
Instructions::LDX(cpu, bus);
}
LDX_ABX =>
{
cpu.addr_mode = AddressingModes::ABY(cpu, bus);
Instructions::LDX(cpu, bus);
}
_ =>
{
cpu.addr_mode = AddressingModes::GROUP_TWO_ADDRS[addr_mask as usize](cpu, bus);
Instructions::GROUP_TWO_OPS[op_mask as usize](cpu, bus);
}
}
} }

@ -4,6 +4,18 @@
use crate::tests::test_bus::RAMBus; use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers}; use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMP()
{
}
#[test]
fn ACM()
{
}
#[test] #[test]
fn IMM() fn IMM()
{ {
@ -94,6 +106,19 @@ fn ZPX()
assert_eq!(0x08, cpu.debug_get_reg(Registers::A)); assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
} }
#[test]
fn ZPY()
{
}
#[test]
fn REL()
{
}
#[test] #[test]
fn ABS() fn ABS()
{ {
@ -189,6 +214,87 @@ fn ABY()
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn IND()
{
}
#[test]
fn IZX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory
bus.write(0x010B, 0x08);
// Manuall put 0x010B into the Zero page at 0x000A
bus.write(0x000A, 0x0B); // Pointer lo byte
bus.write(0x000B, 0x01); // Pointer hi byte
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA1); // LDA - Indirect, X mode
bus.write(addr + 1, 0x09); // Argument - gets added to X reg
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn IZY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory
bus.write(0x020B, 0x08);
// Manuall put 0x01FC into the Zero page at 0x000A
// This will be added to the Y register (which will store 0x0F)
bus.write(0x000A, 0xFC); // Pointer lo byte
bus.write(0x000B, 0x01); // Pointer hi byte
// Program to load 0x08 into the accumulator
bus.write(addr, 0xB1); // LDA - Indirect, Y mode
bus.write(addr + 1, 0x0A); // Argument - Pointer into the Zero Page
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x0F); // Offset of the value at the zero page address
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register? // Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A)); assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
} }

@ -5,7 +5,7 @@ use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags}; use crate::r6502::{R6502, Bus, Registers, Flags};
#[test] #[test]
fn IMM() fn basic()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -32,55 +32,14 @@ fn IMM()
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x0A in the A register? // Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A), "Failed basic addition"); assert_eq!(0x0A, cpu.debug_get_reg(Registers::A), "Wrong answer");
assert_eq!(0, cpu.check_flag(Flags::V), "Overflow bit should not be set");
/////////////////////////////////////////// assert_eq!(0, cpu.check_flag(Flags::C), "Carry bit should not be set");
// EXTRA TESTING
// Add with carry in
// Write the program to memory
// ADC 6
bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr + 1, 0x06); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04);
cpu.set_flag(Flags::C);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A), "Failed addition with carry");
// Add with overflow
// Write the program to memory
// ADC 126
bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr + 1, 126); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 130 in the A register?
assert_eq!(130, cpu.debug_get_reg(Registers::A));
// Is the overflow bit set?
assert_eq!(1, cpu.check_flag(Flags::V), "Failed addition with overflow");
} }
#[test] #[test]
fn ZP0() fn with_carry()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -92,62 +51,30 @@ fn ZP0()
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x04 into memory in the zero page // Add with carry in
bus.write(0x000B, 0x04); // Write the program to memory
// ADC 6
// ADC #6 bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr, 0x65); // ADC - Zero Page mode bus.write(addr + 1, 0x06); // Argument
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
// manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04);
cpu.set_flag(Flags::C);
// manually setup the cpu registers // Clock the cpu twice (Clock essentially runs one full instruction)
cpu.debug_set_reg(Registers::A, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x0A in the A register? // Is 0x0B in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A)); assert_eq!(0x0B, cpu.debug_get_reg(Registers::A), "Wrong answer");
} assert_eq!(0, cpu.check_flag(Flags::V), "Overflow bit should not be set");
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x04);
// ADC #A
bus.write(addr, 0x75); // ADC - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x06);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A));
} }
#[test] #[test]
fn ABS() fn with_overflow()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -159,58 +86,24 @@ fn ABS()
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page // Add with overflow
bus.write(0x010B, 0x06); // Write the program to memory
// ADC 126
// AND $10B bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr, 0x6D); // ADC - Absolute mode bus.write(addr + 1, 126); // Argument
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
// manually setup the cpu registers // manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04); cpu.debug_set_reg(Registers::A, 0x04);
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x09 in the A register? // Is 130 in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A)); assert_eq!(130, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory
bus.write(0x010C, 0x04);
// ADC $10C
bus.write(addr, 0x7D); // ADC - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x06);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register? // Is the overflow bit set?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A)); assert_eq!(1, cpu.check_flag(Flags::V), "Failed addition with overflow");
} }

@ -1,207 +0,0 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x29); // AND - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x25); // AND - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x35); // AND - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x03);
// AND #3
bus.write(addr, 0x2D); // AND - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
//cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x3D); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x39); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}

@ -4,12 +4,8 @@
use crate::tests::test_bus::RAMBus; use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags}; use crate::r6502::{R6502, Bus, Registers, Flags};
//////////////////////////////////////////////////////////////////////////////
/// IMM IMM IMM IMM IMM IMM IMM IMM IMM
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn IMM() fn less_than()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -41,62 +37,10 @@ fn IMM()
assert_eq!(1, cpu.check_flag(Flags::C)); assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z)); assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N)); assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Program to compare 0x10 with 0x10
bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x10); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Program to compare 0x05 with 0x10
bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x10); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
} }
//////////////////////////////////////////////////////////////////////////////
/// ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn ZP0() fn equal_to()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -108,41 +52,12 @@ fn ZP0()
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x05);
// Program to compare 0x10 with 0x05 (0x05 will be the argument)
bus.write(addr, 0xC5); // CMP - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
/////////////////////// ///////////////////////
// Parameter is equal to the A reg // Parameter is equal to the A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x10 with 0x10 // Program to compare 0x10 with 0x10
bus.write(addr, 0xC5); // CMP - Zero Page mode bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x0A); // Argument bus.write(addr + 1, 0x10); // Argument
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
@ -157,132 +72,10 @@ fn ZP0()
assert_eq!(1, cpu.check_flag(Flags::C)); assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z)); assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N)); assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x10 with 0x10
bus.write(addr, 0xC5); // CMP - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x05);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x10 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
} }
//////////////////////////////////////////////////////////////////////////////
/// ABS ABS ABS ABS ABS ABS ABS ABS ABS
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn ABS() fn greater_than()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -293,69 +86,13 @@ fn ABS()
// Set the program counter address // Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010A, 0x05);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xCD); // CMP - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010A, 0x10);
// Program to compare 0x10 and 0x10
bus.write(addr, 0xCD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
/////////////////////// ///////////////////////
// Parameter is greater than A reg // Parameter is greater than A reg
// Manually put 0x10 into memory // Program to compare 0x05 with 0x10
bus.write(0x010A, 0x10); bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x10); // Argument
// Program to compare 0x05 and 0x10
bus.write(addr, 0xCD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
@ -366,202 +103,6 @@ fn ABS()
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ABX ABX ABX ABX ABX ABX ABX ABX ABX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x05);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ABY ABY ABY ABY ABY ABY ABY ABY ABY
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x05);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1 // C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C)); assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z)); assert_eq!(0, cpu.check_flag(Flags::Z));

@ -1,207 +0,0 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x49); // EOR - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x45); // EOR - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x55); // EOR - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x03);
// AND #3
bus.write(addr, 0x4D); // EOR - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
//cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x03 into memory
bus.write(0x010C, 0x03);
// EOR $10B
bus.write(addr, 0x5D); // EOR - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x59); // EOR - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}

@ -1,227 +0,0 @@
#![allow(dead_code, non_snake_case)]
// mod test_bus;
// #[cfg(test)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// ORA #2
bus.write(addr, 0x09); // ORA - Immediate mode
bus.write(addr + 1, 0x02); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x05); // ORA - Zero Page mode
bus.write(addr +1, 0x0A); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x15); // ORA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010A, 0x02);
// ORA #2
bus.write(addr, 0x0D); // ORA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
// cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x1D); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x19); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}

@ -2,14 +2,11 @@
#![allow(dead_code, non_snake_case)] #![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus; use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers}; use crate::r6502::{R6502, Bus, Registers, Flags};
//////////////////////////////////////////////////////////////////////////////
/// IMM IMM IMM IMM IMM IMM IMM IMM IMM
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn IMM() fn basic()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -28,61 +25,21 @@ fn IMM()
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
// manually setup the cpu registers // manually setup the cpu state
cpu.set_flag(Flags::C);
cpu.debug_set_reg(Registers::A, 0x0A); cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x04 in the A register? // Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A)); assert_eq!(0x04, cpu.debug_get_reg(Registers::A), "wrong answer");
assert_eq!(1, cpu.check_flag(Flags::C), "Carry bit should be set");
assert_eq!(0, cpu.check_flag(Flags::V), "Overflow bit should not be set");
} }
//////////////////////////////////////////////////////////////////////////////
/// ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x000A, 0x06);
// Program to
bus.write(addr, 0xE5); // SBC - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn ZPX() fn with_carry()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -94,34 +51,28 @@ fn ZPX()
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page // Program to subtract 0x09 from 0x08
bus.write(0x000A, 0x06); bus.write(addr, 0xE9); // SBC - Immediate mode
bus.write(addr + 1, 0x09); // Argument
// Program to
bus.write(addr, 0xF5); // - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
// manually setup the cpu registers // manually setup the cpu state
cpu.debug_set_reg(Registers::X, 0x06); cpu.set_flag(Flags::C);
cpu.debug_set_reg(Registers::A, 0x0A); cpu.debug_set_reg(Registers::A, 0x08);
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x04 in the A register? // Is -1 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A)); assert_eq!(0xFF as u16, cpu.debug_get_reg(Registers::A), "Wrong answer");
assert_eq!(0, cpu.check_flag(Flags::C), "Carry bit should not be set");
assert_eq!(0, cpu.check_flag(Flags::V), "Overflow bit should not be set");
} }
//////////////////////////////////////////////////////////////////////////////
/// ABS ABS ABS ABS ABS ABS ABS ABS ABS
//////////////////////////////////////////////////////////////////////////////
#[test] #[test]
fn ABS() fn with_overflow()
{ {
let mut cpu = R6502::new(); let mut cpu = R6502::new();
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -133,101 +84,22 @@ fn ABS()
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page // Program to subtract 0x7E from 0xFB (-5 - 126)
bus.write(0x010A, 0x06); bus.write(addr, 0xE9); // SBC - Immediate mode
bus.write(addr + 1, 0x7E); // Argument
// Program to
bus.write(addr, 0xED); // SBC - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu // Restart cpu
cpu.reset(&mut bus); cpu.reset(&mut bus);
cpu.debug_set_reg(Registers::A, 0x0A); // manually setup the cpu state
cpu.set_flag(Flags::C);
cpu.debug_set_reg(Registers::A, 0xFB);
// Clock the cpu to run the program (Clock essentially runs one full instruction) // Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus); cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
assert_eq!(0x7D, cpu.debug_get_reg(Registers::A), "Wrong answer");
////////////////////////////////////////////////////////////////////////////// assert_eq!(1, cpu.check_flag(Flags::C), "Carry bit should be set");
/// ABX ABX ABX ABX ABX ABX ABX ABX ABX assert_eq!(1, cpu.check_flag(Flags::V), "Overflow bit should be set");
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x010B, 0x06);
// Program to
bus.write(addr, 0xFD); // SBC - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
} }
//////////////////////////////////////////////////////////////////////////////
/// ABY ABY ABY ABY ABY ABY ABY ABY ABY
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x06);
// Program to
bus.write(addr, 0xF9); // - Absolute, Y mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}

@ -1,185 +0,0 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
//bus.write(0x000B, 0x0A);
// STA $0A
bus.write(addr, 0x85); // STA - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x0A?
assert_eq!(0x0F, bus.read(0x0A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// STA
bus.write(addr, 0x95); // STA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x0A?
assert_eq!(0x0F, bus.read(0x0A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010A, 0x02);
// STA
bus.write(addr, 0x8D); // STA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
// cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010A?
assert_eq!(0x0F, bus.read(0x010A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// STA
bus.write(addr, 0x9D); // STA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010B?
assert_eq!(0x0F, bus.read(0x010B));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// STA
bus.write(addr, 0x99); // STA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010B?
assert_eq!(0x0F, bus.read(0x010B));
}

@ -1,24 +1,175 @@
#[cfg(test)] #![allow(dead_code, non_snake_case)]
mod ORA;
#[cfg(test)] use crate::tests::test_bus::RAMBus;
mod AND; use crate::r6502::{R6502, Bus, Registers};
#[cfg(test)] /////////////////////////////////////////////////////////////////////
mod EOR; // GROUP ONE
/////////////////////////////////////////////////////////////////////
#[test]
fn ORA()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// ORA #2
bus.write(addr, 0x09); // ORA - Immediate mode
bus.write(addr + 1, 0x02); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[cfg(test)] #[cfg(test)]
mod ADC; mod ADC;
#[cfg(test)] #[test]
mod LDA; fn AND()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
#[cfg(test)] // program address
mod STA; let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x29); // AND - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn EOR()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x49); // EOR - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA9); // LDA - Immediate mode
bus.write(addr + 1, 0x08); // Argument
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn STA()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// STA $0A
bus.write(addr, 0x85); // STA - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x0A?
assert_eq!(0x0F, bus.read(0x0A));
}
#[cfg(test)] #[cfg(test)]
mod CMP; mod CMP;
#[cfg(test)] #[cfg(test)]
mod SBC; mod SBC;
/////////////////////////////////////////////////////////////////////
// GROUP TWO
/////////////////////////////////////////////////////////////////////
// TODO: TEST ASL
Loading…
Cancel
Save