broken GUI impl + Broken PPU scrolling

This commit is contained in:
2026-08-10 22:02:37 -05:00
parent 6db56e8142
commit 2c0aa5f18f
4 changed files with 136 additions and 9 deletions
+60 -7
View File
@@ -12,6 +12,8 @@ use crate::bus::{Bus, NesBus};
use crate::cartridge::Cartridge;
use crate::cpu::Cpu;
use crate::render::{PpmRenderer, Renderer};
use eframe::egui;
use crate::render::WindowRenderer;
fn main() {
@@ -20,8 +22,9 @@ fn main() {
1 => run_nestest(),
3 if args[1] == "blargg" => run_blargg(&args[2]),
3 if args[1] == "dbg" => run_dbg(&args[2]),
3 if args[1] == "gui" => run_gui(&args[2]),
2 => run_cart(&args[1]),
_ => eprintln!("usage: rnes [<rom> | blargg <rom>]"),
_ => eprintln!("usage: rnes [<rom> | blargg <rom> | dbg <rom> | gui <rom>]"),
}
}
@@ -34,13 +37,8 @@ fn run_cart(path: &str) {
let frames: u32 = 180;
for _ in 0..frames {
while !bus.frame_done() {
let cycles = cpu.step(&mut bus);
bus.tick_ppu(cycles as u64);
if bus.take_nmi() { cpu.set_nmi(); } // NMI fires when vblank hits, mid-frame
}
run_one_frame(&mut bus, &mut cpu);
renderer.present(bus.framebuffer(), 256, 240);
bus.begin_frame();
}
}
@@ -94,4 +92,59 @@ fn run_dbg(path: &str) {
bus.begin_frame();
}
println!("wrote debug_out/ + renders/, {frames} frames");
}
fn run_one_frame(bus: &mut NesBus, cpu: &mut Cpu) {
while !bus.frame_done() {
let cycles = cpu.step(bus);
bus.tick_ppu(cycles as u64);
if bus.take_nmi() { cpu.set_nmi(); }
}
bus.begin_frame();
}
struct GuiApp {
bus: NesBus,
cpu: Cpu,
renderer: WindowRenderer,
}
impl GuiApp {
fn new(cc: &eframe::CreationContext<'_>, cart: Cartridge) -> Self {
let mut bus = NesBus::new(cart);
let mut cpu = Cpu::new();
cpu.reset(&mut bus);
let renderer = WindowRenderer::new(cc, 256, 240);
Self { bus, cpu, renderer }
}
}
impl eframe::App for GuiApp {
// Non-UI work: emulation runs here, before painting.
fn logic(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
self.renderer.poll_input(self.bus.controller_mut()); // keyboard -> $4016/$4017
run_one_frame(&mut self.bus, &mut self.cpu); // one emulated frame
self.renderer.present(self.bus.framebuffer(), 256, 240);
ctx.request_repaint(); // keep it running at 60fps
}
// Painting: draw the framebuffer texture.
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
self.renderer.draw(ui);
}
}
fn run_gui(path: &str) {
let cart = Cartridge::from_file(path).unwrap();
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_inner_size([1024.0, 960.0])
.with_title("rnes"),
..Default::default()
};
eframe::run_native(
"rnes",
options,
Box::new(move |cc| Ok(Box::new(GuiApp::new(cc, cart)))),
).expect("failed to run GUI");
}