Skip to content

Commit e73f2ce

Browse files
committed
make NES specific behavior configurable
1 parent ca636b7 commit e73f2ce

2 files changed

Lines changed: 63 additions & 15 deletions

File tree

src/cpu.rs

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ impl fmt::Display for Registers {
3636
f,
3737
"PC:{:04X} A:{:02X} X:{:02X} Y:{:02X} P:{:02X} S:{:02X}\nN|V|-|B|D|I|Z|C\n{}|{}|{}|{}|{}|{}|{}|{}",
3838
self.pc, self.a, self.x, self.y, self.p, self.s,
39-
if (self.p & (1 << 7)) != 0 { 1 } else {0},
40-
if (self.p & (1 << 6)) != 0 { 1 } else {0},
41-
if (self.p & (1 << 5)) != 0 { 1 } else {0},
42-
if (self.p & (1 << 4)) != 0 { 1 } else {0},
43-
if (self.p & (1 << 3)) != 0 { 1 } else {0},
44-
if (self.p & (1 << 2)) != 0 { 1 } else {0},
45-
if (self.p & (1 << 1)) != 0 { 1 } else {0},
46-
if (self.p & (1 << 0)) != 0 { 1 } else {0},
39+
if (self.p & (1 << 7)) != 0 { 1 } else { 0 },
40+
if (self.p & (1 << 6)) != 0 { 1 } else { 0 },
41+
if (self.p & (1 << 5)) != 0 { 1 } else { 0 },
42+
if (self.p & (1 << 4)) != 0 { 1 } else { 0 },
43+
if (self.p & (1 << 3)) != 0 { 1 } else { 0 },
44+
if (self.p & (1 << 2)) != 0 { 1 } else { 0 },
45+
if (self.p & (1 << 1)) != 0 { 1 } else { 0 },
46+
if (self.p & (1 << 0)) != 0 { 1 } else { 0 },
4747
)
4848
}
4949
}
@@ -137,7 +137,24 @@ enum Access {
137137
ReadModify,
138138
}
139139

140+
const NES_CPU_OPTIONS: CpuOptions = CpuOptions {
141+
ignore_decimal_bit: true,
142+
};
143+
144+
pub struct CpuOptions {
145+
ignore_decimal_bit: bool,
146+
}
147+
148+
impl Default for CpuOptions {
149+
fn default() -> Self {
150+
Self {
151+
ignore_decimal_bit: false,
152+
}
153+
}
154+
}
155+
140156
pub struct Cpu {
157+
options: CpuOptions,
141158
registers: Registers,
142159
memory: MemoryMap,
143160
clock_speed: u32,
@@ -341,9 +358,26 @@ impl Cpu {
341358

342359
let v = (!(a ^ m) & (a ^ result) & 0x80) != 0;
343360

344-
self.registers.update_carry_bit(sum > 0xFF);
345-
self.registers.update_overflow_bit(v);
346-
self.registers.update_a(result);
361+
if !self.options.ignore_decimal_bit && self.registers.get_decimal_bit() {
362+
let mut adj = 0u16;
363+
if ((a & 0x0F) as u16 + (m & 0x0F) as u16 + c) > 9 {
364+
adj += 0x06;
365+
}
366+
if sum > 0x99 {
367+
adj += 0x60;
368+
}
369+
let bcd = result.wrapping_add(adj as u8);
370+
371+
let carry = sum > 0x99;
372+
373+
self.registers.update_carry_bit(carry);
374+
self.registers.update_overflow_bit(v);
375+
self.registers.update_a(bcd);
376+
} else {
377+
self.registers.update_carry_bit(sum > 0xFF);
378+
self.registers.update_overflow_bit(v);
379+
self.registers.update_a(result);
380+
}
347381
}
348382

349383
fn sbc(&mut self, m: u8) {
@@ -1257,8 +1291,18 @@ impl Cpu {
12571291
}
12581292

12591293
impl Cpu {
1260-
pub fn new(memory: MemoryMap, clock_speed: u32) -> Self {
1294+
pub fn new(options: CpuOptions, memory: MemoryMap, clock_speed: u32) -> Self {
1295+
Self {
1296+
options,
1297+
registers: Registers::new(memory.reset_vector()),
1298+
memory,
1299+
clock_speed,
1300+
}
1301+
}
1302+
1303+
pub fn with_nes_options(memory: MemoryMap, clock_speed: u32) -> Self {
12611304
Self {
1305+
options: NES_CPU_OPTIONS,
12621306
registers: Registers::new(memory.reset_vector()),
12631307
memory,
12641308
clock_speed,
@@ -1468,7 +1512,7 @@ impl Cpu {
14681512

14691513
#[cfg(test)]
14701514
mod test {
1471-
use crate::cpu::Cpu;
1515+
use crate::cpu::{Cpu, CpuOptions};
14721516
use crate::memory_map::MemoryMap;
14731517
use crate::nes_rom::NesRom;
14741518
use std::fs::File;
@@ -1478,14 +1522,18 @@ mod test {
14781522
fn nestest() {
14791523
let rom = NesRom::read_from_file("./vendor/nestest/nestest.nes").unwrap();
14801524
let memory_map = MemoryMap::new(rom);
1481-
let mut cpu = Cpu::new(memory_map, 1 << 16);
1525+
let mut cpu = Cpu::with_nes_options(memory_map, 1 << 16);
14821526
cpu.registers.pc = 0xC000;
14831527
cpu.registers.p = 0x24;
14841528
cpu.registers.s = 0xFD;
14851529

14861530
let reference_log = File::open("./vendor/nestest/nestest.log").unwrap();
14871531
let mut idx = 1;
14881532
for line in BufReader::new(reference_log).lines().map(|l| l.unwrap()) {
1533+
if idx == 5004 {
1534+
// first inofficial opcode (not currently supported)
1535+
break;
1536+
}
14891537
let state = format!(
14901538
"{:04X} A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X}",
14911539
cpu.registers.pc,

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn main() -> Result<(), anyhow::Error> {
1616
let memory_map = MemoryMap::new(rom);
1717
println!("Entry point: {:#X}", memory_map.reset_vector());
1818

19-
let mut cpu = Cpu::new(memory_map, 1 << 16);
19+
let mut cpu = Cpu::with_nes_options(memory_map, 1 << 16);
2020
cpu.run();
2121

2222
Ok(())

0 commit comments

Comments
 (0)