Skip to content

Commit

Permalink
chore: PPU registers (cont)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanleiby committed Dec 10, 2024
1 parent 99d2c6c commit e5eb82f
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 86 deletions.
9 changes: 8 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bitflags = "2.6.0"
env_logger = "0.11.5"
log = "0.4.22"
rand = "0.8.5"
Expand Down
5 changes: 4 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ run:
lint:
cargo clippy --all --all-features --tests -- -D warnings

lint_watch:
git ls-files | entr just lint

lint_fix:
cargo clippy --all --all-features --tests --fix

Expand All @@ -14,7 +17,7 @@ test:
cargo test

test_watch:
git ls-files | entr cargo test
git ls-files | entr just test

nestest:
NESTEST_HACK=1 cargo run roms/nestest.nes > myout.log
Expand Down
46 changes: 36 additions & 10 deletions src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ pub struct Bus {
}

impl Bus {
pub fn new(rom: Rom, ppu: Ppu) -> Self {
pub fn new(rom: Rom) -> Self {
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);

Bus {
cpu_vram: [0; 0x800],
rom,
Expand All @@ -37,15 +39,26 @@ impl Bus {
}

impl Mem for Bus {
fn mem_read(&self, addr: u16) -> u8 {
fn mem_read(&mut self, addr: u16) -> u8 {
if (RAM..RAM_MIRROR_END).contains(&addr) {
let a = addr & 0b1110_0111_1111_1111;
self.cpu_vram[a as usize]
} else if (PPU..PPU_MIRROR_END).contains(&addr) {
// The PPU exposes 8 registers. They are mirrored every 8 bytes in this range.
let addr = (addr % 8) + 0x2000;

todo!("PPU NYI")
let register_idx = addr % 8;
match register_idx {
0 | 1 | 3 | 5 | 6 => panic!(
"attempt to read from write-only PPU register: 0x200{}",
register_idx
),
2 => todo!("NYI: read PPU Status"),
4 => todo!("NYI: read OAM data (sprite data)"),
7 => self.ppu.read_data(),
8..=u16::MAX => panic!("invalid PPU register IDX: {}", register_idx),
}
} else if addr == 0x4016 {
// 2.9 OAMDMA - Sprite DMA ($4014 write)
panic!("attempt to read from write-only PPU register: 0x4016 (OAMDMA - Sprite DMA)");
} else if (PRG_ROM_START..=PRG_ROM_END).contains(&addr) {
self.read_prg_rom(addr)
} else {
Expand All @@ -58,7 +71,22 @@ impl Mem for Bus {
let a = addr & 0b1110_0111_1111_1111;
self.cpu_vram[a as usize] = data
} else if (PPU..PPU_MIRROR_END).contains(&addr) {
todo!("PPU NYI")
// The PPU exposes 8 registers. They are mirrored every 8 bytes in this range.
let register_idx = addr % 8;
match register_idx {
0 => self.ppu.write_to_ctrl(data),
1 => todo!("write to PPU Mask"),
2 => panic!("attempt to write to read-only PPU register: 0x2002 (Status)",),
3 => todo!("write to OAM Addr"),
4 => todo!("write to OAM Data"),
5 => todo!("write to PPU Scroll"),
6 => self.ppu.write_to_addr(data),
7 => self.ppu.write_to_data(data),
8..=u16::MAX => panic!("invalid PPU register IDX: {}", register_idx),
}
} else if addr == 0x4016 {
// 2.9 OAMDMA - Sprite DMA ($4014 write)
panic!("attempt to read from write-only PPU register: 0x4016 (OAMDMA - Sprite DMA)");
} else if (PRG_ROM_START..=PRG_ROM_END).contains(&addr) {
panic!("attempt to write to ROM cartridge")
} else {
Expand All @@ -74,8 +102,7 @@ mod tests {
#[test]
fn test_read_mirroring() {
let rom = Rom::new_test_rom(vec![]);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
let mut bus = Bus::new(rom, ppu);
let mut bus = Bus::new(rom);
bus.cpu_vram[0] = 123;

assert_eq!(bus.mem_read(0), 123);
Expand All @@ -87,8 +114,7 @@ mod tests {
#[test]
fn test_write_mirroring() {
let rom = Rom::new_test_rom(vec![]);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
let mut bus = Bus::new(rom, ppu);
let mut bus = Bus::new(rom);

bus.mem_write(0, 1);
assert_eq!(bus.cpu_vram[0], 1);
Expand Down
30 changes: 13 additions & 17 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::env;
use crate::{
bus::Bus,
ops::{is_official, lookup_opcode, OpName},
ppu::Ppu,
rom::Rom,
utility::addr_from,
};
Expand Down Expand Up @@ -72,11 +71,11 @@ const DEFAULT_STACK_POINTER: u8 = 0xfd;
const DEFAULT_STATUS: u8 = 0b100100;

pub trait Mem {
fn mem_read(&self, addr: u16) -> u8;
fn mem_read(&mut self, addr: u16) -> u8;

fn mem_write(&mut self, addr: u16, val: u8);

fn mem_read_u16(&self, addr: u16) -> u16 {
fn mem_read_u16(&mut self, addr: u16) -> u16 {
// NES CPU uses Little-Endian addressing
let lo = self.mem_read(addr);
let hi = self.mem_read(addr + 1);
Expand All @@ -94,7 +93,7 @@ pub trait Mem {
}

impl Mem for Cpu {
fn mem_read(&self, addr: u16) -> u8 {
fn mem_read(&mut self, addr: u16) -> u8 {
self.bus.mem_read(addr)
}

Expand All @@ -106,15 +105,14 @@ impl Mem for Cpu {
impl Cpu {
pub fn new() -> Self {
let rom = Rom::new_test_rom(vec![]);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
Cpu {
pc: 0,
sp: DEFAULT_STACK_POINTER,
a: 0,
x: 0,
y: 0,
status: DEFAULT_STATUS,
bus: Bus::new(rom, ppu),
bus: Bus::new(rom),
}
}

Expand Down Expand Up @@ -158,13 +156,13 @@ impl Cpu {
//

/// used for the "index indirect" and "indirect indexed" lookups
fn mem_read_zero_page_wrapping(&self, ptr: u8) -> u16 {
fn mem_read_zero_page_wrapping(&mut self, ptr: u8) -> u16 {
let lo = self.mem_read(ptr as u16);
let hi = self.mem_read(ptr.wrapping_add(1) as u16);
(hi as u16) << 8 | (lo as u16)
}

fn get_operand_address(&self, mode: &AddressingMode) -> u16 {
fn get_operand_address(&mut self, mode: &AddressingMode) -> u16 {
match mode {
AddressingMode::Immediate => self.pc,
AddressingMode::ZeroPage => self.mem_read(self.pc) as u16,
Expand Down Expand Up @@ -208,16 +206,15 @@ impl Cpu {
//

pub fn load_rom(&mut self, rom: Rom) {
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
self.set_bus(Bus::new(rom, ppu));
self.set_bus(Bus::new(rom));
}

// Test Helpers

fn _load_test_rom(&mut self, program: Vec<u8>) {
let rom = Rom::new_test_rom(program);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
self.set_bus(Bus::new(rom, ppu));

self.set_bus(Bus::new(rom));
}

fn _load_and_run(&mut self, program: Vec<u8>) {
Expand Down Expand Up @@ -828,7 +825,7 @@ impl Cpu {
val != 0
}

pub fn trace(&self) -> String {
pub fn trace(&mut self) -> String {
// C000 4C F5 C5 JMP $C5F5 A:00 X:00 Y:00 P:24 SP:FD PPU: 0, 21 CYC:7

let code = self.mem_read(self.pc);
Expand Down Expand Up @@ -1625,8 +1622,8 @@ mod tests {
#[test]
fn test_format_trace() {
let rom = Rom::new_test_rom(vec![]);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
let mut bus = Bus::new(rom, ppu);

let mut bus = Bus::new(rom);

bus.mem_write(100, 0xa2);
bus.mem_write(101, 0x01);
Expand Down Expand Up @@ -1661,8 +1658,7 @@ mod tests {
#[test]
fn test_format_mem_access() {
let rom = Rom::new_test_rom(vec![]);
let ppu = Ppu::new(rom.chr_rom.clone(), rom.mirroring);
let mut bus = Bus::new(rom, ppu);
let mut bus = Bus::new(rom);
// ORA ($33), Y
bus.mem_write(100, 0x11);
bus.mem_write(101, 0x33);
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fn color(byte: u8) -> Color {
}
}

fn read_screen_state(cpu: &Cpu, screen: &mut [u8; 32 * 3 * 32]) -> bool {
fn read_screen_state(cpu: &mut Cpu, screen: &mut [u8; 32 * 3 * 32]) -> bool {
let mut screen_idx = 0;
let mut updated = false;
for i in 0x0200..0x0600 {
Expand Down
Loading

0 comments on commit e5eb82f

Please sign in to comment.