forked from MightyPork/crsn
mouse and key input, handle close btn, mouse demo
This commit is contained in:
@@ -73,7 +73,7 @@ impl Flatten for Vec<Box<dyn Flatten>> {
|
|||||||
for item in self.into_iter() {
|
for item in self.into_iter() {
|
||||||
ops.extend(item.flatten(label_num)?);
|
ops.extend(item.flatten(label_num)?);
|
||||||
}
|
}
|
||||||
labels_to_skips(ops)
|
Ok(ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::asm::data::literal::RoutineName;
|
|||||||
|
|
||||||
pub mod op;
|
pub mod op;
|
||||||
pub mod cond;
|
pub mod cond;
|
||||||
mod flatten;
|
pub mod flatten;
|
||||||
|
|
||||||
/// A higher-level instruction
|
/// A higher-level instruction
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||||||
use crate::asm::parse::{ParserContext, ParserState};
|
use crate::asm::parse::{ParserContext, ParserState};
|
||||||
use crate::module::CrsnExtension;
|
use crate::module::CrsnExtension;
|
||||||
use crate::runtime::program::Program;
|
use crate::runtime::program::Program;
|
||||||
|
use crate::asm::instr::flatten::labels_to_skips;
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
@@ -23,6 +24,7 @@ pub fn assemble(source: &str, parsers: Arc<Vec<Box<dyn CrsnExtension>>>) -> Resu
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ops = parse::parse(source, &pcx)?;
|
let ops = parse::parse(source, &pcx)?;
|
||||||
|
let ops = labels_to_skips(ops)?;
|
||||||
|
|
||||||
Ok(Program::new(ops, parsers)?)
|
Ok(Program::new(ops, parsers)?)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-1
@@ -1,4 +1,4 @@
|
|||||||
use crsn::asm::data::Rd;
|
use crsn::asm::data::{Rd, Wr};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum ScreenOp {
|
pub enum ScreenOp {
|
||||||
@@ -11,6 +11,22 @@ pub enum ScreenOp {
|
|||||||
y: Rd,
|
y: Rd,
|
||||||
color: Rd,
|
color: Rd,
|
||||||
},
|
},
|
||||||
|
GetMouse {
|
||||||
|
x: Wr,
|
||||||
|
y: Wr,
|
||||||
|
},
|
||||||
|
TestKey {
|
||||||
|
pressed: Wr,
|
||||||
|
code: Rd,
|
||||||
|
},
|
||||||
|
TestMouse {
|
||||||
|
pressed: Wr,
|
||||||
|
button: Rd,
|
||||||
|
},
|
||||||
|
Update,
|
||||||
|
Erase {
|
||||||
|
color: Rd,
|
||||||
|
},
|
||||||
Blit {
|
Blit {
|
||||||
force: Rd,
|
force: Rd,
|
||||||
},
|
},
|
||||||
|
|||||||
+244
-7
@@ -1,7 +1,7 @@
|
|||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use minifb::{ScaleMode, Window, WindowOptions};
|
use minifb::{ScaleMode, Window, WindowOptions, MouseMode, Key, MouseButton};
|
||||||
|
|
||||||
use crsn::asm::data::literal::Value;
|
use crsn::asm::data::literal::Value;
|
||||||
use crsn::asm::instr::Cond;
|
use crsn::asm::instr::Cond;
|
||||||
@@ -61,7 +61,17 @@ impl OpTrait for ScreenOp {
|
|||||||
let h = state.read(*height)?;
|
let h = state.read(*height)?;
|
||||||
init(state, w, h)?;
|
init(state, w, h)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScreenOp::Erase { color } => {
|
||||||
|
let color = (state.read(*color)? & 0xffffff) as u32;
|
||||||
|
let backend: &mut Backend = state.ext_mut();
|
||||||
|
for n in 0..(backend.buffer.len()) {
|
||||||
|
backend.buffer[n] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScreenOp::SetOpt { opt, val } => {
|
ScreenOp::SetOpt { opt, val } => {
|
||||||
|
state.clear_status();
|
||||||
let opt = state.read(*opt)?;
|
let opt = state.read(*opt)?;
|
||||||
let val = state.read(*val)?;
|
let val = state.read(*val)?;
|
||||||
let backend: &mut Backend = state.ext_mut();
|
let backend: &mut Backend = state.ext_mut();
|
||||||
@@ -81,6 +91,7 @@ impl OpTrait for ScreenOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenOp::Blit { force } => {
|
ScreenOp::Blit { force } => {
|
||||||
let force = state.read(*force)?;
|
let force = state.read(*force)?;
|
||||||
let backend: &mut Backend = state.ext_mut();
|
let backend: &mut Backend = state.ext_mut();
|
||||||
@@ -91,7 +102,21 @@ impl OpTrait for ScreenOp {
|
|||||||
blit_maybe(backend)
|
blit_maybe(backend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScreenOp::Update => {
|
||||||
|
let backend: &mut Backend = state.ext_mut();
|
||||||
|
match &mut backend.window {
|
||||||
|
Some(w) => {
|
||||||
|
w.update();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScreenOp::SetPixel { x, y, color } => {
|
ScreenOp::SetPixel { x, y, color } => {
|
||||||
|
state.clear_status();
|
||||||
let x = state.read(*x)?;
|
let x = state.read(*x)?;
|
||||||
let y = state.read(*y)?;
|
let y = state.read(*y)?;
|
||||||
let color = state.read(*color)?;
|
let color = state.read(*color)?;
|
||||||
@@ -122,6 +147,83 @@ impl OpTrait for ScreenOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScreenOp::GetMouse { x, y } => {
|
||||||
|
state.clear_status();
|
||||||
|
let backend: &mut Backend = state.ext_mut();
|
||||||
|
match &mut backend.window {
|
||||||
|
Some(w) => {
|
||||||
|
let mp = w.get_mouse_pos(MouseMode::Discard);
|
||||||
|
debug!("mp = {:?}", mp);
|
||||||
|
match mp {
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Overflow, true);
|
||||||
|
}
|
||||||
|
Some((xf, yf)) => {
|
||||||
|
let xval = xf.round() as u64;
|
||||||
|
let yval = yf.round() as u64;
|
||||||
|
|
||||||
|
state.write(*x, xval);
|
||||||
|
state.write(*y, yval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenOp::TestKey { pressed, code } => {
|
||||||
|
state.clear_status();
|
||||||
|
let num = num2key(state.read(*code)?);
|
||||||
|
let backend: &mut Backend = state.ext_mut();
|
||||||
|
match &mut backend.window {
|
||||||
|
Some(w) => {
|
||||||
|
match num {
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
}
|
||||||
|
Some(kn) => {
|
||||||
|
let down = w.is_key_down(kn) as u64;
|
||||||
|
state.write(*pressed, down)?;
|
||||||
|
state.update_status(down);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenOp::TestMouse { pressed, button } => {
|
||||||
|
state.clear_status();
|
||||||
|
|
||||||
|
let omb = match state.read(*button)? {
|
||||||
|
0 => Some(MouseButton::Left),
|
||||||
|
1 => Some(MouseButton::Right),
|
||||||
|
2 => Some(MouseButton::Middle),
|
||||||
|
_ => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let backend: &mut Backend = state.ext_mut();
|
||||||
|
match &mut backend.window {
|
||||||
|
Some(w) => {
|
||||||
|
if let Some(mb) = omb {
|
||||||
|
let is_pressed = w.get_mouse_down(mb) as u64;
|
||||||
|
state.write(*pressed, is_pressed)?;
|
||||||
|
state.update_status(is_pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
state.set_flag(Cond::Invalid, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(eres)
|
Ok(eres)
|
||||||
@@ -132,7 +234,12 @@ impl OpTrait for ScreenOp {
|
|||||||
ScreenOp::SetOpt { opt, val } => sexp::list(&[A("sc-opt"), A(opt), A(val)]),
|
ScreenOp::SetOpt { opt, val } => sexp::list(&[A("sc-opt"), A(opt), A(val)]),
|
||||||
ScreenOp::ScreenInit { width, height } => sexp::list(&[A("sc-init"), A(width), A(height)]),
|
ScreenOp::ScreenInit { width, height } => sexp::list(&[A("sc-init"), A(width), A(height)]),
|
||||||
ScreenOp::SetPixel { x, y, color } => sexp::list(&[A("sc-px"), A(x), A(y), A(color)]),
|
ScreenOp::SetPixel { x, y, color } => sexp::list(&[A("sc-px"), A(x), A(y), A(color)]),
|
||||||
ScreenOp::Blit { force } => sexp::list(&[A("sc-blit"), A(force)])
|
ScreenOp::Blit { force } => sexp::list(&[A("sc-blit"), A(force)]),
|
||||||
|
ScreenOp::Update => sexp::list(&[A("sc-poll")]),
|
||||||
|
ScreenOp::GetMouse { x, y } => sexp::list(&[A("sc-mouse"), A(x), A(y)]),
|
||||||
|
ScreenOp::TestKey { pressed, code } => sexp::list(&[A("sc-key"), A(pressed), A(code)]),
|
||||||
|
ScreenOp::TestMouse { pressed, button } => sexp::list(&[A("sc-mbtn"), A(pressed), A(button)]),
|
||||||
|
ScreenOp::Erase { color } => sexp::list(&[A("sc-erase"), A(color)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,9 +267,6 @@ fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault>
|
|||||||
backend.height = height as usize;
|
backend.height = height as usize;
|
||||||
backend.buffer = vec![0; (width * 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);
|
|
||||||
|
|
||||||
backend.window = Some(window);
|
backend.window = Some(window);
|
||||||
|
|
||||||
blit_maybe(backend);
|
blit_maybe(backend);
|
||||||
@@ -177,9 +281,142 @@ fn blit_maybe(backend: &mut Backend) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn blit(backend: &mut Backend) {
|
fn blit(backend: &mut Backend) {
|
||||||
backend.window.as_mut().unwrap()
|
let w = backend.window.as_mut().unwrap();
|
||||||
.update_with_buffer(&backend.buffer, backend.width, backend.height)
|
|
||||||
|
if !w.is_open() {
|
||||||
|
// TODO...
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.update_with_buffer(&backend.buffer, backend.width, backend.height)
|
||||||
.expect("Update screen"); // TODO fault
|
.expect("Update screen"); // TODO fault
|
||||||
|
|
||||||
backend.last_render = Instant::now();
|
backend.last_render = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn num2key(num : Value) -> Option<Key> {
|
||||||
|
let remap = [
|
||||||
|
Key::Key0,
|
||||||
|
Key::Key1,
|
||||||
|
Key::Key2,
|
||||||
|
Key::Key3,
|
||||||
|
Key::Key4,
|
||||||
|
Key::Key5,
|
||||||
|
Key::Key6,
|
||||||
|
Key::Key7,
|
||||||
|
Key::Key8,
|
||||||
|
Key::Key9,
|
||||||
|
|
||||||
|
Key::A, // 10
|
||||||
|
Key::B,
|
||||||
|
Key::C,
|
||||||
|
Key::D,
|
||||||
|
Key::E,
|
||||||
|
Key::F,
|
||||||
|
Key::G,
|
||||||
|
Key::H,
|
||||||
|
Key::I,
|
||||||
|
Key::J,
|
||||||
|
Key::K,
|
||||||
|
Key::L,
|
||||||
|
Key::M,
|
||||||
|
Key::N,
|
||||||
|
Key::O,
|
||||||
|
Key::P,
|
||||||
|
Key::Q,
|
||||||
|
Key::R,
|
||||||
|
Key::S,
|
||||||
|
Key::T,
|
||||||
|
Key::U,
|
||||||
|
Key::V,
|
||||||
|
Key::W,
|
||||||
|
Key::X,
|
||||||
|
Key::Y,
|
||||||
|
Key::Z, // 35
|
||||||
|
|
||||||
|
Key::F1, // 36
|
||||||
|
Key::F2,
|
||||||
|
Key::F3,
|
||||||
|
Key::F4,
|
||||||
|
Key::F5,
|
||||||
|
Key::F6,
|
||||||
|
Key::F7,
|
||||||
|
Key::F8,
|
||||||
|
Key::F9,
|
||||||
|
Key::F10,
|
||||||
|
Key::F11,
|
||||||
|
Key::F12,
|
||||||
|
Key::F13,
|
||||||
|
Key::F14,
|
||||||
|
Key::F15, // 50
|
||||||
|
|
||||||
|
Key::Down, // 51
|
||||||
|
Key::Left,
|
||||||
|
Key::Right,
|
||||||
|
Key::Up,
|
||||||
|
Key::Apostrophe,
|
||||||
|
Key::Backquote,
|
||||||
|
|
||||||
|
Key::Backslash, // 57
|
||||||
|
Key::Comma,
|
||||||
|
Key::Equal,
|
||||||
|
Key::LeftBracket,
|
||||||
|
Key::Minus,
|
||||||
|
Key::Period,
|
||||||
|
Key::RightBracket,
|
||||||
|
Key::Semicolon,
|
||||||
|
|
||||||
|
Key::Slash, // 65
|
||||||
|
Key::Backspace,
|
||||||
|
Key::Delete,
|
||||||
|
Key::End,
|
||||||
|
Key::Enter,
|
||||||
|
|
||||||
|
Key::Escape, // 70
|
||||||
|
Key::Home,
|
||||||
|
Key::Insert,
|
||||||
|
Key::Menu,
|
||||||
|
Key::PageDown,
|
||||||
|
Key::PageUp,
|
||||||
|
|
||||||
|
Key::Pause, // 76
|
||||||
|
Key::Space,
|
||||||
|
Key::Tab,
|
||||||
|
Key::NumLock,
|
||||||
|
Key::CapsLock,
|
||||||
|
Key::ScrollLock,
|
||||||
|
Key::LeftShift,
|
||||||
|
Key::RightShift,
|
||||||
|
Key::LeftCtrl,
|
||||||
|
Key::RightCtrl,
|
||||||
|
|
||||||
|
Key::NumPad0, // 86
|
||||||
|
Key::NumPad1,
|
||||||
|
Key::NumPad2,
|
||||||
|
Key::NumPad3,
|
||||||
|
Key::NumPad4,
|
||||||
|
Key::NumPad5,
|
||||||
|
Key::NumPad6,
|
||||||
|
Key::NumPad7,
|
||||||
|
Key::NumPad8,
|
||||||
|
Key::NumPad9,
|
||||||
|
Key::NumPadDot,
|
||||||
|
Key::NumPadSlash,
|
||||||
|
Key::NumPadAsterisk,
|
||||||
|
Key::NumPadMinus,
|
||||||
|
Key::NumPadPlus,
|
||||||
|
Key::NumPadEnter, // 100
|
||||||
|
|
||||||
|
Key::LeftAlt,
|
||||||
|
Key::RightAlt,
|
||||||
|
Key::LeftSuper,
|
||||||
|
Key::RightSuper,
|
||||||
|
];
|
||||||
|
|
||||||
|
if num < remap.len() as u64 {
|
||||||
|
Some(remap[num as usize])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crsn::asm::data::Rd;
|
use crsn::asm::data::{Rd, RdData};
|
||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::op::OpKind;
|
use crsn::asm::instr::op::OpKind;
|
||||||
use crsn::asm::parse::arg_parser::TokenParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
@@ -15,6 +15,16 @@ pub(crate) fn parse<'a>(keyword: &str, mut args: TokenParser<'a>) -> Result<Pars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"sc-erase" => {
|
||||||
|
ScreenOp::Erase {
|
||||||
|
color: if args.len() > 0 {
|
||||||
|
args.next_rd()?
|
||||||
|
} else {
|
||||||
|
Rd::immediate(0) // black
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"sc-px" => {
|
"sc-px" => {
|
||||||
ScreenOp::SetPixel {
|
ScreenOp::SetPixel {
|
||||||
x: args.next_rd()?,
|
x: args.next_rd()?,
|
||||||
@@ -40,6 +50,31 @@ pub(crate) fn parse<'a>(keyword: &str, mut args: TokenParser<'a>) -> Result<Pars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"sc-poll" => {
|
||||||
|
ScreenOp::Update
|
||||||
|
}
|
||||||
|
|
||||||
|
"sc-mouse" => {
|
||||||
|
ScreenOp::GetMouse {
|
||||||
|
x: args.next_wr()?,
|
||||||
|
y: args.next_wr()?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"sc-key" => {
|
||||||
|
ScreenOp::TestKey {
|
||||||
|
pressed: args.next_wr()?,
|
||||||
|
code: args.next_rd()?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"sc-mbtn" => {
|
||||||
|
ScreenOp::TestMouse {
|
||||||
|
pressed: args.next_wr()?,
|
||||||
|
button: args.next_rd()?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_other => {
|
_other => {
|
||||||
return Ok(ParseRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
(
|
||||||
|
(sc-init 640 480)
|
||||||
|
|
||||||
|
(sym x r6)
|
||||||
|
(sym y r7)
|
||||||
|
|
||||||
|
(def BOXSIZE 10)
|
||||||
|
|
||||||
|
(:loop)
|
||||||
|
(sc-poll)
|
||||||
|
(sc-mouse x y
|
||||||
|
(ov? (j :next)))
|
||||||
|
|
||||||
|
(sc-mbtn r0 0 (z? (j :next)))
|
||||||
|
|
||||||
|
(sym vx r0)
|
||||||
|
(sym vy r1)
|
||||||
|
(sym endx r2)
|
||||||
|
(sym endy r3)
|
||||||
|
|
||||||
|
(add endx x BOXSIZE)
|
||||||
|
(add endy y BOXSIZE)
|
||||||
|
|
||||||
|
(sub vy y BOXSIZE)
|
||||||
|
|
||||||
|
(:nextline)
|
||||||
|
(cmp vy endy (eq? (j :endbox)))
|
||||||
|
(sub vx x BOXSIZE)
|
||||||
|
(:nextpx)
|
||||||
|
(sc-px vx vy 0xffffff)
|
||||||
|
(inc vx)
|
||||||
|
(cmp vx endx
|
||||||
|
(eq? (inc vy)(j :nextline)))
|
||||||
|
(j :nextpx)
|
||||||
|
(:endbox)
|
||||||
|
|
||||||
|
(:next)
|
||||||
|
(sleep 20000)
|
||||||
|
(j :loop)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user