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 tracing_subscriber::EnvFilter;
const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "even_odd.nes");
// const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "even_odd.nes");
const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
extern crate nes_emu;
@@ -174,15 +174,10 @@ impl Emulator {
if let Some(WindowType::Main) = self.windows.get(&id) {
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 {
tokio::time::sleep(Duration::from_millis(50)).await;
})
.then(move |_| {
iced::window::resize(id, size)
});
.then(move |_| iced::window::resize(id, size));
}
}
// 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> {
row![
header_menu(

View File

@@ -83,6 +83,10 @@ pub struct Background {
state: BackgroundState,
cur_nametable: u8,
cur_attr: u8,
cur_high: u8,
cur_low: u8,
cur_shift_high: u8,
cur_shift_low: u8,
}
@@ -99,70 +103,326 @@ pub struct Mask {
}
const COLORS: &'static [Color; 0b100_0000] = &[
Color { r: 0x66, g: 0x66, b: 0x66 }, // 00
Color { r: 0x00, g: 0x2A, b: 0x88 }, // 01
Color { r: 0x14, g: 0x12, b: 0xA7 }, // 02
Color { r: 0x3B, g: 0x00, b: 0xA4 }, // 03
Color { r: 0x5C, g: 0x00, b: 0x7E }, // 04
Color { r: 0x6E, g: 0x00, b: 0x40 }, // 05
Color { r: 0x6C, g: 0x06, b: 0x00 }, // 06
Color { r: 0x56, g: 0x1D, b: 0x00 }, // 07
Color { r: 0x33, g: 0x35, b: 0x00 }, // 08
Color { r: 0x0B, g: 0x48, b: 0x00 }, // 09
Color { r: 0x00, g: 0x52, b: 0x00 }, // 0A
Color { r: 0x00, g: 0x4F, b: 0x08 }, // 0B
Color { r: 0x00, g: 0x40, 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
Color {
r: 0x66,
g: 0x66,
b: 0x66,
}, // 00
Color {
r: 0x00,
g: 0x2A,
b: 0x88,
}, // 01
Color {
r: 0x14,
g: 0x12,
b: 0xA7,
}, // 02
Color {
r: 0x3B,
g: 0x00,
b: 0xA4,
}, // 03
Color {
r: 0x5C,
g: 0x00,
b: 0x7E,
}, // 04
Color {
r: 0x6E,
g: 0x00,
b: 0x40,
}, // 05
Color {
r: 0x6C,
g: 0x06,
b: 0x00,
}, // 06
Color {
r: 0x56,
g: 0x1D,
b: 0x00,
}, // 07
Color {
r: 0x33,
g: 0x35,
b: 0x00,
}, // 08
Color {
r: 0x0B,
g: 0x48,
b: 0x00,
}, // 09
Color {
r: 0x00,
g: 0x52,
b: 0x00,
}, // 0A
Color {
r: 0x00,
g: 0x4F,
b: 0x08,
}, // 0B
Color {
r: 0x00,
g: 0x40,
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 {
@@ -170,6 +430,13 @@ pub struct Palette {
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 {
// registers: PPURegisters,
frame_count: usize,
@@ -228,14 +495,9 @@ impl PPU {
palette: Palette {
colors: COLORS,
ram: [
0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B,
0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F,
0x09, 0x01, 0x00, 0x01, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
],
},
vblank: false,
@@ -260,8 +522,12 @@ impl PPU {
w: false,
vram_column: false,
state: BackgroundState::NameTableBytePre,
cur_high: 0,
cur_low: 0,
cur_shift_high: 0,
cur_shift_low: 0,
cur_nametable: 0,
cur_attr: 0,
},
oam: OAM {
mem: vec![0u8; 256],
@@ -412,27 +678,55 @@ impl PPU {
} else if self.pixel < 257 {
// self.dbg_int = true;
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.scanline,
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
self.background.cur_shift_high <<= 1;
self.background.cur_shift_low <<= 1;
}
self.background.state = match self.background.state {
BackgroundState::NameTableByte => {
// 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::AttrTableByte => {
// 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::PatternTableTileLow => {
// 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::PatternTableTileHigh => {
// 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::NameTableByte,
@@ -598,7 +892,7 @@ impl PPU {
frame.fill_rectangle(
Point::new(x as f32 * 10., y as f32 * 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],
);
}
}