diff --git a/gemmaegui/src/bin/support/gemma_egui_support.rs b/gemmaegui/src/bin/support/gemma_egui_support.rs index eccf7a2..c7a0a93 100644 --- a/gemmaegui/src/bin/support/gemma_egui_support.rs +++ b/gemmaegui/src/bin/support/gemma_egui_support.rs @@ -111,7 +111,7 @@ impl GemmaEguiSupport { pub fn memory_view(system: &Chip8Computer, ui: &mut Ui) { ui.label("Memory View"); - for i in (0..=0x200).step_by(16) { + for i in (0..0x200).step_by(16) { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { for y in 0..16 { ui.label(format!("{:02x}", system.memory.peek((i + y) as u16)).as_str()); diff --git a/gemmasdl2/Cargo.toml b/gemmasdl2/Cargo.toml deleted file mode 100644 index 0028fbc..0000000 --- a/gemmasdl2/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "gemmasdl2" -version = "0.1.0" -edition = "2021" - -[dependencies] -gemma = { path = "../gemma" } -egui_sdl2_platform = "0.3.0" -gl = "0.14" -egui = "0.27" -egui_glow = "0.27" - -pollster = "0.2" -anyhow = "1.0" diff --git a/gemmasdl2/src/bin/gemmasdl2.rs b/gemmasdl2/src/bin/gemmasdl2.rs deleted file mode 100644 index acff6dc..0000000 --- a/gemmasdl2/src/bin/gemmasdl2.rs +++ /dev/null @@ -1,171 +0,0 @@ -mod support; -use crate::support::gemma_egui_support::GemmaEguiSupport; -use anyhow::Context; -use egui::TextBuffer; -use egui_glow::glow::{HasContext, COLOR_BUFFER_BIT}; -use egui_sdl2_platform::sdl2; -use gemma::chip8::computer::Chip8Computer; -use sdl2::event::{Event, WindowEvent}; -use std::{sync::Arc, time::Instant}; -use support::timestep::TimeStep; - -const SCREEN_WIDTH: u32 = 800; -const SCREEN_HEIGHT: u32 = 480; - -async fn run() -> anyhow::Result { - // Initialize SDL2 and video subsystem - let sdl = sdl2::init().map_err(|e| anyhow::anyhow!("Failed to create SDL context: {}", e))?; - let mut video = sdl - .video() - .map_err(|e| anyhow::anyhow!("Failed to initialize SDL video subsystem: {}", e))?; - - // Create SDL2 window and OpenGL context - let window = video - .window("Window", SCREEN_WIDTH, SCREEN_HEIGHT) - .opengl() - .position_centered() - .build()?; - let _gl_context = window - .gl_create_context() - .expect("Failed to create GL context"); - - // Load OpenGL functions - let gl = unsafe { - egui_glow::painter::Context::from_loader_function(|name| { - video.gl_get_proc_address(name) as *const _ - }) - }; - let mut painter = egui_glow::Painter::new(Arc::new(gl), "", None)?; - - // Setup Egui and SDL2 platform - let mut platform = egui_sdl2_platform::Platform::new(window.size())?; - let mut event_pump = sdl - .event_pump() - .map_err(|e| anyhow::anyhow!("Failed to get SDL event pump: {}", e))?; - - // Initial settings - let color = [0.0, 0.0, 0.0, 1.0]; // Background color - let start_time = Instant::now(); - let mut timestep = TimeStep::new(); - - let mut computer = Chip8Computer::new(); - let mut is_running: bool = false; - computer.load_bytes_to_memory(0x200, &std::fs::read("resources/roms/3-corax+.ch8")?); - - // Main loop - 'main: loop { - // Update the Egui platform with the current time - platform.update_time(start_time.elapsed().as_secs_f64()); - - // Begin Egui frame - let ctx = platform.context(); - - if is_running { - computer.step_system(); - } - - egui::Window::new("Hello, world!").show(&ctx, |ui| { - GemmaEguiSupport::video_view(&computer, ui); - GemmaEguiSupport::memory_view(&computer, ui); - GemmaEguiSupport::registers_view(&computer, ui); - }); - - // Process Egui frame - let full_output = platform.end_frame(&mut video)?; - let paint_jobs = platform.tessellate(&full_output); - - // Clear the screen with the current color - unsafe { - painter.gl().clear_color(color[0], color[1], color[2], 1.0); - painter.gl().clear(COLOR_BUFFER_BIT); - } - - // Paint Egui outputs and update textures - let size = window.size(); - painter.paint_and_update_textures( - [size.0, size.1], - 1.0, - paint_jobs.as_slice(), - &full_output.textures_delta, - ); - window.gl_swap_window(); - - // Run the timestep logic - timestep.run_this(|_| {}); - - // Handle SDL2 events - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDown { - keycode: Some(sdl2::keyboard::Keycode::Escape), - .. - } => break 'main, - Event::Window { - window_id, - win_event, - .. - } if window_id == window.id() => { - if let WindowEvent::Close = win_event { - break 'main; - } - } - Event::KeyUp { - keycode: Some(sdl2::keyboard::Keycode::F3), - .. - } => { - println!("USER PRESSED F3 -> running"); - is_running = true; - } - Event::KeyUp { - keycode: Some(sdl2::keyboard::Keycode::F4), - .. - } => { - println!("USER PRESSED F4 -> stopping"); - is_running = false; - } - Event::KeyDown { - keycode: Some(sdl2::keyboard::Keycode::F5), - .. - } => { - println!("USER PRESSED F5 -> Step"); - computer.step_system(); - } - Event::KeyDown { - keycode: Some(sdl2::keyboard::Keycode::F6), - .. - } => { - println!("USER PRESSED F6 -> RESET"); - computer.reset(computer.quirk_mode.clone()); - } - Event::ControllerButtonDown { which, .. } => { - println!("PLAYER {which} DOWN"); - } - Event::JoyButtonDown { button_idx, .. } => { - println!("JoyButtonDown {}", button_idx); - } - Event::JoyAxisMotion { - which, axis_idx, .. - } => { - println!("JoyAxismotion {which} {axis_idx}"); - } - _ => platform.handle_event(&event, &sdl, &video), - } - } - - // Optionally log the frame rate - if let Some(fps) = timestep.frame_rate() { - println!("{:?} fps", fps); - } - - let num_js = sdl.joystick().unwrap().num_joysticks().unwrap(); - println!("NUM JS = {num_js}"); - } - - Ok(("").parse()?) -} - -fn main() -> anyhow::Result<()> { - pollster::block_on(run())?; - Ok(()) -} diff --git a/gemmasdl2/src/bin/support/gemma_egui_support.rs b/gemmasdl2/src/bin/support/gemma_egui_support.rs deleted file mode 100644 index 3f4eda3..0000000 --- a/gemmasdl2/src/bin/support/gemma_egui_support.rs +++ /dev/null @@ -1,151 +0,0 @@ -use crate::Chip8Computer; -use egui::Rect; -use egui::Ui; -use egui::Vec2; -use egui::{Align, Color32, ComboBox, Pos2}; -use std::fs::read_dir; -use std::path::PathBuf; - -const CELL_WIDTH: f32 = 5.0; -const CELL_HEIGHT: f32 = 5.0; - -pub struct EGuiFileList {} -impl EGuiFileList { - pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) { - let working_filename = selected_filename.clone(); - ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { - // ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path"))); - ComboBox::from_label("Select ROM") - .selected_text(selected_filename.clone()) - .show_ui(ui, |ui| { - let mut sorted_options = vec![]; - for option in read_dir(root.as_path()).unwrap() { - let to_push = option - .unwrap() - .file_name() - .into_string() - .unwrap_or(String::new()); - sorted_options.push(to_push); - } - - sorted_options.sort(); - for item in sorted_options { - // Add each option to the ComboBox - if ui - .selectable_label(selected_filename.eq(&item.as_str()), item.clone()) - .clicked() - { - *selected_filename = item; - } - } - }); - // Display the selected option - }); - } -} - -pub struct GemmaEguiSupport {} - -impl GemmaEguiSupport { - pub fn controls_view(system: &mut Chip8Computer, ui: &mut Ui) { - ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { - if ui.button("Start").clicked() { - println!("Start"); - // state.is_running = true; - } - if ui.button("Step").clicked() { - system.step_system(); - } - - if ui.button("Stop").clicked() { - println!("STOP"); - // state.is_running = false; - } - if ui.button("Reset").clicked() { - system.reset(system.quirk_mode.clone()); - // state.is_running = false; - } - }); - - // if ui.button(format!("Load {}", state.selected_rom_filename)).clicked() { - // load the bin... - // let read_bin = std::fs::read(PathBuf::from(format!("resources/roms/{}", state.selected_rom_filename))).unwrap(); - // ...then feed the system. - // system.load_bytes_to_memory(0x200, &read_bin); - // println!("Loaded {}", state.selected_rom_filename); - // } - // EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_rom_filename, ui); - - ui.with_layout(egui::Layout::left_to_right(Align::TOP), |ui| { - // ui.checkbox(&mut state.display_memory, "Display Memory"); - // ui.checkbox(&mut state.display_video, "Display Video"); - // ui.checkbox(&mut state.display_registers, "Display Registers"); - }); - } - - pub fn registers_view(system: &Chip8Computer, ui: &mut Ui) { - ui.label(format!( - "V0-7: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ", - system.registers.peek(0x00), - system.registers.peek(0x01), - system.registers.peek(0x02), - system.registers.peek(0x03), - system.registers.peek(0x04), - system.registers.peek(0x05), - system.registers.peek(0x06), - system.registers.peek(0x07) - )); - ui.label(format!( - "V8-F: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ", - system.registers.peek(0x08), - system.registers.peek(0x09), - system.registers.peek(0x0A), - system.registers.peek(0x0B), - system.registers.peek(0x0C), - system.registers.peek(0x0D), - system.registers.peek(0x0E), - system.registers.peek(0x0F) - )); - ui.label(format!( - "PC: {:04x}\tI: {:04x}", - system.registers.peek_pc(), - system.registers.peek_i() - )); - } - - pub fn video_view(system: &Chip8Computer, ui: &mut Ui) { - let (_resp, painter) = ui.allocate_painter(Vec2::new(350.0, 165.0), egui::Sense::hover()); - for current_row in 0..32 { - for current_col in 0..64 { - let data_offset = current_row * 64 + current_col; - let x_offset = current_col as f32 * CELL_WIDTH; - let y_offset = current_row as f32 * CELL_HEIGHT; - let origin = Pos2::new(x_offset, y_offset); - let colour = if system.video_memory.peek(data_offset) { - Color32::RED - } else { - Color32::WHITE - }; - let rect = Rect::from_min_size(origin, Vec2::new(CELL_WIDTH, CELL_HEIGHT)); - painter.rect_filled(rect, 0.0, colour); - // println!("Cell {current_col}x{current_row} at {}x{} -> {}", - // origin.x, origin.y, - // system.video_memory.peek(data_offset)); - } - } - // thread::sleep(Duration::from_secs(1)); - } - - pub fn memory_view(system: &Chip8Computer, ui: &mut Ui) { - ui.label("Memory View"); - - for i in (0..=0x200).step_by(16) { - ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { - for y in 0..16 { - ui.label(format!("{:02x}", system.memory.peek((i + y) as u16)).as_str()); - } - }); - } - ui.label("Should have **something** to adjust the 'memory window'"); - } -} diff --git a/gemmasdl2/src/bin/support/mod.rs b/gemmasdl2/src/bin/support/mod.rs deleted file mode 100644 index 646b816..0000000 --- a/gemmasdl2/src/bin/support/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod timestep; -pub mod gemma_egui_support; diff --git a/gemmasdl2/src/bin/support/timestep.rs b/gemmasdl2/src/bin/support/timestep.rs deleted file mode 100644 index 3c6327b..0000000 --- a/gemmasdl2/src/bin/support/timestep.rs +++ /dev/null @@ -1,95 +0,0 @@ - -//! Gameplay speed control. It attempts to mimic/limit progression to -//! the 30 tics per second Doom used. - -use std::{fmt, time::Instant}; - -const MS_PER_UPDATE: f32 = 28.57; - -#[derive(Debug)] -pub struct TimeStep { - last_time: Instant, - delta_time: f32, - frame_count: u32, - frame_time: f32, - run_tics: u32, - last_tics: u32, - lag: f32, -} - -#[derive(Debug)] -pub struct FrameData { - pub tics: u32, - pub frames: u32, -} - -impl fmt::Display for FrameData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "FrameData (per-second):\n - tics: {}\n - fps: {}", - self.tics, self.frames - )) - } -} - -impl TimeStep { - pub fn new() -> TimeStep { - TimeStep { - last_time: Instant::now(), - delta_time: 0.0, - frame_count: 0, - frame_time: 0.0, - run_tics: 0, - last_tics: 0, - lag: 0.0, - } - } - - pub fn delta(&mut self) -> f32 { - let current_time = Instant::now(); - let delta = current_time.duration_since(self.last_time).as_micros() as f32 * 0.001; - self.last_time = current_time; - self.delta_time = delta; - delta - } - - /// Increments self time and returns current lag. `run_this` is run only for - /// `n` tics available. - pub fn run_this(&mut self, mut run_this: impl FnMut(f32)) { - let dt = self.delta(); - self.lag += dt; - while self.lag >= MS_PER_UPDATE { - run_this(dt); - self.lag -= MS_PER_UPDATE; - self.run_tics += 1; - } - } - - pub fn frame_rate(&mut self) -> Option { - self.frame_count += 1; - self.frame_time += self.delta_time; - let tmp; - let tmp2; - // per second - if self.frame_time >= 1000.0 { - tmp = self.frame_count; - tmp2 = self.last_tics; - self.frame_count = 0; - self.frame_time = 0.0; - self.last_tics = self.run_tics; - return Some(FrameData { - tics: self.run_tics - tmp2, - frames: tmp, - }); - } - - None - } -} - -impl Default for TimeStep { - // shutup clippy! - fn default() -> Self { - Self::new() - } -} \ No newline at end of file