placeholder to compute the current pixel

This commit is contained in:
2024-07-21 22:09:11 -05:00
parent 3468b1f948
commit 97236657a0
2 changed files with 148 additions and 6 deletions
+62 -2
View File
@@ -12,7 +12,7 @@ pub struct PPU {
impl PPU { impl PPU {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
framebuffer: vec![0; FRAMEBUFFER_SIZE], framebuffer: vec![0xFF; FRAMEBUFFER_SIZE],
registers: PPURegisters::new(), registers: PPURegisters::new(),
was_vblank_nmi_set: false, was_vblank_nmi_set: false,
is_irq_set: false, is_irq_set: false,
@@ -26,6 +26,9 @@ impl PPU {
} }
pub fn dot_cycle(&mut self) { pub fn dot_cycle(&mut self) {
if !self.registers.is_vblanking() && !self.registers.is_hblanking() {
self.put_pixel(self.compute_pixel())
}
self.increment_hv_count(); self.increment_hv_count();
} }
@@ -51,6 +54,29 @@ impl PPU {
pub fn framebuffer(&self) -> &[u8] { pub fn framebuffer(&self) -> &[u8] {
&self.framebuffer &self.framebuffer
} }
fn compute_pixel(&self) -> (u8, u8, u8) {
if self.registers.is_hblanking() || self.registers.is_hblanking() {
return (0x00, 0x00, 0x00)
}
(0xFF, 0x00, 0xFF)
}
fn put_pixel(&mut self, pixel: (u8, u8, u8)) {
let fb_index = self.get_pixel_index();
self.framebuffer[fb_index] = pixel.0;
self.framebuffer[fb_index + 1] = pixel.1;
self.framebuffer[fb_index + 2] = pixel.2;
}
fn get_pixel_index(&self) -> usize {
let h_count = self.registers.h_count as usize;
let v_count = self.registers.v_count as usize;
return (
(h_count - 22) +
((v_count - 1) * MAX_TV_WIDTH)
) * 4
}
} }
impl Default for PPU { impl Default for PPU {
@@ -81,4 +107,38 @@ mod ppu_general_test {
assert_eq!(ppu.registers.h_count, 0); assert_eq!(ppu.registers.h_count, 0);
assert_eq!(ppu.registers.v_count, 0); assert_eq!(ppu.registers.v_count, 0);
} }
}
#[test]
fn test_get_current_pixel_index() {
let mut ppu = PPU::new();
ppu.registers.v_count = 1;
ppu.registers.h_count = 22;
assert_eq!(ppu.get_pixel_index(), 0);
ppu.registers.v_count = 1;
ppu.registers.h_count = 23;
assert_eq!(ppu.get_pixel_index(), 4);
ppu.registers.v_count = 1;
ppu.registers.h_count = 24;
assert_eq!(ppu.get_pixel_index(), 8);
ppu.registers.v_count = 2;
ppu.registers.h_count = 22;
assert_eq!(ppu.get_pixel_index(), 2048);
ppu.registers.v_count = 2;
ppu.registers.h_count = 23;
assert_eq!(ppu.get_pixel_index(), 2052);
ppu.registers.v_count = 2;
ppu.registers.h_count = 24;
assert_eq!(ppu.get_pixel_index(), 2056);
}
#[test]
fn test_put_pixel() {
let mut ppu = PPU::new();
ppu.registers.v_count = 2;
ppu.registers.h_count = 22;
ppu.put_pixel((11, 22, 33));
assert_eq!(ppu.framebuffer[2048], 11);
assert_eq!(ppu.framebuffer[2049], 22);
assert_eq!(ppu.framebuffer[2050], 33);
}
}
+86 -4
View File
@@ -375,10 +375,26 @@ impl PPURegisters {
} }
pub fn is_vblanking(&self) -> bool { pub fn is_vblanking(&self) -> bool {
if self.v_count >= 1 && self.v_count <= 224 { !(self.v_count >= 1 && self.v_count <= 224)
return false }
}
true pub fn is_hblanking(&self) -> bool {
!(self.h_count >= 22 && self.h_count <= 277)
}
pub fn get_current_res(&self) -> (u16, u16) {
let w = if self.is_true_high_res_mode_enabled() {512} else {256};
let h = if self.is_interlace_mode_enabled() {448} else {224};
(w, h)
}
pub fn is_interlace_mode_enabled(&self) -> bool {
self._read(SETINI) & 0x01 == 0b1
}
pub fn is_true_high_res_mode_enabled(&self) -> bool {
let current_bg_mode = self._read(BGMODE);
current_bg_mode == 5 || current_bg_mode == 6
} }
} }
@@ -590,4 +606,70 @@ mod ppu_registers_test {
registers.v_count = 50; registers.v_count = 50;
assert!(!registers.is_vblanking()); assert!(!registers.is_vblanking());
} }
#[test]
fn test_is_hblanking() {
let mut registers = PPURegisters::new();
registers.h_count = 0;
assert!(registers.is_hblanking());
registers.h_count = 20;
assert!(registers.is_hblanking());
registers.h_count = 21;
assert!(registers.is_hblanking());
registers.h_count = 278;
assert!(registers.is_hblanking());
registers.h_count = 300;
assert!(registers.is_hblanking());
registers.h_count = 22;
assert!(!registers.is_hblanking());
registers.h_count = 100;
assert!(!registers.is_hblanking());
registers.h_count = 277;
assert!(!registers.is_hblanking());
}
#[test]
fn test_is_interlace_mode_enabled() {
let mut registers = PPURegisters::new();
registers._write(SETINI, 0x01);
assert!(registers.is_interlace_mode_enabled());
registers._write(SETINI, 0x00);
assert!(!registers.is_interlace_mode_enabled());
}
#[test]
fn test_is_true_high_res_mode_enabled() {
let mut registers = PPURegisters::new();
registers._write(BGMODE, 1);
assert!(!registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 2);
assert!(!registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 3);
assert!(!registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 4);
assert!(!registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 5);
assert!(registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 6);
assert!(registers.is_true_high_res_mode_enabled());
registers._write(BGMODE, 7);
assert!(!registers.is_true_high_res_mode_enabled());
}
#[test]
fn test_get_current_res() {
let mut registers = PPURegisters::new();
registers._write(BGMODE, 1);
registers._write(SETINI, 0x00);
assert_eq!(registers.get_current_res(), (256, 224));
registers._write(BGMODE, 1);
registers._write(SETINI, 0x01);
assert_eq!(registers.get_current_res(), (256, 448));
registers._write(BGMODE, 5);
registers._write(SETINI, 0x00);
assert_eq!(registers.get_current_res(), (512, 224));
registers._write(BGMODE, 6);
registers._write(SETINI, 0x01);
assert_eq!(registers.get_current_res(), (512, 448));
}
} }