mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
placeholder to compute the current pixel
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user