rich keyboard
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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::<u32>::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::<u32>::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::<u32>::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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user