vram writes, reads, auto increments and clear vblank nmi flag when read

This commit is contained in:
2023-07-05 23:13:14 -05:00
parent a82c554b25
commit e7a40db745
10 changed files with 302 additions and 176 deletions
+55 -55
View File
@@ -6,28 +6,28 @@ pub fn immediate(pc_addr: u32) -> u32 {
}
/// OPCODE addr
pub fn absolute(bus: &Bus, pc_addr: u32) -> u32 {
pub fn absolute(bus: &mut Bus, pc_addr: u32) -> u32 {
(pc_addr & 0xFF0000) |
(bus.read(pc_addr + 1) as u32) |
((bus.read(pc_addr + 2) as u32) << 8)
}
/// OPCODE (addr)
pub fn absolute_indirect(bus: &Bus, pc_addr: u32) -> u32 {
pub fn absolute_indirect(bus: &mut Bus, pc_addr: u32) -> u32 {
let addr = absolute(bus, pc_addr);
let dbr = pc_addr & 0xFF0000;
dbr | ((bus.read(addr) as u32) << 8) | (bus.read(addr + 1) as u32)
}
/// OPCODE long
pub fn absolute_long(bus: &Bus, pc_addr: u32) -> u32 {
pub fn absolute_long(bus: &mut Bus, pc_addr: u32) -> u32 {
(bus.read(pc_addr + 1) as u32) |
((bus.read(pc_addr + 2) as u32) << 8) |
((bus.read(pc_addr + 3) as u32) << 16)
}
/// OPCODE (addr)
pub fn absolute_indirect_long(bus: &Bus, pc_addr: u32) -> u32 {
pub fn absolute_indirect_long(bus: &mut Bus, pc_addr: u32) -> u32 {
let addr = absolute(bus, pc_addr);
((bus.read(addr) as u32) << 16) |
((bus.read(addr + 1) as u32) << 8) |
@@ -35,19 +35,19 @@ pub fn absolute_indirect_long(bus: &Bus, pc_addr: u32) -> u32 {
}
/// OPCODE dp
pub fn direct_page(bus: &Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
pub fn direct_page(bus: &mut Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
(bus.read(pc_addr + 1) as u32) + direct_page_register as u32
}
/// OPCODE (dp)
pub fn direct_page_indirect(bus: &Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
pub fn direct_page_indirect(bus: &mut Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
let addr = direct_page(bus, pc_addr, direct_page_register);
let dbr = pc_addr & 0xFF0000;
dbr | ((bus.read(addr) as u32) << 8) | (bus.read(addr + 1) as u32)
}
/// OPCODE [dp]
pub fn direct_page_indirect_long(bus: &Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
pub fn direct_page_indirect_long(bus: &mut Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
let addr = direct_page(bus, pc_addr, direct_page_register);
((bus.read(addr) as u32) << 16) |
((bus.read(addr + 1) as u32) << 8) |
@@ -56,12 +56,12 @@ pub fn direct_page_indirect_long(bus: &Bus, pc_addr: u32, direct_page_register:
/// OPCODE addr,X
/// OPCODE addr,Y
pub fn absolute_indexed(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
pub fn absolute_indexed(bus: &mut Bus, pc_addr: u32, xy: u16) -> u32 {
absolute(bus, pc_addr) + (xy as u32)
}
/// OPCODE (addr)
pub fn absolute_indexed_indirect(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
pub fn absolute_indexed_indirect(bus: &mut Bus, pc_addr: u32, xy: u16) -> u32 {
let addr = absolute_indexed(bus, pc_addr, xy);
let dbr = pc_addr & 0xFF0000;
dbr | ((bus.read(addr) as u32) << 8) | (bus.read(addr + 1) as u32)
@@ -70,42 +70,42 @@ pub fn absolute_indexed_indirect(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
/// OPCODE long,X
/// OPCODE long,Y
pub fn absolute_long_indexed(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
pub fn absolute_long_indexed(bus: &mut Bus, pc_addr: u32, xy: u16) -> u32 {
absolute_long(bus, pc_addr) + (xy as u32)
}
/// OPCODE dp,X
/// OPCODE dp,Y
pub fn direct_page_indexed(bus: &Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
pub fn direct_page_indexed(bus: &mut Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
direct_page(bus, pc_addr, direct_page_register) + (xy as u32)
}
/// OPCODE (dp,X)
/// OPCODE (dp,Y)
pub fn direct_page_indexed_indirect(bus: &Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
pub fn direct_page_indexed_indirect(bus: &mut Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
direct_page_indirect(bus, pc_addr, direct_page_register.wrapping_add(xy))
}
/// OPCODE (dp),X
/// OPCODE (dp),Y
pub fn direct_page_indirect_indexed(bus: &Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
pub fn direct_page_indirect_indexed(bus: &mut Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
direct_page_indirect(bus, pc_addr, direct_page_register) + (xy as u32)
}
/// OPCODE [dp],X
/// OPCODE [dp],Y
pub fn direct_page_indirect_long_indexed(bus: &Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
pub fn direct_page_indirect_long_indexed(bus: &mut Bus, pc_addr: u32, direct_page_register: u16, xy: u16) -> u32 {
direct_page_indirect_long(bus, pc_addr, direct_page_register) + (xy as u32)
}
/// OPCODE sr,S
pub fn stack_relative(bus: &Bus, pc_addr: u32, stack_pointer: u16) -> u32 {
pub fn stack_relative(bus: &mut Bus, pc_addr: u32, stack_pointer: u16) -> u32 {
absolute_indexed(bus, pc_addr, stack_pointer)
}
/// OPCODE (sr,S),X
/// OPCODE (sr,S),Y
pub fn stack_relative_indirect_indexed(bus: &Bus, pc_addr: u32, stack_pointer: u16, xy: u16) -> u32 {
pub fn stack_relative_indirect_indexed(bus: &mut Bus, pc_addr: u32, stack_pointer: u16, xy: u16) -> u32 {
absolute_indexed(bus, pc_addr, stack_pointer) + (xy as u32)
}
@@ -137,7 +137,7 @@ pub enum AddressingMode {
}
impl AddressingMode {
pub fn effective_address(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u32 {
pub fn effective_address(self, bus: &mut Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u32 {
use IndexRegister::X as X;
// TODO: maybe use impl Immediate {pub fn effective_address} to prevent this match statement?
match self {
@@ -162,12 +162,12 @@ impl AddressingMode {
}
}
pub fn value_8bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u8 {
pub fn value_8bit(self, bus: &mut Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u8 {
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, x, y);
return bus.read(address);
}
pub fn value_16bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u16 {
pub fn value_16bit(self, bus: &mut Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u16 {
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, x, y);
return (bus.read(address) as u16) | ((bus.read(address + 1) as u16) << 8);
}
@@ -200,13 +200,13 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(absolute(&bus, pc_addr), 0x000201);
assert_eq!(absolute(&mut bus, pc_addr), 0x000201);
let mut bus = Bus::new();
let pc_addr = 0x7F0000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(absolute(&bus, pc_addr), 0x7F0201);
assert_eq!(absolute(&mut bus, pc_addr), 0x7F0201);
}
#[test]
@@ -217,21 +217,21 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, addr);
bus.write(addr as u32, 0x02);
bus.write((addr + 1) as u32, 0x01);
assert_eq!(absolute_indirect(&bus, pc_addr), 0x000201);
assert_eq!(absolute_indirect(&mut bus, pc_addr), 0x000201);
let pc_addr = 0x7E0010;
let addr = 0x55;
bus.write(pc_addr + 1, addr);
bus.write(addr as u32, 0x02);
bus.write((addr + 1) as u32, 0x01);
assert_eq!(absolute_indirect(&bus, pc_addr), 0x7E0201);
assert_eq!(absolute_indirect(&mut bus, pc_addr), 0x7E0201);
let pc_addr = 0x7E0010;
let addr = 0x55;
bus.write(pc_addr + 1, addr);
bus.write(addr as u32, 0x02);
bus.write((addr + 1) as u32, 0x01);
assert_eq!(absolute_indirect(&bus, pc_addr), 0x7E0201);
assert_eq!(absolute_indirect(&mut bus, pc_addr), 0x7E0201);
}
#[test]
@@ -241,14 +241,14 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
bus.write(pc_addr + 3, 0x03);
assert_eq!(absolute_long(&bus, pc_addr), 0x030201);
assert_eq!(absolute_long(&mut bus, pc_addr), 0x030201);
let mut bus = Bus::new();
let pc_addr = 0x7E0010;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
bus.write(pc_addr + 3, 0x03);
assert_eq!(absolute_long(&bus, pc_addr), 0x030201);
assert_eq!(absolute_long(&mut bus, pc_addr), 0x030201);
}
#[test]
@@ -260,7 +260,7 @@ mod addressing_modes_tests {
bus.write(addr as u32, 0x03);
bus.write((addr + 1) as u32, 0x02);
bus.write((addr + 2) as u32, 0x01);
assert_eq!(absolute_indirect_long(&bus, pc_addr), 0x030201);
assert_eq!(absolute_indirect_long(&mut bus, pc_addr), 0x030201);
}
@@ -270,11 +270,11 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
assert_eq!(direct_page(&bus, pc_addr, 0x00), 0x000055);
assert_eq!(direct_page(&mut bus, pc_addr, 0x00), 0x000055);
let dp = 0x55;
bus.write(pc_addr + 1, dp);
assert_eq!(direct_page(&bus, pc_addr, 0x01), 0x000056);
assert_eq!(direct_page(&mut bus, pc_addr, 0x01), 0x000056);
}
#[test]
@@ -285,21 +285,21 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, dp);
bus.write(dp as u32, 0x02);
bus.write((dp + 1) as u32, 0x01);
assert_eq!(direct_page_indirect(&bus, pc_addr, 0x00), 0x000201);
assert_eq!(direct_page_indirect(&mut bus, pc_addr, 0x00), 0x000201);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write(dp as u32, 0x02);
bus.write((dp + 1) as u32, 0x01);
assert_eq!(direct_page_indirect(&bus, pc_addr, 0x00), 0x7E0201);
assert_eq!(direct_page_indirect(&mut bus, pc_addr, 0x00), 0x7E0201);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indirect(&bus, pc_addr, 0x01), 0x7E0201);
assert_eq!(direct_page_indirect(&mut bus, pc_addr, 0x01), 0x7E0201);
}
#[test]
@@ -311,7 +311,7 @@ mod addressing_modes_tests {
bus.write(dp as u32, 0x03);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indirect_long(&bus, pc_addr, 0x00), 0x030201);
assert_eq!(direct_page_indirect_long(&mut bus, pc_addr, 0x00), 0x030201);
let mut bus = Bus::new();
let pc_addr = 0x000000;
@@ -320,7 +320,7 @@ mod addressing_modes_tests {
bus.write((dp + 1) as u32, 0x03);
bus.write((dp + 2) as u32, 0x02);
bus.write((dp + 3) as u32, 0x01);
assert_eq!(direct_page_indirect_long(&bus, pc_addr, 0x01), 0x030201);
assert_eq!(direct_page_indirect_long(&mut bus, pc_addr, 0x01), 0x030201);
}
#[test]
@@ -329,13 +329,13 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(absolute_indexed(&bus, pc_addr, 0x02), 0x000203);
assert_eq!(absolute_indexed(&mut bus, pc_addr, 0x02), 0x000203);
let mut bus = Bus::new();
let pc_addr = 0x7F0000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(absolute_indexed(&bus, pc_addr, 0x02), 0x7F0203);
assert_eq!(absolute_indexed(&mut bus, pc_addr, 0x02), 0x7F0203);
}
#[test]
@@ -346,7 +346,7 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, addr);
bus.write(addr as u32, 0x02);
bus.write((addr + 1) as u32, 0x01);
assert_eq!(absolute_indexed_indirect(&bus, pc_addr, 0), 0x000201);
assert_eq!(absolute_indexed_indirect(&mut bus, pc_addr, 0), 0x000201);
}
#[test]
@@ -356,14 +356,14 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
bus.write(pc_addr + 3, 0x03);
assert_eq!(absolute_long_indexed(&bus, pc_addr, 0x02), 0x030203);
assert_eq!(absolute_long_indexed(&mut bus, pc_addr, 0x02), 0x030203);
let mut bus = Bus::new();
let pc_addr = 0x7E0010;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
bus.write(pc_addr + 3, 0x03);
assert_eq!(absolute_long_indexed(&bus, pc_addr, 0x02), 0x030203);
assert_eq!(absolute_long_indexed(&mut bus, pc_addr, 0x02), 0x030203);
}
#[test]
@@ -372,11 +372,11 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
assert_eq!(direct_page_indexed(&bus, pc_addr, 0x00, 0x01), 0x000056);
assert_eq!(direct_page_indexed(&mut bus, pc_addr, 0x00, 0x01), 0x000056);
let dp = 0x55;
bus.write(pc_addr + 1, dp);
assert_eq!(direct_page_indexed(&bus, pc_addr, 0x01, 0x01), 0x000057);
assert_eq!(direct_page_indexed(&mut bus, pc_addr, 0x01, 0x01), 0x000057);
}
#[test]
@@ -387,21 +387,21 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, dp);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indexed_indirect(&bus, pc_addr, 0x00, 0x01), 0x000201);
assert_eq!(direct_page_indexed_indirect(&mut bus, pc_addr, 0x00, 0x01), 0x000201);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indexed_indirect(&bus, pc_addr, 0x00, 0x01), 0x7E0201);
assert_eq!(direct_page_indexed_indirect(&mut bus, pc_addr, 0x00, 0x01), 0x7E0201);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write((dp + 2) as u32, 0x02);
bus.write((dp + 3) as u32, 0x01);
assert_eq!(direct_page_indexed_indirect(&bus, pc_addr, 0x01, 0x01), 0x7E0201);
assert_eq!(direct_page_indexed_indirect(&mut bus, pc_addr, 0x01, 0x01), 0x7E0201);
}
#[test]
@@ -412,21 +412,21 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, dp);
bus.write(dp as u32, 0x02);
bus.write((dp + 1) as u32, 0x01);
assert_eq!(direct_page_indirect_indexed(&bus, pc_addr, 0x00, 0x01), 0x000202);
assert_eq!(direct_page_indirect_indexed(&mut bus, pc_addr, 0x00, 0x01), 0x000202);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write(dp as u32, 0x02);
bus.write((dp + 1) as u32, 0x01);
assert_eq!(direct_page_indirect_indexed(&bus, pc_addr, 0x00, 0x01), 0x7E0202);
assert_eq!(direct_page_indirect_indexed(&mut bus, pc_addr, 0x00, 0x01), 0x7E0202);
let pc_addr = 0x7E0010;
let dp = 0x55;
bus.write(pc_addr + 1, dp);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indirect_indexed(&bus, pc_addr, 0x01, 0x01), 0x7E0202);
assert_eq!(direct_page_indirect_indexed(&mut bus, pc_addr, 0x01, 0x01), 0x7E0202);
}
#[test]
@@ -438,7 +438,7 @@ mod addressing_modes_tests {
bus.write(dp as u32, 0x03);
bus.write((dp + 1) as u32, 0x02);
bus.write((dp + 2) as u32, 0x01);
assert_eq!(direct_page_indirect_long_indexed(&bus, pc_addr, 0x00, 0x02), 0x030203);
assert_eq!(direct_page_indirect_long_indexed(&mut bus, pc_addr, 0x00, 0x02), 0x030203);
let mut bus = Bus::new();
let pc_addr = 0x000000;
@@ -447,7 +447,7 @@ mod addressing_modes_tests {
bus.write((dp + 1) as u32, 0x03);
bus.write((dp + 2) as u32, 0x02);
bus.write((dp + 3) as u32, 0x01);
assert_eq!(direct_page_indirect_long_indexed(&bus, pc_addr, 0x01, 0x02), 0x030203);
assert_eq!(direct_page_indirect_long_indexed(&mut bus, pc_addr, 0x01, 0x02), 0x030203);
}
#[test]
@@ -456,13 +456,13 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(stack_relative(&bus, pc_addr, 0x02), 0x000203);
assert_eq!(stack_relative(&mut bus, pc_addr, 0x02), 0x000203);
let mut bus = Bus::new();
let pc_addr = 0x7F0000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(stack_relative(&bus, pc_addr, 0x02), 0x7F0203);
assert_eq!(stack_relative(&mut bus, pc_addr, 0x02), 0x7F0203);
}
#[test]
@@ -471,13 +471,13 @@ mod addressing_modes_tests {
let pc_addr = 0x000000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(stack_relative_indirect_indexed(&bus, pc_addr, 0x02, 0x02), 0x000205);
assert_eq!(stack_relative_indirect_indexed(&mut bus, pc_addr, 0x02, 0x02), 0x000205);
let mut bus = Bus::new();
let pc_addr = 0x7F0000;
bus.write(pc_addr + 1, 0x01);
bus.write(pc_addr + 2, 0x02);
assert_eq!(stack_relative_indirect_indexed(&bus, pc_addr, 0x02, 0x02), 0x7F0205);
assert_eq!(stack_relative_indirect_indexed(&mut bus, pc_addr, 0x02, 0x02), 0x7F0205);
}
#[test]
@@ -487,7 +487,7 @@ mod addressing_modes_tests {
bus.write(pc_addr + 1, 0x20);
bus.write(pc_addr + 2, 0x10);
bus.write(0x001020, 0xFE);
let val = AddressingMode::Absolute.value_8bit(&bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
let val = AddressingMode::Absolute.value_8bit(&mut bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
assert_eq!(val, 0xFE);
let mut bus = Bus::new();
@@ -496,7 +496,7 @@ mod addressing_modes_tests {
bus.write(pc_addr + 2, 0x10);
bus.write(0x001020, 0xFF);
bus.write(0x001021, 0xEE);
let val = AddressingMode::Absolute.value_16bit(&bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
let val = AddressingMode::Absolute.value_16bit(&mut bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
assert_eq!(val, 0xEEFF);
}
}