Fix minor warnings and debug log

This commit is contained in:
2026-04-08 21:15:15 -05:00
parent e882b3b325
commit d140f1e122
9 changed files with 153 additions and 142 deletions

View File

@@ -1,12 +1,9 @@
use std::{
sync::{
atomic::AtomicBool, mpsc::{channel, Sender, TryRecvError}, Arc
},
time::Instant,
};
use std::sync::{
atomic::AtomicBool, Arc
};
use cpal::{
Device, FrameCount, Host, SampleFormat, Stream,
Device, FrameCount, Host, Stream,
traits::{DeviceTrait, HostTrait, StreamTrait},
};
use ringbuf::{

View File

@@ -70,13 +70,13 @@ where
{
text(format!("{val:02X}"))
}
pub fn bin8<'a, Theme, Renderer>(val: u8) -> Text<'a, Theme, Renderer>
where
Theme: text::Catalog + 'a,
Renderer: iced::advanced::text::Renderer,
{
text(format!("{val:08b}"))
}
// pub fn bin8<'a, Theme, Renderer>(val: u8) -> Text<'a, Theme, Renderer>
// where
// Theme: text::Catalog + 'a,
// Renderer: iced::advanced::text::Renderer,
// {
// text(format!("{val:08b}"))
// }
pub fn bin32<'a, Theme, Renderer>(val: u32) -> Text<'a, Theme, Renderer>
where
Theme: text::Catalog + 'a,
@@ -408,7 +408,7 @@ pub fn labelled_box<'a, Message: 'a>(label: &'a str, value: bool) -> Element<'a,
pub enum DbgImage<'a> {
NameTable(&'a Mapped, &'a PPU),
PatternTable(&'a Mapped, &'a PPU),
Palette(&'a Mapped, &'a PPU),
Palette(&'a PPU),
}
impl<Message, T> Program<Message, T> for DbgImage<'_> {
@@ -432,7 +432,7 @@ impl<Message, T> Program<Message, T> for DbgImage<'_> {
DbgImage::PatternTable(mem, ppu) => {
ppu.render_pattern_tables(mem, &mut name_table_frame)
}
DbgImage::Palette(_, ppu) => ppu.render_palette(&mut name_table_frame),
DbgImage::Palette(ppu) => ppu.render_palette(&mut name_table_frame),
};
vec![name_table_frame.into_geometry()]
}
@@ -443,21 +443,21 @@ impl DbgImage<'_> {
match self {
DbgImage::NameTable(_, _) => Length::Fixed(512. * 2.),
DbgImage::PatternTable(_, _) => Length::Fixed(16. * 8. * 2.),
DbgImage::Palette(_, _) => Length::Fixed(40. * 2.),
DbgImage::Palette(_) => Length::Fixed(40. * 2.),
}
}
fn height(&self) -> Length {
match self {
DbgImage::NameTable(_, _) => Length::Fixed(512. * 2.),
DbgImage::PatternTable(_, _) => Length::Fixed(16. * 8. * 2. * 2.),
DbgImage::Palette(_, _) => Length::Fixed(80. * 2.),
DbgImage::Palette(_) => Length::Fixed(80. * 2.),
}
}
fn help(&self, cursor: Point) -> Option<String> {
match self {
DbgImage::NameTable(mem, ppu) => ppu.name_cursor_info(mem, cursor),
DbgImage::PatternTable(_, ppu) => ppu.pattern_cursor_info(cursor),
DbgImage::Palette(_, ppu) => ppu.palette_cursor_info(cursor),
DbgImage::Palette(ppu) => ppu.palette_cursor_info(cursor),
}
}
}

View File

