142 lines
5.2 KiB
Rust
142 lines
5.2 KiB
Rust
mod support;
|
|
use std::{sync::Arc, time::Instant};
|
|
use anyhow::Context;
|
|
use egui::TextBuffer;
|
|
use egui_glow::glow::{HasContext, COLOR_BUFFER_BIT};
|
|
use egui_sdl2_platform::sdl2;
|
|
use sdl2::event::{Event, WindowEvent};
|
|
use gemma::chip8::computer::Chip8Computer;
|
|
use support::timestep::TimeStep;
|
|
use crate::support::gemma_egui_support::GemmaEguiSupport;
|
|
|
|
const SCREEN_WIDTH: u32 = 800;
|
|
const SCREEN_HEIGHT: u32 = 480;
|
|
|
|
async fn run() -> anyhow::Result<String> {
|
|
// 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();
|
|
}
|
|
Event::ControllerButtonDown { which, .. } => {
|
|
println!("PLAYER {which} DOWN");
|
|
}
|
|
Event::ControllerButtonDown { button, .. } => {
|
|
println!("BUTTON {:?}", button);
|
|
}
|
|
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(())
|
|
}
|