Finally find (& fix) bug in BIT instructions
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 26s

- BIT not longer ANDs the A register
- I now a pretty good debug view for debugging the CPU
- I wrote a number_input element for iced
- I upgraded to iced 0.14
- I added images for play and pause
- The debug log now displays in the debug view
This commit is contained in:
2025-12-14 13:10:57 -06:00
parent fecef26e2f
commit af770d232c
14 changed files with 2325 additions and 1330 deletions

View File

@@ -1,15 +1,12 @@
use std::{
collections::HashMap,
fmt,
io::{Read, stdin},
};
use iced::{
Color, Element, Font,
Length::Fill,
Point, Renderer, Size, Subscription, Task, Theme, Vector,
futures::io::Window,
mouse,
Point, Renderer, Size, Subscription, Task, Theme, mouse,
widget::{
Canvas, button,
canvas::{Frame, Program},
@@ -18,13 +15,13 @@ use iced::{
window::{self, Id, Settings},
};
use nes_emu::{
NES, PPU, RenderBuffer,
header_menu::header_menu,
hex_view::{self, HexEvent, HexView},
debugger::{DebuggerMessage, DebuggerState}, header_menu::header_menu, hex_view::{HexEvent, HexView}, NES, PPU
};
use tracing::{debug, info};
use tracing_subscriber::EnvFilter;
const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "basic_init_1.nes");
// const ROM_FILE: &str = "./Super Mario Bros. (World).nes";
extern crate nes_emu;
fn main() -> Result<(), iced::Error> {
@@ -32,16 +29,11 @@ fn main() -> Result<(), iced::Error> {
.with_env_filter(EnvFilter::from_default_env())
.init();
iced::daemon(Emulator::title, Emulator::update, Emulator::view)
iced::daemon(Emulator::new, Emulator::update, Emulator::view)
.subscription(Emulator::subscriptions)
.theme(|_, _| Theme::Dark)
.run_with(Emulator::new)
// iced::application(title, Emulator::update, Emulator::view)
// .subscription(Emulator::subscriptions)
// .theme(|_| Theme::Dark)
// .centered()
// .run()
.theme(Theme::Dark)
.title(Emulator::title)
.run()
}
enum MemoryTy {
@@ -53,6 +45,7 @@ enum WindowType {
Memory(MemoryTy, HexView),
TileMap,
TileViewer,
Debugger,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -60,6 +53,7 @@ enum HeaderButton {
OpenMemory,
OpenTileMap,
OpenTileViewer,
OpenDebugger,
Reset,
PowerCycle,
}
@@ -70,6 +64,7 @@ impl fmt::Display for HeaderButton {
Self::OpenMemory => write!(f, "Open Memory Viewer"),
Self::OpenTileMap => write!(f, "Open TileMap Viewer"),
Self::OpenTileViewer => write!(f, "Open Tile Viewer"),
Self::OpenDebugger => write!(f, "Open Debugger"),
Self::Reset => write!(f, "Reset"),
Self::PowerCycle => write!(f, "Power Cycle"),
}
@@ -79,6 +74,7 @@ impl fmt::Display for HeaderButton {
struct Emulator {
nes: NES,
windows: HashMap<Id, WindowType>,
debugger: DebuggerState,
}
#[derive(Debug, Clone)]
@@ -92,13 +88,12 @@ enum Message {
WindowClosed(Id),
Header(HeaderButton),
Hex(Id, HexEvent),
Debugger(DebuggerMessage),
}
impl Emulator {
fn new() -> (Self, Task<Message>) {
let rom_file = concat!(env!("ROM_DIR"), "/", "basic_init_1.nes");
// let rom_file = "./Super Mario Bros. (World).nes";
let mut nes = nes_emu::NES::load_nes_file(rom_file)
let mut nes = nes_emu::NES::load_nes_file(ROM_FILE)
.expect("Failed to load nes file");
nes.reset();
let (win, task) = iced::window::open(Settings::default());
@@ -106,6 +101,7 @@ impl Emulator {
Self {
nes,
windows: HashMap::from_iter([(win, WindowType::Main)]),
debugger: DebuggerState::new(),
},
task.map(Message::WindowOpened),
)
@@ -116,6 +112,7 @@ impl Emulator {
Some(WindowType::Memory(_, _)) => "NES MemoryView".into(),
Some(WindowType::TileMap) => "NES TileMap".into(),
Some(WindowType::TileViewer) => "NES Tile Viewer".into(),
Some(WindowType::Debugger) => "NES Debugger".into(),
None => todo!(),
}
}
@@ -129,38 +126,42 @@ impl Emulator {
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::Tick(count) => {
for _ in 0..count {
self.nes.run_one_clock_cycle();
}
}
for _ in 0..count {
self.nes.run_one_clock_cycle();
}
}
Message::Frame => while !self.nes.run_one_clock_cycle().ppu_frame {},
Message::DMA => while !self.nes.run_one_clock_cycle().dma {},
Message::CPU => while !self.nes.run_one_clock_cycle().cpu_exec {},
Message::DebugInt => while !self.nes.run_one_clock_cycle().dbg_int {},
Message::WindowOpened(id) => {
// Window
}
Message::WindowOpened(_id) => {
// Window
}
Message::WindowClosed(id) => {
if let Some(WindowType::Main) = self.windows.remove(&id) {
return iced::exit();
}
}
if let Some(WindowType::Main) = self.windows.remove(&id) {
return iced::exit();
}
}
Message::Header(HeaderButton::OpenMemory) => {
return self.open(WindowType::Memory(MemoryTy::Cpu, HexView::new()));
}
return self.open(WindowType::Memory(MemoryTy::Cpu, HexView::new()));
}
Message::Header(HeaderButton::OpenTileMap) => {
return self.open(WindowType::TileMap);
}
return self.open(WindowType::TileMap);
}
Message::Header(HeaderButton::OpenTileViewer) => {
return self.open(WindowType::TileViewer);
}
return self.open(WindowType::TileViewer);
}
Message::Header(HeaderButton::OpenDebugger) => {
return self.open(WindowType::Debugger);
}
Message::Hex(id, val) => {
if let Some(WindowType::Memory(_, view)) = self.windows.get_mut(&id) {
return view.update(val).map(move |e| Message::Hex(id, e));
}
}
if let Some(WindowType::Memory(_, view)) = self.windows.get_mut(&id) {
return view.update(val).map(move |e| Message::Hex(id, e));
}
}
Message::Header(HeaderButton::Reset) => { self.nes.reset(); }
Message::Header(HeaderButton::PowerCycle) => { self.nes.power_cycle(); }
Message::Debugger(debugger_message) => self.debugger.update(debugger_message, &mut self.nes),
}
// self.image.0.clone_from(self.nes.image());
Task::none()
@@ -197,7 +198,11 @@ impl Emulator {
Some(WindowType::TileViewer) => {
container(Canvas::new(DbgImage::NameTable(self.nes.ppu()))).width(Fill).height(Fill).into()
}
_ => todo!(),
Some(WindowType::Debugger) => {
container(self.debugger.view(&self.nes).map(Message::Debugger)).width(Fill).height(Fill).into()
}
None => panic!("Window not found"),
// _ => todo!(),
}
}
@@ -235,6 +240,7 @@ impl Emulator {
header_menu(
"Debugging",
[
HeaderButton::OpenDebugger,
HeaderButton::OpenMemory,
HeaderButton::OpenTileMap,
HeaderButton::OpenTileViewer,
@@ -252,13 +258,13 @@ impl Program<Message> for Emulator {
fn draw(
&self,
state: &Self::State,
_state: &Self::State,
renderer: &Renderer,
theme: &Theme,
bounds: iced::Rectangle,
_theme: &Theme,
_bounds: iced::Rectangle,
_cursor: mouse::Cursor,
) -> Vec<iced::widget::canvas::Geometry<Renderer>> {
const SIZE: f32 = 2.;
// const SIZE: f32 = 2.;
let mut frame = Frame::new(
renderer,
iced::Size {
@@ -291,13 +297,13 @@ impl Program<Message> for DbgImage<'_> {
fn draw(
&self,
state: &Self::State,
_state: &Self::State,
renderer: &Renderer,
theme: &Theme,
bounds: iced::Rectangle,
_theme: &Theme,
_bounds: iced::Rectangle,
_cursor: mouse::Cursor,
) -> Vec<iced::widget::canvas::Geometry<Renderer>> {
const SIZE: f32 = 2.;
// const SIZE: f32 = 2.;
let mut name_table_frame =
Frame::new(renderer, Size::new(256. * 4. + 260. * 2., 256. * 4.));
name_table_frame.scale(2.);