Format and basic background impl

This commit is contained in:
2025-12-21 14:03:01 -06:00
parent 5c3d537cfd
commit c8d441297e
2 changed files with 372 additions and 104 deletions

View File

@@ -21,8 +21,8 @@ use nes_emu::{
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "even_odd.nes"); // const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "even_odd.nes");
// const ROM_FILE: &str = "./Super Mario Bros. (World).nes"; const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
extern crate nes_emu; extern crate nes_emu;
@@ -174,15 +174,10 @@ impl Emulator {
if let Some(WindowType::Main) = self.windows.get(&id) { if let Some(WindowType::Main) = self.windows.get(&id) {
self.main_win_size = size; self.main_win_size = size;
} }
println!("New size for {:?}, {:?}", id, size);
// return iced::window::set_min_size(id, size.into())
// .then(move |_: ()| iced::window::resize(id, size));
return Task::future(async { return Task::future(async {
tokio::time::sleep(Duration::from_millis(50)).await; tokio::time::sleep(Duration::from_millis(50)).await;
}) })
.then(move |_| { .then(move |_| iced::window::resize(id, size));
iced::window::resize(id, size)
});
} }
} }
// self.image.0.clone_from(self.nes.image()); // self.image.0.clone_from(self.nes.image());
@@ -249,27 +244,6 @@ impl Emulator {
} }
} }
// fn cpu_state(&self) -> Element<'_, Message> {
// row![column![
// // text!("Registers").font(Font::MONOSPACE),
// text!("{:?}", self.nes).font(Font::MONOSPACE),
// ],]
// .width(Fill)
// .into()
// }
// fn controls(&self) -> Element<'_, Message> {
// row![
// button("Clock tick").on_press(Message::Tick(1)),
// button("CPU tick").on_press(Message::CPU),
// button("Next Frame").on_press(Message::Frame),
// button("Next DMA").on_press(Message::DMA),
// button("Next DBG").on_press(Message::DebugInt),
// ]
// .width(Fill)
// .into()
// }
fn dropdowns(&self) -> Element<'_, Message> { fn dropdowns(&self) -> Element<'_, Message> {
row![ row![
header_menu( header_menu(

View File

@@ -83,6 +83,10 @@ pub struct Background {
state: BackgroundState, state: BackgroundState,
cur_nametable: u8,
cur_attr: u8,
cur_high: u8,
cur_low: u8,
cur_shift_high: u8, cur_shift_high: u8,
cur_shift_low: u8, cur_shift_low: u8,
} }
@@ -99,70 +103,326 @@ pub struct Mask {
} }
const COLORS: &'static [Color; 0b100_0000] = &[ const COLORS: &'static [Color; 0b100_0000] = &[
Color { r: 0x66, g: 0x66, b: 0x66 }, // 00 Color {
Color { r: 0x00, g: 0x2A, b: 0x88 }, // 01 r: 0x66,
Color { r: 0x14, g: 0x12, b: 0xA7 }, // 02 g: 0x66,
Color { r: 0x3B, g: 0x00, b: 0xA4 }, // 03 b: 0x66,
Color { r: 0x5C, g: 0x00, b: 0x7E }, // 04 }, // 00
Color { r: 0x6E, g: 0x00, b: 0x40 }, // 05 Color {
Color { r: 0x6C, g: 0x06, b: 0x00 }, // 06 r: 0x00,
Color { r: 0x56, g: 0x1D, b: 0x00 }, // 07 g: 0x2A,
Color { r: 0x33, g: 0x35, b: 0x00 }, // 08 b: 0x88,
Color { r: 0x0B, g: 0x48, b: 0x00 }, // 09 }, // 01
Color { r: 0x00, g: 0x52, b: 0x00 }, // 0A Color {
Color { r: 0x00, g: 0x4F, b: 0x08 }, // 0B r: 0x14,
Color { r: 0x00, g: 0x40, b: 0x4D }, // 0C g: 0x12,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 0D b: 0xA7,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 0E }, // 02
Color { r: 0x00, g: 0x00, b: 0x00 }, // 0F Color {
Color { r: 0xAD, g: 0xAD, b: 0xAD }, // 10 r: 0x3B,
Color { r: 0x15, g: 0x5F, b: 0xD9 }, // 11 g: 0x00,
Color { r: 0x42, g: 0x40, b: 0xFF }, // 12 b: 0xA4,
Color { r: 0x75, g: 0x27, b: 0xFE }, // 13 }, // 03
Color { r: 0xA0, g: 0x1A, b: 0xCC }, // 14 Color {
Color { r: 0xB7, g: 0x1E, b: 0x7B }, // 15 r: 0x5C,
Color { r: 0xB5, g: 0x31, b: 0x20 }, // 16 g: 0x00,
Color { r: 0x99, g: 0x4E, b: 0x00 }, // 17 b: 0x7E,
Color { r: 0x6B, g: 0x6D, b: 0x00 }, // 18 }, // 04
Color { r: 0x38, g: 0x87, b: 0x00 }, // 19 Color {
Color { r: 0x0C, g: 0x93, b: 0x00 }, // 1A r: 0x6E,
Color { r: 0x00, g: 0x8F, b: 0x32 }, // 1B g: 0x00,
Color { r: 0x00, g: 0x7C, b: 0x8D }, // 1C b: 0x40,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 1D }, // 05
Color { r: 0x00, g: 0x00, b: 0x00 }, // 1E Color {
Color { r: 0x00, g: 0x00, b: 0x00 }, // 1F r: 0x6C,
Color { r: 0xFF, g: 0xFE, b: 0xFF }, // 20 g: 0x06,
Color { r: 0x64, g: 0xB0, b: 0xFF }, // 21 b: 0x00,
Color { r: 0x92, g: 0x90, b: 0xFF }, // 22 }, // 06
Color { r: 0xC6, g: 0x76, b: 0xFF }, // 23 Color {
Color { r: 0xF3, g: 0x6A, b: 0xFF }, // 24 r: 0x56,
Color { r: 0xFE, g: 0x6E, b: 0xCC }, // 25 g: 0x1D,
Color { r: 0xFE, g: 0x81, b: 0x70 }, // 26 b: 0x00,
Color { r: 0xEA, g: 0x9E, b: 0x22 }, // 27 }, // 07
Color { r: 0xBC, g: 0xBE, b: 0x00 }, // 28 Color {
Color { r: 0x88, g: 0xD8, b: 0x00 }, // 29 r: 0x33,
Color { r: 0x5C, g: 0xE4, b: 0x30 }, // 2A g: 0x35,
Color { r: 0x45, g: 0xE0, b: 0x82 }, // 2B b: 0x00,
Color { r: 0x48, g: 0xCD, b: 0xDE }, // 2C }, // 08
Color { r: 0x4F, g: 0x4F, b: 0x4F }, // 2D Color {
Color { r: 0x00, g: 0x00, b: 0x00 }, // 2E r: 0x0B,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 2F g: 0x48,
Color { r: 0xFF, g: 0xFE, b: 0xFF }, // 30 b: 0x00,
Color { r: 0xC0, g: 0xDF, b: 0xFF }, // 31 }, // 09
Color { r: 0xD3, g: 0xD2, b: 0xFF }, // 32 Color {
Color { r: 0xE8, g: 0xC8, b: 0xFF }, // 33 r: 0x00,
Color { r: 0xFB, g: 0xC2, b: 0xFF }, // 34 g: 0x52,
Color { r: 0xFE, g: 0xC4, b: 0xEA }, // 35 b: 0x00,
Color { r: 0xFE, g: 0xCC, b: 0xC5 }, // 36 }, // 0A
Color { r: 0xF7, g: 0xD8, b: 0xA5 }, // 37 Color {
Color { r: 0xE4, g: 0xE5, b: 0x94 }, // 38 r: 0x00,
Color { r: 0xCF, g: 0xEF, b: 0x96 }, // 39 g: 0x4F,
Color { r: 0xBD, g: 0xF4, b: 0xAB }, // 3A b: 0x08,
Color { r: 0xB3, g: 0xF3, b: 0xCC }, // 3B }, // 0B
Color { r: 0xB5, g: 0xEB, b: 0xF2 }, // 3C Color {
Color { r: 0xB8, g: 0xB8, b: 0xB8 }, // 3D r: 0x00,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 3E g: 0x40,
Color { r: 0x00, g: 0x00, b: 0x00 }, // 3F b: 0x4D,
}, // 0C
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 0D
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 0E
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 0F
Color {
r: 0xAD,
g: 0xAD,
b: 0xAD,
}, // 10
Color {
r: 0x15,
g: 0x5F,
b: 0xD9,
}, // 11
Color {
r: 0x42,
g: 0x40,
b: 0xFF,
}, // 12
Color {
r: 0x75,
g: 0x27,
b: 0xFE,
}, // 13
Color {
r: 0xA0,
g: 0x1A,
b: 0xCC,
}, // 14
Color {
r: 0xB7,
g: 0x1E,
b: 0x7B,
}, // 15
Color {
r: 0xB5,
g: 0x31,
b: 0x20,
}, // 16
Color {
r: 0x99,
g: 0x4E,
b: 0x00,
}, // 17
Color {
r: 0x6B,
g: 0x6D,
b: 0x00,
}, // 18
Color {
r: 0x38,
g: 0x87,
b: 0x00,
}, // 19
Color {
r: 0x0C,
g: 0x93,
b: 0x00,
}, // 1A
Color {
r: 0x00,
g: 0x8F,
b: 0x32,
}, // 1B
Color {
r: 0x00,
g: 0x7C,
b: 0x8D,
}, // 1C
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 1D
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 1E
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 1F
Color {
r: 0xFF,
g: 0xFE,
b: 0xFF,
}, // 20
Color {
r: 0x64,
g: 0xB0,
b: 0xFF,
}, // 21
Color {
r: 0x92,
g: 0x90,
b: 0xFF,
}, // 22
Color {
r: 0xC6,
g: 0x76,
b: 0xFF,
}, // 23
Color {
r: 0xF3,
g: 0x6A,
b: 0xFF,
}, // 24
Color {
r: 0xFE,
g: 0x6E,
b: 0xCC,
}, // 25
Color {
r: 0xFE,
g: 0x81,
b: 0x70,
}, // 26
Color {
r: 0xEA,
g: 0x9E,
b: 0x22,
}, // 27
Color {
r: 0xBC,
g: 0xBE,
b: 0x00,
}, // 28
Color {
r: 0x88,
g: 0xD8,
b: 0x00,
}, // 29
Color {
r: 0x5C,
g: 0xE4,
b: 0x30,
}, // 2A
Color {
r: 0x45,
g: 0xE0,
b: 0x82,
}, // 2B
Color {
r: 0x48,
g: 0xCD,
b: 0xDE,
}, // 2C
Color {
r: 0x4F,
g: 0x4F,
b: 0x4F,
}, // 2D
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 2E
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 2F
Color {
r: 0xFF,
g: 0xFE,
b: 0xFF,
}, // 30
Color {
r: 0xC0,
g: 0xDF,
b: 0xFF,
}, // 31
Color {
r: 0xD3,
g: 0xD2,
b: 0xFF,
}, // 32
Color {
r: 0xE8,
g: 0xC8,
b: 0xFF,
}, // 33
Color {
r: 0xFB,
g: 0xC2,
b: 0xFF,
}, // 34
Color {
r: 0xFE,
g: 0xC4,
b: 0xEA,
}, // 35
Color {
r: 0xFE,
g: 0xCC,
b: 0xC5,
}, // 36
Color {
r: 0xF7,
g: 0xD8,
b: 0xA5,
}, // 37
Color {
r: 0xE4,
g: 0xE5,
b: 0x94,
}, // 38
Color {
r: 0xCF,
g: 0xEF,
b: 0x96,
}, // 39
Color {
r: 0xBD,
g: 0xF4,
b: 0xAB,
}, // 3A
Color {
r: 0xB3,
g: 0xF3,
b: 0xCC,
}, // 3B
Color {
r: 0xB5,
g: 0xEB,
b: 0xF2,
}, // 3C
Color {
r: 0xB8,
g: 0xB8,
b: 0xB8,
}, // 3D
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 3E
Color {
r: 0x00,
g: 0x00,
b: 0x00,
}, // 3F
]; ];
pub struct Palette { pub struct Palette {
@@ -170,6 +430,13 @@ pub struct Palette {
ram: [u8; 0x20], ram: [u8; 0x20],
} }
impl Palette {
pub fn color(&self, idx: u8) -> Color {
debug_assert!(idx < 0x20, "Palette index out of range");
self.colors[(self.ram[idx as usize] & 0x3F) as usize]
}
}
pub struct PPU { pub struct PPU {
// registers: PPURegisters, // registers: PPURegisters,
frame_count: usize, frame_count: usize,
@@ -228,14 +495,9 @@ impl PPU {
palette: Palette { palette: Palette {
colors: COLORS, colors: COLORS,
ram: [ ram: [
0x20, 0x21, 0x22, 0x23, 0x09, 0x01, 0x00, 0x01, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x24, 0x25, 0x26, 0x27, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x28, 0x29, 0x2A, 0x2B, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F,
], ],
}, },
vblank: false, vblank: false,
@@ -260,8 +522,12 @@ impl PPU {
w: false, w: false,
vram_column: false, vram_column: false,
state: BackgroundState::NameTableBytePre, state: BackgroundState::NameTableBytePre,
cur_high: 0,
cur_low: 0,
cur_shift_high: 0, cur_shift_high: 0,
cur_shift_low: 0, cur_shift_low: 0,
cur_nametable: 0,
cur_attr: 0,
}, },
oam: OAM { oam: OAM {
mem: vec![0u8; 256], mem: vec![0u8; 256],
@@ -412,27 +678,55 @@ impl PPU {
} else if self.pixel < 257 { } else if self.pixel < 257 {
// self.dbg_int = true; // self.dbg_int = true;
if self.scanline < 240 { if self.scanline < 240 {
// Determine background color
let a = self.background.cur_shift_high & 0x80;
let b = self.background.cur_shift_low & 0x80;
let val = (a >> 6) | (b >> 7);
debug_assert!(val < 4);
// Write to screen
self.render_buffer.write( self.render_buffer.write(
self.scanline, self.scanline,
self.pixel - 1, self.pixel - 1,
Color { r: 255, g: 0, b: 0 }, self.palette.color(val)
// self.palette.colors[val as usize],
); // TODO: this should come from shift registers ); // TODO: this should come from shift registers
self.background.cur_shift_high <<= 1;
self.background.cur_shift_low <<= 1;
} }
self.background.state = match self.background.state { self.background.state = match self.background.state {
BackgroundState::NameTableByte => { BackgroundState::NameTableByte => {
// TODO: Fetch name table byte // TODO: Fetch name table byte
let addr = 0x2000 + self.pixel / 8 + self.scanline / 8;
let val = self.memory.read(addr as u16).reg_map(|_, _| todo!());
self.background.cur_nametable = val;
// self.background.v;
BackgroundState::AttrTableBytePre BackgroundState::AttrTableBytePre
} }
BackgroundState::AttrTableByte => { BackgroundState::AttrTableByte => {
// TODO: Fetch attr table byte // TODO: Fetch attr table byte
// let addr = 0x2000 + self.pixel / 8 + self.scanline / 8;
// let val = self.memory.read(addr as u16).reg_map(|_, _| todo!());
// self.background.cur_attr = val;
BackgroundState::PatternTableTileLowPre BackgroundState::PatternTableTileLowPre
} }
BackgroundState::PatternTableTileLow => { BackgroundState::PatternTableTileLow => {
// TODO: Fetch // TODO: Fetch
let addr = self.background.cur_nametable as u16 * 16
+ (self.scanline % 8) as u16;
let val = self.memory.read(addr).reg_map(|_, _| todo!());
self.background.cur_low = val;
BackgroundState::PatternTableTileHighPre BackgroundState::PatternTableTileHighPre
} }
BackgroundState::PatternTableTileHigh => { BackgroundState::PatternTableTileHigh => {
// TODO: Fetch // TODO: Fetch
let addr = self.background.cur_nametable as u16 * 16
+ 8
+ (self.scanline % 8) as u16;
let val = self.memory.read(addr).reg_map(|_, _| todo!());
self.background.cur_high = val;
self.background.cur_shift_low = self.background.cur_low;
self.background.cur_shift_high = self.background.cur_high;
BackgroundState::NameTableBytePre BackgroundState::NameTableBytePre
} }
BackgroundState::NameTableBytePre => BackgroundState::NameTableByte, BackgroundState::NameTableBytePre => BackgroundState::NameTableByte,
@@ -598,7 +892,7 @@ impl PPU {
frame.fill_rectangle( frame.fill_rectangle(
Point::new(x as f32 * 10., y as f32 * 10.), Point::new(x as f32 * 10., y as f32 * 10.),
Size::new(10., 10.), Size::new(10., 10.),
self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize] self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize],
); );
} }
} }