Minor refactors and bug fixes
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Has been cancelled

- Bit instruction now sets Z flag correctly
- DMA is no longer handled by cpu.rs
This commit is contained in:
2026-01-26 01:21:37 -06:00
parent f861f75b21
commit 7b76026ade
10 changed files with 379 additions and 166 deletions

View File

@@ -1,7 +1,7 @@
use std::fmt::Write;
use tracing::debug;
use crate::{debug::DebugLog, mem::CpuMem};
use crate::{Break, debug::DebugLog, mem::CpuMem};
bitfield::bitfield! {
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -634,7 +634,9 @@ impl Cpu {
if self.status.carry() {
let page = self.jmp_rel(off);
log!(" : - JMP ${:04X}", self.pc);
if page { return ExecState::PageCross };
if page {
return ExecState::PageCross;
};
}
}),
0xF0 => inst!("BEQ", self.status.zero(), |off| {
@@ -642,7 +644,9 @@ impl Cpu {
if self.status.zero() {
let page = self.jmp_rel(off);
log!(" : - JMP ${:04X}", self.pc);
if page { return ExecState::PageCross };
if page {
return ExecState::PageCross;
};
}
}),
0x30 => inst!("BMI", self.status.negative(), |off| {
@@ -650,7 +654,9 @@ impl Cpu {
if self.status.negative() {
let page = self.jmp_rel(off);
log!(" : - JMP ${:04X}", self.pc);
if page { return ExecState::PageCross };
if page {
return ExecState::PageCross;
};
}
}),
0xD0 => inst!("BNE", !self.status.zero(), |off| {
@@ -658,7 +664,9 @@ impl Cpu {
if !self.status.zero() {
let page = self.jmp_rel(off);
log!(" : - JMP ${:04X}", self.pc);
if page { return ExecState::PageCross };
if page {
return ExecState::PageCross;
};
}
}),
0x10 => inst!("BPL", !self.status.negative(), |off| {
@@ -666,7 +674,9 @@ impl Cpu {
if !self.status.negative() {
let page = self.jmp_rel(off);
log!(" : - JMP ${:04X}", self.pc);
if page { return ExecState::PageCross };
if page {
return ExecState::PageCross;
};
}
}),
0x4C => inst!("JMP abs", 0, |low, high| {
@@ -1509,14 +1519,14 @@ impl Cpu {
}),
0x24 => inst!("BIT zp", 1, |off| {
let val = self.read_abs(mem, off, 0);
self.status.set_zero(val == 0);
self.status.set_zero(val & self.a == 0);
self.status.set_overflow(val & 0x40 == 0x40);
self.status.set_negative(val & 0x80 == 0x80);
log!("{addr:04X}: BIT ${:02X} | {:02X}", off, val);
}),
0x2C => inst!("BIT abs", 1, |low, high| {
let val = self.read_abs(mem, low, high);
self.status.set_zero(val == 0);
self.status.set_zero(val & self.a == 0);
self.status.set_overflow(val & 0x40 == 0x40);
self.status.set_negative(val & 0x80 == 0x80);
log!("{addr:04X}: BIT ${:02X}{:02X} | {:02X}", high, low, val);
@@ -1723,7 +1733,7 @@ impl Cpu {
}
}
fn clock_cpu(&mut self, mem: &mut CpuMem<'_>, nmi: bool, irq: bool) {
pub fn clock_cpu(&mut self, mem: &mut CpuMem<'_>, nmi: bool, irq: bool, br: &Break) -> bool {
self.clock_state = match self.clock_state {
ClockState::HoldNmi { cycles } => {
if cycles == 0 {
@@ -1750,6 +1760,10 @@ impl Cpu {
}
}
ClockState::ReadInstruction => {
if br.cpu_exec {
println!("Returning early from clock_cpu");
return true;
}
let addr = self.pc;
let instruction = mem.read(self.pc);
if instruction != 0x02 {
@@ -1900,59 +1914,13 @@ impl Cpu {
}
// self.irq_pending = self.ppu.irq_waiting() || self.apu.irq_waiting();
self.irq_pending = irq;
false
}
pub fn cpu_cycle(
&mut self,
mem: &mut CpuMem<'_>,
dma: &mut DmaState,
nmi: bool,
irq: bool,
) {
match *dma {
DmaState::Passive => self.clock_cpu(mem, nmi, irq),
// TODO: Validate that this takes the correct number of cycles (513 or 514 cycles)
DmaState::Running {
cpu_addr,
rem,
read: Some(read),
} => {
mem.write(0x2004, read);
// self.ppu.write_reg(4, read);
debug!("OAM DMA write {:02X}", read);
if rem == 0 {
*dma = DmaState::Passive;
} else {
*dma = DmaState::Running {
cpu_addr: cpu_addr + 1,
rem: rem - 1,
read: None,
};
}
}
DmaState::Running {
cpu_addr,
rem,
read: None,
} => {
let read = mem.read(cpu_addr);
debug!("OAM DMA read {:04X} {:02X}", cpu_addr, read);
*dma = DmaState::Running {
cpu_addr,
rem,
read: Some(read),
};
}
}
// if [0x8031, 0x8014].contains(&self.cpu.pc) {
// self.dbg_int = true;
// }
}
pub fn cpu_cycle_update(&mut self) {
if !self.halted {
self.cycle += 1;
}
}
pub fn executed(&self) -> bool {
@@ -1978,6 +1946,7 @@ impl Cpu {
#[derive(Debug, Clone, Copy)]
pub enum DmaState {
Passive,
Idle(u16),
Running {
cpu_addr: u16,
rem: u8,
@@ -1995,6 +1964,56 @@ impl DmaState {
}
}
}
pub fn cycle(self, mem: &mut CpuMem<'_>, cpu: &mut Cpu) -> Option<Self> {
match self {
DmaState::Passive => None,
DmaState::Idle(cpu_addr) => Some(DmaState::Running {
cpu_addr,
rem: 0xFF,
read: None,
}),
DmaState::Running {
cpu_addr,
rem,
read: Some(read),
} => {
mem.write(0x2004, read);
// self.ppu.write_reg(4, read);
writeln!(&mut cpu.debug_log, "OAM DMA write {:02X}", read).unwrap();
if rem == 0 {
Some(DmaState::Passive)
} else {
Some(DmaState::Running {
cpu_addr: cpu_addr + 1,
rem: rem - 1,
read: None,
})
}
}
DmaState::Running {
cpu_addr,
rem,
read: None,
} => {
if cpu.cycle % 2 != 1 {
return Some(self);
}
let read = mem.read(cpu_addr);
writeln!(
&mut cpu.debug_log,
"OAM DMA read {:04X} {:02X}",
cpu_addr, read
)
.unwrap();
Some(DmaState::Running {
cpu_addr,
rem,
read: Some(read),
})
}
}
}
}
pub struct CycleResult {