2026-02-07 update
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 8s

This commit is contained in:
2026-02-07 04:52:13 -06:00
parent 825e245df1
commit 22c586f15a
15 changed files with 1062 additions and 162 deletions

View File

@@ -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;