2026-02-07 update
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 8s
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 8s
This commit is contained in:
79
src/ppu.rs
79
src/ppu.rs
@@ -1,15 +1,13 @@
|
||||
use std::fmt;
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use iced::{
|
||||
Point, Size,
|
||||
advanced::graphics::geometry::Renderer,
|
||||
widget::canvas::{Fill, Frame},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
hex_view::Memory,
|
||||
mem::{Mapped, PpuMem},
|
||||
};
|
||||
use crate::mem::{Mapped, PpuMem, Value};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Color {
|
||||
@@ -33,18 +31,25 @@ impl fmt::Display for Color {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RenderBuffer<const W: usize, const H: usize> {
|
||||
buffer: Box<[Color]>,
|
||||
raw_rgba: BytesMut,
|
||||
}
|
||||
|
||||
impl<const W: usize, const H: usize> RenderBuffer<W, H> {
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
buffer: vec![Color { r: 0, g: 0, b: 0 }; W * H].into_boxed_slice(),
|
||||
raw_rgba: BytesMut::from_iter(vec![0; W * H * 4]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, line: usize, pixel: usize, color: Color) {
|
||||
assert!(line < H && pixel < W);
|
||||
self.buffer[line * W + pixel] = color;
|
||||
let pos = (line * W + pixel) * 4;
|
||||
self.raw_rgba[pos] = color.r;
|
||||
self.raw_rgba[pos + 1] = color.g;
|
||||
self.raw_rgba[pos + 2] = color.b;
|
||||
self.raw_rgba[pos + 3] = 0xFF;
|
||||
}
|
||||
pub fn read(&self, line: usize, pixel: usize) -> Color {
|
||||
assert!(line < H && pixel < W);
|
||||
@@ -53,6 +58,12 @@ impl<const W: usize, const H: usize> RenderBuffer<W, H> {
|
||||
|
||||
pub fn clone_from(&mut self, other: &Self) {
|
||||
self.buffer.copy_from_slice(&other.buffer);
|
||||
// self.raw_rgba.fr
|
||||
self.raw_rgba.copy_from_slice(&other.raw_rgba);
|
||||
}
|
||||
|
||||
pub fn image(&self) -> Bytes {
|
||||
Bytes::copy_from_slice(&self.raw_rgba)
|
||||
}
|
||||
|
||||
pub fn assert_eq(&self, other: &Self) {
|
||||
@@ -72,7 +83,7 @@ impl<const W: usize, const H: usize> RenderBuffer<W, H> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PPUMMRegisters {
|
||||
Palette,
|
||||
}
|
||||
@@ -84,18 +95,6 @@ pub struct OAM {
|
||||
edit_ver: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum BackgroundState {
|
||||
NameTableBytePre,
|
||||
NameTableByte,
|
||||
AttrTableBytePre,
|
||||
AttrTableByte,
|
||||
PatternTableTileLowPre,
|
||||
PatternTableTileLow,
|
||||
PatternTableTileHighPre,
|
||||
PatternTableTileHigh,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Background {
|
||||
/// Current vram address, 15 bits
|
||||
@@ -112,8 +111,6 @@ pub struct Background {
|
||||
pub vram_column: bool,
|
||||
pub second_pattern: bool,
|
||||
|
||||
state: BackgroundState,
|
||||
|
||||
pub cur_nametable: u8,
|
||||
pub cur_attr: u8,
|
||||
pub next_attr: u8,
|
||||
@@ -470,6 +467,10 @@ impl Palette {
|
||||
debug_assert!(idx < 0x20, "Palette index out of range");
|
||||
self.colors[(self.ram[idx as usize + palette as usize * 4] & 0x3F) as usize]
|
||||
}
|
||||
|
||||
pub fn ram(&self, offset: u8) -> u8 {
|
||||
self.ram[offset as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -482,10 +483,12 @@ pub struct PPU {
|
||||
pub scanline: usize,
|
||||
pub pixel: usize,
|
||||
|
||||
vram_buffer: u8,
|
||||
|
||||
pub mask: Mask,
|
||||
pub vblank: bool,
|
||||
|
||||
palette: Palette,
|
||||
pub palette: Palette,
|
||||
pub background: Background,
|
||||
oam: OAM,
|
||||
pub render_buffer: RenderBuffer<256, 240>,
|
||||
@@ -542,6 +545,7 @@ impl PPU {
|
||||
frame_count: 0,
|
||||
nmi_enabled: false,
|
||||
// nmi_waiting: false,
|
||||
// TODO: Is even in the right initial state?
|
||||
even: false,
|
||||
scanline: 0,
|
||||
pixel: 25,
|
||||
@@ -553,7 +557,6 @@ impl PPU {
|
||||
w: false,
|
||||
vram_column: false,
|
||||
second_pattern: false,
|
||||
state: BackgroundState::NameTableBytePre,
|
||||
cur_high: 0,
|
||||
cur_low: 0,
|
||||
cur_shift_high: 0,
|
||||
@@ -568,6 +571,7 @@ impl PPU {
|
||||
addr: 0,
|
||||
edit_ver: 0,
|
||||
},
|
||||
vram_buffer: 0,
|
||||
}
|
||||
}
|
||||
pub fn reset(&mut self) {
|
||||
@@ -593,10 +597,22 @@ impl PPU {
|
||||
5 => panic!("ppuscroll is write-only"),
|
||||
6 => panic!("ppuaddr is write-only"),
|
||||
7 => {
|
||||
// TODO: read buffer only applies to ppu data, not palette ram...
|
||||
// println!("Updating v for ppudata read");
|
||||
let val = mem.read(self.background.v).reg_map(|a, off| match a {
|
||||
PPUMMRegisters::Palette => self.palette.ram[off as usize],
|
||||
});
|
||||
// self.vram_buffer =
|
||||
let val = match mem.read(self.background.v) {
|
||||
Value::Value(v) => {
|
||||
let val = self.vram_buffer;
|
||||
self.vram_buffer = v;
|
||||
val
|
||||
},
|
||||
Value::Register { reg: PPUMMRegisters::Palette, offset } => {
|
||||
self.palette.ram[offset as usize]
|
||||
},
|
||||
};
|
||||
// .reg_map(|a, off| match a {
|
||||
// PPUMMRegisters::Palette => self.palette.ram[off as usize],
|
||||
// });
|
||||
// if self.background
|
||||
self.increment_v();
|
||||
val
|
||||
@@ -656,7 +672,7 @@ impl PPU {
|
||||
}
|
||||
}
|
||||
0x06 => {
|
||||
// TODO: ppu addr
|
||||
// TODO: this actually sets T, which is copied to v later (~ a pixel later?)
|
||||
if self.background.w {
|
||||
self.background.v =
|
||||
u16::from_le_bytes([val, self.background.v.to_le_bytes()[1]]);
|
||||
@@ -672,10 +688,16 @@ impl PPU {
|
||||
}
|
||||
0x07 => {
|
||||
// println!("Writing: {:02X}, @{:04X}", val, self.background.v);
|
||||
mem.write(self.background.v, val, |r, o, v| match r {
|
||||
mem.write(self.background.v, val, |r, mut o, v| match r {
|
||||
PPUMMRegisters::Palette => {
|
||||
// println!("Writing {:02X} to {:02X}", v & 0x3F, o);
|
||||
self.palette.ram[o as usize] = v & 0x3F;
|
||||
if o % 4 == 0 {
|
||||
o = o & !0b1_0000;
|
||||
self.palette.ram[o as usize] = v & 0x3F;
|
||||
self.palette.ram[(o | 0b1_0000) as usize] = v & 0x3F;
|
||||
} else {
|
||||
self.palette.ram[o as usize] = v & 0x3F;
|
||||
}
|
||||
}
|
||||
});
|
||||
self.increment_v();
|
||||
@@ -710,6 +732,7 @@ impl PPU {
|
||||
self.scanline = 0;
|
||||
self.pixel = 0;
|
||||
self.even = !self.even;
|
||||
self.frame_count += 1;
|
||||
}
|
||||
if self.pixel == 341 {
|
||||
self.pixel = 0;
|
||||
@@ -849,8 +872,6 @@ impl PPU {
|
||||
}
|
||||
if self.scanline == 241 && self.pixel == 1 {
|
||||
self.vblank = true;
|
||||
self.frame_count += 1;
|
||||
self.background.state = BackgroundState::NameTableBytePre;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user