Fix 'oops cycle' timing, to pass timing test rom
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 25s
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 25s
This commit is contained in:
118
src/lib.rs
118
src/lib.rs
@@ -182,6 +182,12 @@ pub enum ClockState {
|
|||||||
count: u8,
|
count: u8,
|
||||||
addr: u16,
|
addr: u16,
|
||||||
},
|
},
|
||||||
|
Oops {
|
||||||
|
instruction: u8,
|
||||||
|
ops: [u8; 5],
|
||||||
|
count: u8,
|
||||||
|
addr: u16,
|
||||||
|
},
|
||||||
HoldNmi {
|
HoldNmi {
|
||||||
cycles: u8,
|
cycles: u8,
|
||||||
},
|
},
|
||||||
@@ -224,6 +230,17 @@ impl std::fmt::Debug for ClockState {
|
|||||||
ClockState::HoldIrq { cycles } => {
|
ClockState::HoldIrq { cycles } => {
|
||||||
f.debug_struct("HoldIrq").field("cycles", cycles).finish()
|
f.debug_struct("HoldIrq").field("cycles", cycles).finish()
|
||||||
}
|
}
|
||||||
|
ClockState::Oops {
|
||||||
|
instruction,
|
||||||
|
ops,
|
||||||
|
count,
|
||||||
|
addr,
|
||||||
|
} => f
|
||||||
|
.debug_struct("Oops")
|
||||||
|
.field("instruction", instruction)
|
||||||
|
.field("addr", addr)
|
||||||
|
.field("ops", &&ops[..*count as usize])
|
||||||
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,6 +249,7 @@ enum ExecState {
|
|||||||
Done,
|
Done,
|
||||||
MoreParams,
|
MoreParams,
|
||||||
Hold(u8),
|
Hold(u8),
|
||||||
|
Oops,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum CPUMMRegisters {
|
pub enum CPUMMRegisters {
|
||||||
@@ -436,7 +454,14 @@ impl NES {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if more bytes are needed
|
/// Returns true if more bytes are needed
|
||||||
fn exec_instruction(&mut self, ins: u8, mut params: &[u8], held: bool, addr: u16) -> ExecState {
|
fn exec_instruction(
|
||||||
|
&mut self,
|
||||||
|
ins: u8,
|
||||||
|
mut params: &[u8],
|
||||||
|
held: bool,
|
||||||
|
oops: bool,
|
||||||
|
addr: u16,
|
||||||
|
) -> ExecState {
|
||||||
macro_rules! inst {
|
macro_rules! inst {
|
||||||
($val:expr, $hold:expr, |$($name:pat_param),*| $eval:expr) => {{
|
($val:expr, $hold:expr, |$($name:pat_param),*| $eval:expr) => {{
|
||||||
let hold_time: u8 = ($hold).into();
|
let hold_time: u8 = ($hold).into();
|
||||||
@@ -588,6 +613,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xBD => inst!("LDA abs,x", 1, |low, high| {
|
0xBD => inst!("LDA abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a = self.read_abs_x(low, high);
|
self.cpu.a = self.read_abs_x(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -599,6 +625,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xB9 => inst!("LDA abs,y", 1, |low, high| {
|
0xB9 => inst!("LDA abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a = self.read_abs_y(low, high);
|
self.cpu.a = self.read_abs_y(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -620,6 +647,7 @@ impl NES {
|
|||||||
0xB1 => inst!("LDA (ind),y", 3, |off| {
|
0xB1 => inst!("LDA (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
self.cpu.a = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -655,6 +683,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xBE => inst!("LDX abs,y", 1, |low, high| {
|
0xBE => inst!("LDX abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.x = self.read_abs_y(low, high);
|
self.cpu.x = self.read_abs_y(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.x == 0);
|
self.cpu.status.set_zero(self.cpu.x == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.x & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.x & 0x80 == 0x80);
|
||||||
@@ -695,6 +724,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xBC => inst!("LDX abs,x", 1, |low, high| {
|
0xBC => inst!("LDX abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.y = self.read_abs_x(low, high);
|
self.cpu.y = self.read_abs_x(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.y == 0);
|
self.cpu.status.set_zero(self.cpu.y == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.y & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.y & 0x80 == 0x80);
|
||||||
@@ -956,6 +986,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xDD => inst!("CMP abs,x", 1, |low, high| {
|
0xDD => inst!("CMP abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_x(low, high);
|
let val = self.read_abs_x(low, high);
|
||||||
let v = self.cpu.a.wrapping_sub(val);
|
let v = self.cpu.a.wrapping_sub(val);
|
||||||
self.cpu.status.set_zero(v == 0);
|
self.cpu.status.set_zero(v == 0);
|
||||||
@@ -971,6 +1002,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xD9 => inst!("CMP abs,y", 1, |low, high| {
|
0xD9 => inst!("CMP abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_y(low, high);
|
let val = self.read_abs_y(low, high);
|
||||||
let v = self.cpu.a.wrapping_sub(val);
|
let v = self.cpu.a.wrapping_sub(val);
|
||||||
self.cpu.status.set_zero(v == 0);
|
self.cpu.status.set_zero(v == 0);
|
||||||
@@ -1003,9 +1035,9 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xD1 => inst!("CMP (ind),y", 3, |off| {
|
0xD1 => inst!("CMP (ind),y", 3, |off| {
|
||||||
// TODO: iymode
|
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_y(low, high);
|
let val = self.read_abs_y(low, high);
|
||||||
let v = self.cpu.a.wrapping_sub(val);
|
let v = self.cpu.a.wrapping_sub(val);
|
||||||
self.cpu.status.set_zero(v == 0);
|
self.cpu.status.set_zero(v == 0);
|
||||||
@@ -1163,6 +1195,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x7D => inst!("ADC abs,x", 1, |low, high| {
|
0x7D => inst!("ADC abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_x(low, high);
|
let val = self.read_abs_x(low, high);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1181,6 +1214,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x79 => inst!("ADC abs,y", 1, |low, high| {
|
0x79 => inst!("ADC abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_y(low, high);
|
let val = self.read_abs_y(low, high);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1221,6 +1255,7 @@ impl NES {
|
|||||||
0x71 => inst!("ADC (ind),y", 3, |off| {
|
0x71 => inst!("ADC (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
let val = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1295,6 +1330,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xFD => inst!("SBC abs,x", 1, |low, high| {
|
0xFD => inst!("SBC abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_x(low, high);
|
let val = self.read_abs_x(low, high);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1313,6 +1349,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0xF9 => inst!("SBC abs,y", 1, |low, high| {
|
0xF9 => inst!("SBC abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read_abs_y(low, high);
|
let val = self.read_abs_y(low, high);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1353,6 +1390,7 @@ impl NES {
|
|||||||
0xF1 => inst!("SBC (ind),y", 3, |off| {
|
0xF1 => inst!("SBC (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
let val = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
let val = self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
let (a, carry_1) = self.cpu.a.overflowing_add(!val);
|
||||||
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
let (a, carry_2) = a.overflowing_add(self.cpu.status.carry().into());
|
||||||
@@ -1502,7 +1540,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x1D => inst!("ORA abs,x", 1, |low, high| {
|
0x1D => inst!("ORA abs,x", 1, |low, high| {
|
||||||
// TODO: page crossing
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a |= self.read_abs_x(low, high);
|
self.cpu.a |= self.read_abs_x(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1514,6 +1552,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x19 => inst!("ORA abs,y", 1, |low, high| {
|
0x19 => inst!("ORA abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a |= self.read_abs_y(low, high);
|
self.cpu.a |= self.read_abs_y(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1540,6 +1579,10 @@ impl NES {
|
|||||||
0x11 => inst!("ORA (ind),y", 3, |off| {
|
0x11 => inst!("ORA (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() {
|
||||||
|
return ExecState::Oops;
|
||||||
|
}
|
||||||
self.cpu.a |= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
self.cpu.a |= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1580,6 +1623,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x3D => inst!("AND abs,x", 1, |low, high| {
|
0x3D => inst!("AND abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a &= self.read_abs_x(low, high);
|
self.cpu.a &= self.read_abs_x(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1591,6 +1635,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x39 => inst!("AND abs,y", 1, |low, high| {
|
0x39 => inst!("AND abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a &= self.read_abs_y(low, high);
|
self.cpu.a &= self.read_abs_y(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1617,6 +1662,7 @@ impl NES {
|
|||||||
0x31 => inst!("AND (ind),y", 3, |off| {
|
0x31 => inst!("AND (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a &= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
self.cpu.a &= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1657,6 +1703,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x5D => inst!("EOR abs,x", 1, |low, high| {
|
0x5D => inst!("EOR abs,x", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.x).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a ^= self.read_abs_x(low, high);
|
self.cpu.a ^= self.read_abs_x(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1668,6 +1715,7 @@ impl NES {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
0x59 => inst!("EOR abs,y", 1, |low, high| {
|
0x59 => inst!("EOR abs,y", 1, |low, high| {
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a ^= self.read_abs_y(low, high);
|
self.cpu.a ^= self.read_abs_y(low, high);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1694,6 +1742,7 @@ impl NES {
|
|||||||
0x51 => inst!("EOR (ind),y", 3, |off| {
|
0x51 => inst!("EOR (ind),y", 3, |off| {
|
||||||
let low = self.read_abs(off, 0);
|
let low = self.read_abs(off, 0);
|
||||||
let high = self.read_abs(off.wrapping_add(1), 0);
|
let high = self.read_abs(off.wrapping_add(1), 0);
|
||||||
|
if !oops && low.checked_add(self.cpu.y).is_none() { return ExecState::Oops; }
|
||||||
self.cpu.a ^= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
self.cpu.a ^= self.read(u16::from_le_bytes([low, high]) + self.cpu.y as u16);
|
||||||
self.cpu.status.set_zero(self.cpu.a == 0);
|
self.cpu.status.set_zero(self.cpu.a == 0);
|
||||||
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
self.cpu.status.set_negative(self.cpu.a & 0x80 == 0x80);
|
||||||
@@ -1973,24 +2022,12 @@ impl NES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClockState::ReadInstruction => {
|
ClockState::ReadInstruction => {
|
||||||
// if self.cpu.nmi_pending {
|
|
||||||
// self.cpu.nmi_pending = false;
|
|
||||||
// writeln!(self.debug_log, "NMI detected").unwrap();
|
|
||||||
// ClockState::HoldNmi { cycles: 5 }
|
|
||||||
// } else if !self.cpu.status.interrupt_disable()
|
|
||||||
// && (self.ppu.irq_waiting() || self.apu.irq_waiting())
|
|
||||||
// {
|
|
||||||
// // TODO: handle proper irq detection
|
|
||||||
// writeln!(self.debug_log, "IRQ detected").unwrap();
|
|
||||||
// ClockState::HoldIrq { cycles: 6 }
|
|
||||||
// } else
|
|
||||||
{
|
|
||||||
let addr = self.cpu.pc;
|
let addr = self.cpu.pc;
|
||||||
let instruction = self.read(self.cpu.pc);
|
let instruction = self.read(self.cpu.pc);
|
||||||
if instruction != 0x02 {
|
if instruction != 0x02 {
|
||||||
self.cpu.pc = self.cpu.pc.wrapping_add(1);
|
self.cpu.pc = self.cpu.pc.wrapping_add(1);
|
||||||
}
|
}
|
||||||
match self.exec_instruction(instruction, &[], false, addr) {
|
match self.exec_instruction(instruction, &[], false, false, addr) {
|
||||||
ExecState::Done => ClockState::ReadInstruction,
|
ExecState::Done => ClockState::ReadInstruction,
|
||||||
ExecState::MoreParams => ClockState::ReadOperands {
|
ExecState::MoreParams => ClockState::ReadOperands {
|
||||||
instruction,
|
instruction,
|
||||||
@@ -2005,7 +2042,12 @@ impl NES {
|
|||||||
count: 0,
|
count: 0,
|
||||||
addr,
|
addr,
|
||||||
},
|
},
|
||||||
}
|
ExecState::Oops => ClockState::Oops {
|
||||||
|
instruction,
|
||||||
|
ops: [0u8; 5],
|
||||||
|
count: 0,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClockState::ReadOperands {
|
ClockState::ReadOperands {
|
||||||
@@ -2019,7 +2061,13 @@ impl NES {
|
|||||||
}
|
}
|
||||||
ops[count as usize] = self.read(self.cpu.pc);
|
ops[count as usize] = self.read(self.cpu.pc);
|
||||||
self.cpu.pc = self.cpu.pc.wrapping_add(1);
|
self.cpu.pc = self.cpu.pc.wrapping_add(1);
|
||||||
match self.exec_instruction(instruction, &ops[..count as usize + 1], false, addr) {
|
match self.exec_instruction(
|
||||||
|
instruction,
|
||||||
|
&ops[..count as usize + 1],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
addr,
|
||||||
|
) {
|
||||||
ExecState::Done => ClockState::ReadInstruction,
|
ExecState::Done => ClockState::ReadInstruction,
|
||||||
ExecState::MoreParams => ClockState::ReadOperands {
|
ExecState::MoreParams => ClockState::ReadOperands {
|
||||||
instruction,
|
instruction,
|
||||||
@@ -2034,6 +2082,12 @@ impl NES {
|
|||||||
count: count + 1,
|
count: count + 1,
|
||||||
addr,
|
addr,
|
||||||
},
|
},
|
||||||
|
ExecState::Oops => ClockState::Oops {
|
||||||
|
instruction,
|
||||||
|
ops,
|
||||||
|
count: count + 1,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClockState::Hold {
|
ClockState::Hold {
|
||||||
@@ -2044,15 +2098,24 @@ impl NES {
|
|||||||
addr,
|
addr,
|
||||||
} => {
|
} => {
|
||||||
if cycles == 0 {
|
if cycles == 0 {
|
||||||
match self.exec_instruction(instruction, &ops[..count as usize], true, addr) {
|
match self.exec_instruction(
|
||||||
|
instruction,
|
||||||
|
&ops[..count as usize],
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
addr,
|
||||||
|
) {
|
||||||
ExecState::Done => ClockState::ReadInstruction,
|
ExecState::Done => ClockState::ReadInstruction,
|
||||||
ExecState::MoreParams => ClockState::ReadOperands {
|
ExecState::MoreParams => {
|
||||||
|
panic!("Should never return MoreParams after holding")
|
||||||
|
}
|
||||||
|
ExecState::Hold(_) => panic!("Should never return Hold after holding"),
|
||||||
|
ExecState::Oops => ClockState::Oops {
|
||||||
instruction,
|
instruction,
|
||||||
ops,
|
ops,
|
||||||
count: count + 1,
|
count,
|
||||||
addr,
|
addr,
|
||||||
},
|
},
|
||||||
ExecState::Hold(_) => panic!("Should never return Hold after holding"),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ClockState::Hold {
|
ClockState::Hold {
|
||||||
@@ -2064,6 +2127,17 @@ impl NES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ClockState::Oops {
|
||||||
|
instruction,
|
||||||
|
ops,
|
||||||
|
count,
|
||||||
|
addr,
|
||||||
|
} => {
|
||||||
|
match self.exec_instruction(instruction, &ops[..count as usize], true, true, addr) {
|
||||||
|
ExecState::Done => ClockState::ReadInstruction,
|
||||||
|
_ => panic!("Must execute after oops"),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if self.cpu.clock_state == ClockState::ReadInstruction {
|
if self.cpu.clock_state == ClockState::ReadInstruction {
|
||||||
if self.cpu.nmi_pending {
|
if self.cpu.nmi_pending {
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ use tracing_subscriber::EnvFilter;
|
|||||||
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "ppu_fill_red.nes");
|
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "ppu_fill_red.nes");
|
||||||
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "ppu_fill_name_table.nes");
|
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "ppu_fill_name_table.nes");
|
||||||
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "int_nmi_exit_timing.nes");
|
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "int_nmi_exit_timing.nes");
|
||||||
const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
|
// const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
|
||||||
// const ROM_FILE: &str = "./cpu_timing_test.nes";
|
const ROM_FILE: &str = "./cpu_timing_test.nes";
|
||||||
|
|
||||||
extern crate nes_emu;
|
extern crate nes_emu;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user