diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5317f31 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +test: + cargo test + +clippy: + cargo clippy --all-targets --all-features + +run: + cargo run --bin snes-frontend + +run-release: + cargo run --bin snes-frontend --release + diff --git a/snes-core/src/cpu/bus.rs b/snes-core/src/cpu/bus.rs index 7bc1c01..32b3cfb 100644 --- a/snes-core/src/cpu/bus.rs +++ b/snes-core/src/cpu/bus.rs @@ -35,6 +35,12 @@ impl Bus { } } + pub fn hard_reset(&mut self) { + self.wram = [0; 0x10000]; + self.internal_registers = InternalRegisters::new(); + self.dma = DMA::new(); + } + fn read_wram(&self, address: u32) -> u8 { self.wram[(address & 0xFFFF) as usize] } diff --git a/snes-core/src/emulator.rs b/snes-core/src/emulator.rs index edf9040..3369ce9 100644 --- a/snes-core/src/emulator.rs +++ b/snes-core/src/emulator.rs @@ -34,9 +34,15 @@ impl Emulator { } } - pub fn reset(&mut self) { + pub fn reset_vector(&mut self) { self.cpu.reset_vector(&mut self.bus); } + + pub fn hard_reset(&mut self) { + self.cpu = CPU::new(); + self.bus.hard_reset(); + self.reset_vector(); + } } impl Default for Emulator { diff --git a/snes-core/src/ppu/interface.rs b/snes-core/src/ppu/interface.rs index ecd5848..ac655a3 100644 --- a/snes-core/src/ppu/interface.rs +++ b/snes-core/src/ppu/interface.rs @@ -94,6 +94,7 @@ impl PPU { // ---- // possible optimizations: // - Fetch all of the necessary data before starting to render the scanline + // - Pre-render each background in a framebuffer and only update the framebuffer if either the tileset or charset changes let tileset_vram_base_address = self.registers.get_bg_tile_base_address(background) as usize; let charset_vram_base_address = self.registers.get_bg_char_base_address(background) as usize; let (bg_size_width, _) = self.registers.get_bg_size(background).to_usize(); diff --git a/snes-core/src/rom/lo_rom.rs b/snes-core/src/rom/lo_rom.rs index 5288dea..d48d509 100644 --- a/snes-core/src/rom/lo_rom.rs +++ b/snes-core/src/rom/lo_rom.rs @@ -20,6 +20,7 @@ impl LoROM { impl ROM for LoROM { fn load(&mut self, filename: &str) -> std::io::Result { + self.data = vec![]; load_rom(filename, &mut self.data) } diff --git a/snes-frontend/Cargo.toml b/snes-frontend/Cargo.toml index 87d9c75..db574b2 100644 --- a/snes-frontend/Cargo.toml +++ b/snes-frontend/Cargo.toml @@ -9,11 +9,11 @@ edition = "2021" snes-core = { path = "../snes-core" } # Frontend stuff -eframe = "0.26.0" +eframe = "0.29.1" env_logger = "0.10.1" rfd = "0.12.1" regex = "1.10.2" -wgpu = "0.19.0" +wgpu = "23.0.0" [features] wgpu = ["eframe/wgpu"] diff --git a/snes-frontend/src/emu_ui/debug/cpu.rs b/snes-frontend/src/emu_ui/debug/cpu.rs index d1923d3..a8a0020 100644 --- a/snes-frontend/src/emu_ui/debug/cpu.rs +++ b/snes-frontend/src/emu_ui/debug/cpu.rs @@ -34,7 +34,7 @@ pub fn build_cpu_debug_controls(ctx: &egui::Context, cpu_debug_options: &mut CPU ui.monospace("Vectors:"); ui.horizontal(|ui| { if ui.button("Reset").clicked() { - emulator.reset(); + emulator.reset_vector(); } }); ui.separator(); diff --git a/snes-frontend/src/emu_ui/debug/ppu_graphics.rs b/snes-frontend/src/emu_ui/debug/ppu_graphics.rs index 6e7e077..47fef41 100644 --- a/snes-frontend/src/emu_ui/debug/ppu_graphics.rs +++ b/snes-frontend/src/emu_ui/debug/ppu_graphics.rs @@ -223,7 +223,7 @@ fn paint_texture(ui: &mut Ui, texture: &mut Option, framebuffer: if let Some(txt) = texture { txt.set( ColorImage::from_rgba_premultiplied([width, height], framebuffer), - TextureOptions::default(), + TextureOptions::LINEAR, ); let (whole_rect, _) = ui.allocate_exact_size(Vec2::from([(width * 2) as f32, (height * 2) as f32]), egui::Sense::focusable_noninteractive()); diff --git a/snes-frontend/src/emu_ui/game.rs b/snes-frontend/src/emu_ui/game.rs index 2ed9760..4e9fabc 100644 --- a/snes-frontend/src/emu_ui/game.rs +++ b/snes-frontend/src/emu_ui/game.rs @@ -1,4 +1,4 @@ -use eframe::egui; +use eframe::egui::{self, Pos2, Rect}; use eframe::{egui::Context, epaint::ColorImage}; use eframe::egui::{TextureOptions, Ui}; use eframe::epaint::{Vec2, TextureHandle}; @@ -12,11 +12,12 @@ pub fn build_game_window( ctx: &egui::Context, game_tv_texture: &mut Option, framebuffer: &[u8], + current_res: (u16, u16), ) { egui::Window::new("TV") .collapsible(false) .show(ctx, |ui| { - paint_game_texture(ui, game_tv_texture, framebuffer); + paint_game_texture(ui, game_tv_texture, framebuffer, current_res); }); } @@ -33,21 +34,34 @@ pub fn initialize_game_texture(ctx: &Context, game_tv_texture: &mut Option, framebuffer: &[u8]) { +fn paint_game_texture(ui: &mut Ui, texture: &mut Option, framebuffer: &[u8], current_res: (u16, u16)) { if let Some(txt) = texture { txt.set( ColorImage::from_rgba_premultiplied([MAX_TV_WIDTH, MAX_TV_HEIGHT], framebuffer), - TextureOptions::default(), + TextureOptions::LINEAR, ); let (whole_rect, _) = ui.allocate_exact_size( Vec2::from([(MAX_TV_WIDTH) as f32, (MAX_TV_HEIGHT) as f32]), egui::Sense::focusable_noninteractive(), ); + let current_resolution_scale = calculate_resolution_scale(current_res); egui::Image::new(( txt.id(), txt.size_vec2(), )) + .texture_options(TextureOptions::LINEAR) + .uv(Rect::from_two_pos( + Pos2::new(0.0,0.0), + Pos2::new(current_resolution_scale.0, current_resolution_scale.1)) + ) .paint_at(ui, whole_rect); } } + +fn calculate_resolution_scale(current_res: (u16, u16)) -> (f32, f32) { + ( + current_res.0 as f32 / MAX_TV_WIDTH as f32, + current_res.1 as f32 / MAX_TV_HEIGHT as f32, + ) +} diff --git a/snes-frontend/src/emu_ui/menu.rs b/snes-frontend/src/emu_ui/menu.rs index 989e370..5316a14 100644 --- a/snes-frontend/src/emu_ui/menu.rs +++ b/snes-frontend/src/emu_ui/menu.rs @@ -10,10 +10,16 @@ pub fn build_menu_bar(emulator: &mut Emulator, ui: &mut egui::Ui, state: &mut Ap if ui.button("Load ROM file").clicked() { if let Some(path) = rfd::FileDialog::new().pick_file() { let picked_path = path.display().to_string(); + // TODO: replace this load function by an external function as each ROM may not always be LoROM match emulator.bus.rom.load(&picked_path) { - Ok(_) => println!("Loaded ROM"), + Ok(_) => { + emulator.hard_reset(); + state.emulation_state.is_paused = false; + state.emulation_state.one_tick_per_frame = false; + println!("Loaded ROM"); + }, Err(err) => println!("Error loading the ROM: {}", err), - } + }; } } }); diff --git a/snes-frontend/src/main.rs b/snes-frontend/src/main.rs index 2155e39..66506f8 100644 --- a/snes-frontend/src/main.rs +++ b/snes-frontend/src/main.rs @@ -30,6 +30,7 @@ impl eframe::App for SnesEmulatorApp { ctx, &mut self.state.game_tv_texture, self.emulator.bus.ppu.framebuffer(), + self.emulator.bus.ppu.registers.get_current_res(), ); emu_ui::debug::build_all_debug_options(ctx, &mut self.state.debug_options, &mut self.state.emulation_state, &mut self.emulator); if !self.state.emulation_state.is_paused { @@ -53,6 +54,6 @@ fn main() -> eframe::Result<()> { eframe::run_native( "SNES Emulator", native_options, - Box::new(|cc| Box::new(SnesEmulatorApp::new(cc))), + Box::new(|cc| Ok(Box::new(SnesEmulatorApp::new(cc)))), ) }