screen imrpvoements

pull/21/head
Ondřej Hruška 4 years ago
parent d19c4e5bea
commit 532df6eb04
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 4
      crsn/src/asm/parse/arg_parser.rs
  2. 2
      crsn/src/lib.rs
  3. 3
      crsn/src/utils/mod.rs
  4. 18
      crsn/src/utils/option_ext.rs
  5. 9
      crsn_screen/src/defs.rs
  6. 98
      crsn_screen/src/exec.rs
  7. 21
      crsn_screen/src/parse.rs
  8. 5
      launcher/src/main.rs

@ -29,6 +29,10 @@ impl ArgParser {
} }
} }
pub fn have_more(&self) -> bool {
self.len() > 0
}
/// Get remaining items count /// Get remaining items count
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.args.len() self.args.len()

@ -7,4 +7,4 @@ pub mod asm;
pub mod builtin; pub mod builtin;
pub mod runtime; pub mod runtime;
pub mod module; pub mod module;
pub mod utils;

@ -0,0 +1,3 @@
mod option_ext;
pub use option_ext::UncheckedOptionExt;

@ -0,0 +1,18 @@
/// This is copied from parking_lot
///
/// Copyright 2016 Amanieu d'Antras
// Option::unchecked_unwrap
pub trait UncheckedOptionExt<T> {
unsafe fn unchecked_unwrap(self) -> T;
}
impl<T> UncheckedOptionExt<T> for Option<T> {
#[inline]
unsafe fn unchecked_unwrap(self) -> T {
match self {
Some(x) => x,
None => core::hint::unreachable_unchecked(),
}
}
}

@ -10,5 +10,12 @@ pub enum ScreenOp {
x: Rd, x: Rd,
y: Rd, y: Rd,
color: Rd, color: Rd,
} },
Blit {
force: Rd,
},
SetOpt {
opt: Rd,
val: Rd,
},
} }

