diff --git a/README.md b/README.md index 376722a..c50b957 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,11 @@ syntaxe supplémentaire supportée: - depuis le sous dossier simu `cargo run --release fichierentre` -Pour rajouter le support de multiplication/division: rajouter --features=div_mul +## Features +rajouter --features=[liste séparé par des virgules] +- div_mul: Support des instruction de multiplication / division +- rgba: Écran au format RGBA plutot que 0BGR +- rich_keyboard: rajoute trois champs de mmio pour le clavier. Voir MMIO ### instruction spéciale: halt (jump 0) met le programme en pause, mais on peut se reveiller par des interuptions @@ -45,6 +49,13 @@ Passage au format RGBA (a pour alpha) avec la feature rgba - 0x01200010 : Position verticale de la souris (en pixels, -1 si hors de l'écran) (lecture seule) - 0x01201000 : Activation des Interupts de MMIO. Remis a zero par `dint`. Attention, Écrire ici sans activer les interruptions va bloquer les intéruptions et l'affichage (écriture seule) + +Si la feature rich_keyboard est active, tout en lecture seule: +- 0x01200000 - 12 : Clavier : Representation ascii multichar de la touche pressé, modifié par Alt, Ctrl ... (eg ascii(a), ascii(A), ascii(^)<<8 | ascii(a)) +- 0x01200000 - 8 : Clavier Representation ascii multichar non modifié (eg ascii(a), ascii(\)<<8 | ascii(r)) +- 0x01200000 - 4: Clavier (press | repeat << 1) press: 1 si appuis, 0 si relache. repeat: 1 si l'appuis vient d'une répétition due a l'OS +- 0x01200000 : Clavier (scancode, comme précédement) (lecture seule) + ## Interuptions: Si les interruptions sont activées (avec eint), qu'il y a une raison de faire une interruption, et qu'on n'est pas déjà dans une routine d'interruption de priorité >=, diff --git a/simu/Cargo.toml b/simu/Cargo.toml index f69878c..eb6384a 100644 --- a/simu/Cargo.toml +++ b/simu/Cargo.toml @@ -11,3 +11,5 @@ winit_input_helper = "0.17.0" [features] div_mul = [] +rgba = [] +rich_keyboard = [] diff --git a/simu/src/cpu.rs b/simu/src/cpu.rs index bc89507..4191ff0 100644 --- a/simu/src/cpu.rs +++ b/simu/src/cpu.rs @@ -10,7 +10,7 @@ use std::{ }; pub(crate) struct SharedState { - pub(crate) keyboard: AtomicU32, + pub(crate) keyboard: [AtomicU32; 4], pub(crate) screen_buf: [AtomicU32; 480 * 640], pub(crate) external_interupts: AtomicU32, pub(crate) external_enabled_interupts: AtomicU32, @@ -18,7 +18,7 @@ pub(crate) struct SharedState { } pub(crate) static SHARED: SharedState = SharedState { - keyboard: AtomicU32::new(0), + keyboard: [const { AtomicU32::new(0) }; 4], screen_buf: [const { AtomicU32::new(0) }; 480 * 640], external_interupts: AtomicU32::new(0), external_enabled_interupts: AtomicU32::new(0), @@ -432,9 +432,17 @@ impl Computer { let buf_addr = (addr - 0x0100_0000) / 4; (&SHARED.screen_buf[buf_addr]) .load(std::sync::atomic::Ordering::Relaxed) - } else if 0x0120_0000 <= addr && addr <= 0x0120_0010 { - match addr - 0x0120_0000 { - 0 => SHARED.keyboard.load(std::sync::atomic::Ordering::Relaxed), + } else { + match addr as isize - 0x0120_0000 { + #[cfg(feature = "rich_keyboard")] + -12 => { + SHARED.keyboard[0].load(std::sync::atomic::Ordering::Relaxed) + } + #[cfg(feature = "rich_keyboard")] + -8 => SHARED.keyboard[1].load(std::sync::atomic::Ordering::Relaxed), + #[cfg(feature = "rich_keyboard")] + -4 => SHARED.keyboard[2].load(std::sync::atomic::Ordering::Relaxed), + 0 => SHARED.keyboard[3].load(std::sync::atomic::Ordering::Relaxed), 4 => time::Instant::now() .duration_since(self.creation) .as_millis() as u32, @@ -442,11 +450,11 @@ impl Computer { 12 => SHARED.mouse[1].load(std::sync::atomic::Ordering::Relaxed), 16 => SHARED.mouse[2].load(std::sync::atomic::Ordering::Relaxed), //guaranted by the inequality and is multiple of 4 - _ => unsafe { unreachable_unchecked() }, + _ => { + self.serve_interupt(InteruptKind::IllegalOpcode, [next_opcode]); + return; + } } - } else { - self.serve_interupt(InteruptKind::IllegalOpcode, [next_opcode]); - return; }; } Instruction::Push(op2) => { @@ -506,7 +514,7 @@ impl Computer { match kind { InteruptKind::MMIO => { (&SHARED.external_interupts) - .store(0, std::sync::atomic::Ordering::Relaxed); + .store(0, std::sync::atomic::Ordering::Release); atomic_wait::wake_all(&SHARED.external_interupts); //no need to check prev because MMIO is the lowest priority self.interupts = InteruptState::Enabled diff --git a/simu/src/main.rs b/simu/src/main.rs index c59cba8..abbcf54 100644 --- a/simu/src/main.rs +++ b/simu/src/main.rs @@ -11,7 +11,7 @@ use std::hint::unlikely; use std::process::exit; use std::sync::{ Arc, - atomic::Ordering::{Relaxed, Release}, + atomic::Ordering::{Acquire, Relaxed, Release}, }; use std::thread::scope; use std::time::{Duration, Instant}; @@ -21,6 +21,7 @@ use winit::application::ApplicationHandler; use winit::dpi::LogicalSize; use winit::event::WindowEvent; use winit::event_loop::EventLoop; +use winit::platform::modifier_supplement::KeyEventExtModifierSupplement; use winit::platform::scancode::PhysicalKeyExtScancode; use winit::window::Window; // use winit_input_helper::WinitInputHelper; @@ -31,11 +32,11 @@ mod cpu; use cpu::SHARED; fn wait_int() { - let mut v = (&SHARED.external_interupts).load(Relaxed); + let mut v = (&SHARED.external_interupts).load(Acquire); while unlikely(v != 0) { println!("wating for interupt clear {v}"); atomic_wait::wait(&SHARED.external_interupts, v); - v = (&SHARED.external_interupts).load(std::sync::atomic::Ordering::Relaxed); + v = (&SHARED.external_interupts).load(Acquire); } } @@ -76,7 +77,9 @@ impl<'a> ApplicationHandler for App<'a> { ) { // Draw the current frame match event { - WindowEvent::KeyboardInput { event, .. } => { + WindowEvent::KeyboardInput { + event: key_event, .. + } => { let enabled = (&SHARED.external_enabled_interupts).load(Relaxed) & Into::::into(MMIOInterupt::Keyboard) != 0; @@ -84,18 +87,31 @@ impl<'a> ApplicationHandler for App<'a> { if enabled { wait_int(); } - match event.state { - winit::event::ElementState::Pressed => { - if let Some(val) = event.physical_key.to_scancode() { - cpu::SHARED - .keyboard - .store(val + 8, std::sync::atomic::Ordering::Relaxed); - } - } - winit::event::ElementState::Released => SHARED - .keyboard - .store(0, std::sync::atomic::Ordering::Relaxed), + #[cfg(feature = "rich_keyboard")] + { + let txt = key_event + .logical_key + .to_text() + .unwrap_or("") + .as_bytes() + .into_iter() + .fold(0, |a, e| a << 8 | (*e as u32)); + SHARED.keyboard[0].store(txt, Relaxed); + let txt = key_event + .key_without_modifiers() + .to_text() + .unwrap_or("") + .as_bytes() + .into_iter() + .fold(0, |a, e| a << 8 | (*e as u32)); + SHARED.keyboard[1].store(txt, Relaxed); + SHARED.keyboard[2].store( + key_event.state.is_pressed() as u32 | ((key_event.repeat as u32) << 1), + Relaxed, + ); } + SHARED.keyboard[3] + .store(key_event.physical_key.to_scancode().unwrap_or(0), Relaxed); if enabled { (&SHARED.external_interupts).store(MMIOInterupt::Keyboard.into(), Release); atomic_wait::wake_all(&SHARED.external_interupts); @@ -105,7 +121,9 @@ impl<'a> ApplicationHandler for App<'a> { let enabled = (&SHARED.external_enabled_interupts).load(Relaxed) & Into::::into(MMIOInterupt::MouseMove) != 0; - if enabled {wait_int();} + if enabled { + wait_int(); + } match self .pixels .as_ref() @@ -113,10 +131,8 @@ impl<'a> ApplicationHandler for App<'a> { .window_pos_to_pixel((position.x as f32, position.y as f32)) { Ok((x, y)) => { - (&cpu::SHARED.mouse[1]) - .store(x as u32, Relaxed); - (&cpu::SHARED.mouse[2]) - .store(y as u32, Relaxed); + (&cpu::SHARED.mouse[1]).store(x as u32, Relaxed); + (&cpu::SHARED.mouse[2]).store(y as u32, Relaxed); } Err(_) => { (&SHARED.mouse[1]).store(u32::MAX, Relaxed); @@ -137,7 +153,9 @@ impl<'a> ApplicationHandler for App<'a> { let enabled = (&SHARED.external_enabled_interupts).load(Relaxed) & Into::::into(MMIOInterupt::MouseClick) != 0; - if enabled {wait_int();} + if enabled { + wait_int(); + } let but = 1 << match button { winit::event::MouseButton::Left => 0, @@ -177,8 +195,16 @@ impl<'a> ApplicationHandler for App<'a> { let screen = pix.frame_mut(); for (addr, ubgr) in cpu::SHARED.screen_buf.iter().enumerate() { - let ubgr = ubgr.load(std::sync::atomic::Ordering::Relaxed); - let rgba = [ubgr as u8, (ubgr >> 8) as u8, (ubgr >> 16) as u8, 0xff]; + let raw = ubgr.load(std::sync::atomic::Ordering::Relaxed); + #[cfg(not(feature = "rgba"))] + let rgba = [raw as u8, (raw >> 8) as u8, (raw >> 16) as u8, 0xff]; + #[cfg(feature = "rgba")] + let rgba = [ + (raw >> 24) as u8, + (raw >> 16) as u8, + (raw >> 8) as u8, + raw as u8, + ]; for i in 0..4 { screen[addr * 4 + i] = rgba[i]; }