@@ -1,25 +1,25 @@
use std::{
fmt::{self, Display}, ops::Deref
};
use std::fmt::{self, Display};
use iced::{
advanced::{layout::{Limits, Node}, overlay, renderer::{Quad, Style}, text::Renderer, widget::{tree::{State, Tag}, Operation, Tree}, Clipboard, Layout, Shell, Text, Widget}, alignment::Vertical, keyboard::{key::Named, Key}, mouse::{Button, Cursor, Interaction, ScrollDelta}, widget::{column, lazy, text}, Color, Element, Event, Fill, Font, Length, Padding, Pixels, Point, Rectangle, Size, Task, Vector
Color, Element, Event, Font, Length, Padding, Pixels, Point, Rectangle, Size, Task, Vector,
advanced::{
Clipboard, Layout, Shell, Text, Widget,
layout::{Limits, Node},
overlay,
renderer::{Quad, Style},
text::Renderer,
widget::{
Operation, Tree,
tree::{State, Tag},
},
},
alignment::Vertical,
keyboard::{Key, key::Named},
mouse::{Button, Cursor, Interaction, ScrollDelta},
};
// use iced_core::{
// Clipboard, Color, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, Text, Vector,
// Widget,
// layout::{Limits, Node},
// mouse::{Cursor, Interaction},
// overlay,
// renderer::{Quad, Style},
// widget::{
// Operation, Tree,
// tree::{State, Tag},
// },
// };
use nes_emu::Memory;
use nes_emu::{PPU, Mapped, PPUMMRegisters};
use nes_emu::{Mapped, PPU, PPUMMRegisters};
#[derive(Debug, Clone, Copy)]
struct Cpu<'a>(&'a Mapped);
@@ -82,53 +82,53 @@ pub enum HexEvent {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HexView {}
struct Val(Option<u8>);
impl fmt::Display for Val {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(val) = self.0 {
write!(f, "{:02X}", val)
} else {
write!(f, "XX")
}
}
}
// struct Val(Option<u8>);
// impl fmt::Display for Val {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// if let Some(val) = self.0 {
// write!(f, "{:02X}", val)
// } else {
// write!(f, "XX")
// }
// }
// }
impl HexView {
pub fn new() -> Self {
Self {}
}
// pub fn new() -> Self {
// Self {}
// }
pub fn render_any<'a, M: Memory + Copy + 'a>(&self, mem: M) -> Element<'a, HexEvent> {
struct Row<M: Memory>(usize, M);
impl<'a, M: Memory + 'a> fmt::Display for Row<M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", Val(self.1.peek(self.0)))?;
for i in 1..16 {
write!(f, " {}", Val(self.1.peek(self.0 + i)))?;
}
Ok(())
}
}
column![
text!("Hex view"),
iced::widget::scrollable(lazy(mem.edit_ver(), move |_| column(
[
text!(" | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")
.font(Font::MONOSPACE)
.into()
]
.into_iter()
.chain((0..mem.len()).step_by(16).map(|off| {
text!(" {off:04X} | {}", Row(off, mem))
.font(Font::MONOSPACE)
.into()
}))
)))
.width(Fill),
]
.width(Fill)
.into()
}
// pub fn render_any<'a, M: Memory + Copy + 'a>(&self, mem: M) -> Element<'a, HexEvent> {
// struct Row<M: Memory>(usize, M);
// impl<'a, M: Memory + 'a> fmt::Display for Row<M> {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// write!(f, "{}", Val(self.1.peek(self.0)))?;
// for i in 1..16 {
// write!(f, " {}", Val(self.1.peek(self.0 + i)))?;
// }
// Ok(())
// }
// }
// column![
// text!("Hex view"),
// iced::widget::scrollable(lazy(mem.edit_ver(), move |_| column(
// [
// text!(" | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")
// .font(Font::MONOSPACE)
// .into()
// ]
// .into_iter()
// .chain((0..mem.len()).step_by(16).map(|off| {
// text!(" {off:04X} | {}", Row(off, mem))
// .font(Font::MONOSPACE)
// .into()
// }))
// )))
// .width(Fill),
// ]
// .width(Fill)
// .into()
// }
pub fn render_cpu<'a>(&self, mem: &'a Mapped) -> Element<'a, HexEvent> {
// self.render_any(Cpu(mem))
Element::new(
@@ -147,35 +147,35 @@ impl HexView {
)
}
pub fn update(&mut self, ev: HexEvent) -> Task<HexEvent> {
pub fn update(&mut self, _ev: HexEvent) -> Task<HexEvent> {
todo!()
}
}
pub struct BufferSlice<'a>(pub &'a [u8]);
// pub struct BufferSlice<'a>(pub &'a [u8]);
impl Deref for BufferSlice<'_> {
type Target = [u8];
// impl Deref for BufferSlice<'_> {
// type Target = [u8];
fn deref(&self) -> &Self::Target {
self.0
}
}
// fn deref(&self) -> &Self::Target {
// self.0
// }
// }
pub trait Buffer {
fn peek(&self, val: usize) -> Option<u8>;
fn len(&self) -> usize;
}
impl Buffer for BufferSlice<'_> {
fn peek(&self, val: usize) -> Option<u8> {
self.get(val).copied()
}
// impl Buffer for BufferSlice<'_> {
// fn peek(&self, val: usize) -> Option<u8> {
// self.get(val).copied()
// }
fn len(&self) -> usize {
self.iter().len()
}
}
// fn len(&self) -> usize {
// self.iter().len()
// }
// }
impl<M: Memory> Buffer for M {
fn peek(&self, val: usize) -> Option<u8> {
self.peek(val)
@@ -202,6 +202,7 @@ pub struct HexEdit {
new_value: u8,
}
#[allow(dead_code)]
pub struct HexEditor<B, M, R: Renderer> {
val: B,
font_size: Option<Pixels>,
@@ -279,6 +280,7 @@ where
}
#[derive(Default)]
#[allow(dead_code)]
struct HexEditorState {
offset_y: f32,
selected: usize,
@@ -311,10 +313,10 @@ where
&self,
tree: &Tree,
renderer: &mut R,
theme: &T,
style: &Style,
_theme: &T,
_style: &Style,
layout: Layout<'_>,
cursor: Cursor,
_cursor: Cursor,
viewport: &Rectangle,
) {
let state: &HexEditorState = tree.state.downcast_ref();

View File

@@ -46,11 +46,12 @@ use audio::Audio;
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "sprites.nes");
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "apu_pulse_channel_1.nes");
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "apu_pulse_channel_1_evelope.nes");
const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "apu_pulse_1.nes");
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "apu_pulse_1.nes");
// const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "apu_triangle.nes");
// const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
// const ROM_FILE: &str = "./cpu_timing_test.nes";
// const ROM_FILE: &str = "../nes-test-roms/instr_test-v5/official_only.nes";
const ROM_FILE: &str = "../Downloads/Legend of Zelda, The (USA).nes";
extern crate nes_emu;
@@ -453,7 +454,7 @@ impl Emulator {
dbg_image(DbgImage::PatternTable(self.nes.mem(), self.nes.ppu())).into()
}
Some(WindowType::Palette) => {
dbg_image(DbgImage::Palette(self.nes.mem(), self.nes.ppu())).into()
dbg_image(DbgImage::Palette(self.nes.ppu())).into()
}
Some(WindowType::Debugger) => column![
row![

View File

@@ -1729,7 +1729,12 @@ impl Cpu {
0xEA => inst!("NOP", 1, || {
log!("{addr:04X}: NOP");
}),
_ => todo!("ins: 0x{:04X}: 0x{ins:X}, {params:X?}", self.pc - 1),
// _ => todo!("ins: 0x{:04X}: 0x{ins:X}, {params:X?}", self.pc - 1),
_ => {
println!("ins: 0x{:04X}: 0x{ins:X}, {params:X?}", self.pc - 1);
self.halt();
ExecState::Done
}
}
}
@@ -1936,7 +1941,9 @@ impl Cpu {
}
pub fn reset(&mut self, mem: &mut CpuMem<'_>) {
let debug_log = self.debug_log.enabled();
*self = Self::init();
if debug_log { self.debug_log.enable(); }
self.pc = u16::from_le_bytes([mem.read(0xFFFC), mem.read(0xFFFD)]);
self.sp = 0xFD;
self.status.set_interrupt_disable(true);

View File

@@ -1,12 +1,12 @@
use std::num::NonZeroUsize;
// use std::num::NonZeroUsize;
#[derive(Debug, Clone)]
pub struct DebugLog {
enabled: bool,
current: String,
history: Vec<String>,
max_history: Option<NonZeroUsize>,
pos: usize,
// max_history: Option<NonZeroUsize>,
// pos: usize,
}
impl DebugLog {
@@ -15,8 +15,8 @@ impl DebugLog {
enabled: false,
current: String::new(),
history: vec![],
max_history: None,
pos: 0,
// max_history: None,
// pos: 0,
}
}
@@ -53,6 +53,10 @@ impl DebugLog {
pub fn enable(&mut self) {
self.enabled = true;
}
pub fn enabled(&self) -> bool {
self.enabled
}
}
impl std::fmt::Write for DebugLog {

View File

@@ -9,10 +9,10 @@ mod mem;
mod ppu;
#[cfg(test)]
mod test_roms;
pub use mem::{Memory, Mapped};
pub use mem::{Mapped, Memory};
pub use ppu::{Color, PPU, RenderBuffer, PPUMMRegisters};
pub use cpu::{Cpu, CycleResult, CPUMMRegisters};
pub use cpu::{CPUMMRegisters, Cpu, CycleResult};
pub use ppu::{Color, PPU, PPUMMRegisters, RenderBuffer};
// #[cfg(not(target_arch = "wasm32"))]
// use tokio::io::AsyncReadExt as _;
@@ -260,16 +260,16 @@ impl NES {
pub fn reset(&mut self) {
self.clock_count = 0;
// dbg_int: false,
// dbg_int: false,
// clock_count: 0,
// mapped,
// cpu: Cpu::init(),
// dma: DmaState::Passive,
// // ppu: PPU::with_chr_rom(chr_rom, mapper),
// ppu: PPU::init(),
// apu: APU::init(),
// controller: Controllers::init(),
// clock_count: 0,
// mapped,
// cpu: Cpu::init(),
// dma: DmaState::Passive,
// // ppu: PPU::with_chr_rom(chr_rom, mapper),
// ppu: PPU::init(),
// apu: APU::init(),
// controller: Controllers::init(),
self.cpu.reset(&mut CpuMem::new(
&mut self.mapped,
&mut self.ppu,
@@ -284,11 +284,11 @@ impl NES {
}
pub fn power_cycle(&mut self) {
// self.memory.clear();
// self.ppu.reset();
// self.ppu.memory.clear();
let debug_log = self.debug_log().enabled();
*self = Self::from_mem(self.mapped.power_cylce());
// self.memory.power_cycle();
if debug_log {
self.debug_log_mut().enable();
}
self.reset();
}

View File

@@ -107,7 +107,7 @@ enum OamState {
ReadTile,
ReadAttrs,
ReadX,
OverflowScan,
// OverflowScan,
Wait,
}
@@ -194,7 +194,7 @@ impl OAM {
self.state = OamState::Wait; // Should be Overflow scan...
}
}
OamState::OverflowScan => todo!(),
// OamState::OverflowScan => todo!(),
OamState::Wait => (),
}
}

View File

@@ -10,28 +10,28 @@ macro_rules! rom_test {
($name:ident, $rom:literal, timeout = $timeout:expr, |$nes:ident| $eval:expr) => {
#[test]
fn $name() {
let rom_file = concat!(env!("ROM_DIR"), "/", $rom);
println!("{}: {}", stringify!($name), rom_file);
let mut $nes = crate::NES::load_nes_file(rom_file).expect("Failed to create nes object");
$nes.reset_and_run_with_timeout($timeout);
println!("Final: {:?}", $nes);
$eval
}
};
($name:ident, . $rom:literal, |$nes:ident| $eval:expr) => {
rom_test!($name, . $rom, timeout = 10000000, |$nes| $eval);
};
($name:ident, . $rom:literal, timeout = $timeout:expr, |$nes:ident| $eval:expr) => {
#[test]
fn $name() {
let rom_file = $rom;
println!("{}: {}", stringify!($name), rom_file);
let mut $nes = crate::NES::load_nes_file(rom_file).expect("Failed to create nes object");
let rom_file = include_bytes!(concat!(env!("ROM_DIR"), "/", $rom));
println!("{}: {}", stringify!($name), concat!(env!("ROM_DIR"), "/", $rom));
let mut $nes = crate::NES::load_nes_file_mem(rom_file).expect("Failed to create nes object");
$nes.reset_and_run_with_timeout($timeout);
println!("Final: {:?}", $nes);
$eval
}
};
// ($name:ident, . $rom:literal, |$nes:ident| $eval:expr) => {
// rom_test!($name, . $rom, timeout = 10000000, |$nes| $eval);
// };
// ($name:ident, . $rom:literal, timeout = $timeout:expr, |$nes:ident| $eval:expr) => {
// #[test]
// fn $name() {
// let rom_file = $rom;
// println!("{}: {}", stringify!($name), rom_file);
// let mut $nes = crate::NES::load_nes_file(rom_file).expect("Failed to create nes object");
// $nes.reset_and_run_with_timeout($timeout);
// println!("Final: {:?}", $nes);
// $eval
// }
// };
}
pub(crate) use rom_test;