@ -10,15 +10,45 @@ use crate::defs::ScreenOp;
use minifb::{Window, WindowOptions, ScaleMode}; use minifb::{Window, WindowOptions, ScaleMode};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Instant, Duration};
use std::ops::Sub;
use crsn::utils::UncheckedOptionExt;
#[derive(Debug)]
struct Opts {
auto_blit: bool,
frame_rate: Duration,
}
#[derive(Debug, Default)] #[derive(Debug)]
struct Backend { struct Backend {
width: usize, width: usize,
height: usize, height: usize,
buffer: Vec<u32>, buffer: Vec<u32>,
window: Option<Window>, window: Option<Window>,
last_render: Instant,
opts: Opts
} }
impl Default for Backend {
fn default() -> Self {
Self {
width: 0,
height: 0,
buffer: vec![],
window: None,
last_render: Instant::now().sub(Duration::from_secs(1)),
opts: Opts {
auto_blit: true,
frame_rate: Duration::from_micros(16600),
}
}
}
}
const OPT_AUTO_BLIT : u64 = 1;
const OPT_FRAME_RATE : u64 = 2;
// Hack for Window // Hack for Window
unsafe impl std::marker::Send for Backend { } unsafe impl std::marker::Send for Backend { }
@ -31,12 +61,48 @@ impl OpTrait for ScreenOp {
let h = state.read(*height)?; let h = state.read(*height)?;
init(state, w, h)?; init(state, w, h)?;
} }
ScreenOp::SetOpt { opt, val } => {
let opt = state.read(*opt)?;
let val = state.read(*val)?;
let backend : &mut Backend = state.ext_mut();
match opt {
OPT_AUTO_BLIT => {
backend.opts.auto_blit = (val != 0);
debug!("Set auto blit to {:?}", backend.opts.auto_blit);
}
OPT_FRAME_RATE => {
backend.opts.frame_rate = Duration::from_micros(1_000_000 as u64 / val);
debug!("Set frame rate to {:?}", backend.opts.frame_rate);
}
other => {
warn!("Bad screen opt: {}", other);
state.set_flag(Cond::Invalid, true);
}
}
}
ScreenOp::Blit { force } => {
let force = state.read(*force)?;
let backend : &mut Backend = state.ext_mut();
if force != 0 {
blit(backend)
} else {
blit_maybe(backend)
}
}
ScreenOp::SetPixel { x, y, color } => { ScreenOp::SetPixel { x, y, color } => {
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)?;
let backend : &mut Backend = state.ext_mut(); let backend : &mut Backend = state.ext_mut();
if x >= backend.width as u64 || y >= backend.height as u64 {
state.set_flag(Cond::Overflow, true);
return Ok(eres);
}
match &mut backend.window { match &mut backend.window {
Some(w) => { Some(w) => {
let index = y * backend.width as u64 + x; let index = y * backend.width as u64 + x;
@ -46,9 +112,9 @@ impl OpTrait for ScreenOp {
} else { } else {
backend.buffer[index as usize] = color as u32; backend.buffer[index as usize] = color as u32;
w if backend.opts.auto_blit {
.update_with_buffer(&backend.buffer, backend.width, backend.height) blit_maybe(backend);
.expect("Update screen"); // TODO fault }
} }
} }
None => { None => {
@ -70,7 +136,7 @@ fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault>
height as usize, height as usize,
WindowOptions { WindowOptions {
resize: true, resize: true,
scale_mode: ScaleMode::AspectRatioStretch, scale_mode: ScaleMode::UpperLeft,
..WindowOptions::default() ..WindowOptions::default()
}, },
).expect("Unable to create window"); // TODO fault ).expect("Unable to create window"); // TODO fault
@ -87,13 +153,25 @@ fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault>
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(Some(std::time::Duration::from_micros(16600)));
window.limit_update_rate(None); // window.limit_update_rate(None);
window
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
backend.window = Some(window); backend.window = Some(window);
blit_maybe(backend);
Ok(()) Ok(())
} }
fn blit_maybe(backend: &mut Backend) {
if backend.last_render.elapsed() >= backend.opts.frame_rate {
blit(backend);
}
}
fn blit(backend: &mut Backend) {
backend.window.as_mut().unwrap()
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
backend.last_render = Instant::now();
}

@ -1,8 +1,8 @@
use crsn::asm::data::Rd;
use crsn::asm::error::CrsnError; use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op; use crsn::asm::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser; use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{ParseOpRes}; use crsn::module::ParseOpRes;
use crate::defs::ScreenOp; use crate::defs::ScreenOp;
@ -23,6 +23,23 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
} }
} }
"sc-opt" => {
ScreenOp::SetOpt {
opt: args.next_rd()?,
val: args.next_rd()?,
}
}
"sc-blit" => {
ScreenOp::Blit {
force: if args.have_more() {
args.next_rd()?
} else {
Rd::immediate(1)
},
}
}
_other => { _other => {
return Ok(ParseOpRes::Unknown(args)); return Ok(ParseOpRes::Unknown(args));
} }

@ -78,6 +78,8 @@ fn main() {
( (
(main (main
(sc-init 640 480) (sc-init 640 480)
(sc-opt 1 0) ; auto blit
(sc-opt 2 60) ; frame rate
(ld r0 39) ; x (ld r0 39) ; x
(ld r1 0) ; y (ld r1 0) ; y
@ -88,9 +90,10 @@ fn main() {
(ld r5 0xffffff) (ld r5 0xffffff)
(:loop) (:loop)
(add r5 0x123456) (add r5 0x010001)
(and r5 0xffffff) (and r5 0xffffff)
(sc-px r0 r1 r5) (sc-px r0 r1 r5)
(sc-blit 0)
(add r0 r2) (add r0 r2)
(add r1 r3) (add r1 r3)
(cmp r0 639 (eq? (ld r2 -1))) (cmp r0 639 (eq? (ld r2 -1)))

Loading…
Cancel
Save