use std::collections::{HashMap, VecDeque}; use crsn::asm::data::literal::Value; use crsn::asm::instr::Cond; use crsn::module::{CrsnExtension, EvalRes, OpTrait}; use crsn::runtime::fault::Fault; use crsn::runtime::run_thread::{state::RunState, ThreadInfo}; use crate::defs::ScreenOp; use minifb::{Window, WindowOptions, ScaleMode}; use parking_lot::Mutex; use std::sync::Arc; #[derive(Debug, Default)] struct Backend { width: usize, height: usize, buffer: Vec, window: Option, } // Hack for Window unsafe impl std::marker::Send for Backend { } impl OpTrait for ScreenOp { fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result { let eres = EvalRes::default(); match self { ScreenOp::ScreenInit { width, height } => { let w = state.read(*width)?; let h = state.read(*height)?; init(state, w, h)?; } ScreenOp::SetPixel { x, y, color } => { let x = state.read(*x)?; let y = state.read(*y)?; let color = state.read(*color)?; let backend : &mut Backend = state.ext_mut(); match &mut backend.window { Some(w) => { let index = y * backend.width as u64 + x; if index as usize > backend.buffer.len() { warn!("Screen set pixel out of bounds"); state.set_flag(Cond::Invalid, true); } else { backend.buffer[index as usize] = color as u32; w .update_with_buffer(&backend.buffer, backend.width, backend.height) .expect("Update screen"); // TODO fault } } None => { state.set_flag(Cond::Invalid, true); } } } } Ok(eres) } // } fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault> { let mut window = Window::new( "Croissant", width as usize, height as usize, WindowOptions { resize: true, scale_mode: ScaleMode::AspectRatioStretch, ..WindowOptions::default() }, ).expect("Unable to create window"); // TODO fault let backend : &mut Backend = state.ext_mut(); if backend.window.is_some() { return Err(Fault::NotAllowed("Screen already initialized".into())); } backend.width = width as usize; backend.height = height as usize; backend.buffer = vec![0; (width * height) as usize]; // window.limit_update_rate(Some(std::time::Duration::from_micros(16600))); window.limit_update_rate(None); window .update_with_buffer(&backend.buffer, backend.width, backend.height) .expect("Update screen"); // TODO fault backend.window = Some(window); Ok(()) }