Compare commits

...

2 Commits

  1. 13
      README.md
  2. 32
      crsn_screen/src/exec.rs
  3. 118
      crsn_screen/src/lib.rs
  4. 137
      examples/life.csn
  5. 58
      examples/screen_keys.csn

@ -783,6 +783,7 @@ such as animations.
; Check key status. Keys are 0-127. Reads 1 if the key is pressed, 0 if not.
; A list of supported keys can be found in the extension source code.
; Run the example screen_keys.scn to interactively check key codes.
(sc-key Wr'pressed Rd'num)
; Check mouse button state.
@ -790,6 +791,18 @@ such as animations.
(sc-mbtn Wr'pressed Rd'btn)
```
Available constants provided by the module:
- SCREEN_AUTO_BLIT, SCREEN_FPS, SCREEN_UPSCALE,
- MBTN_LEFT, MBTN_RIGHT, MBTN_MIDDLE (MBTN_MID)
- KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 (0-9)
- KEY_A, 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 (10-35)
- KEY_F1, 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,
- KEY_Down, KEY_Left, KEY_Right, KEY_Up, KEY_Apos, KEY_Backtick, KEY_Backslash, KEY_Comma, KEY_Equal, KEY_BracketL, KEY_Minus, KEY_Period, KEY_BracketR, KEY_Semicolon, KEY_Slash, KEY_Backspace, KEY_Delete, KEY_End, KEY_Enter, KEY_Escape, KEY_Home, KEY_Insert, KEY_Menu, KEY_PageDown, KEY_PageUp, KEY_Pause, KEY_Space, KEY_Tab, KEY_NumLock, KEY_CapsLock, KEY_ScrollLock,
- KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9,
- KEY_KPDot, KEY_KPSlash, KEY_KPAsterisk, KEY_KPMinus, KEY_KPPlus, KEY_KPEnter,
- KEY_ShiftL, KEY_ShiftR, KEY_CtrlL, KEY_CtrlR, KEY_AltL, KEY_AltR, KEY_WinL, KEY_WinR,
### Graphic acceleration commands
```

@ -4,7 +4,6 @@ use std::time::{Duration, Instant};
use minifb::{Key, MouseButton, MouseMode, ScaleMode, Window, WindowOptions};
use crsn::asm::data::literal::{Value, is_negative};
use crsn::asm::error::CrsnError;
use crsn::asm::instr::cond::Flag;
use crsn::module::{EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
@ -55,7 +54,7 @@ impl Default for Backend {
}
impl Backend {
pub fn draw_rect_log(&mut self, mut x: Value, mut y: Value, w: Value, h: Value, color: u32) {
pub fn draw_rect_log(&mut self, x: Value, y: Value, w: Value, h: Value, color: u32) {
for yy in (y * self.opts.upscale)..((y + h) * self.opts.upscale).min(self.height) {
for xx in (x * self.opts.upscale)..((x + w) * self.opts.upscale).min(self.width) {
self.buffer[(yy * self.width + xx) as usize] = color as u32;
@ -414,7 +413,7 @@ fn blit(backend: &mut Backend) -> Result<(), Fault> {
fn num2key(num: Value) -> Option<Key> {
let remap = [
Key::Key0,
Key::Key0, // 0
Key::Key1,
Key::Key2,
Key::Key3,
@ -423,28 +422,29 @@ fn num2key(num: Value) -> Option<Key> {
Key::Key6,
Key::Key7,
Key::Key8,
Key::Key9,
Key::Key9, // 9
Key::A, // 10
Key::B,
Key::C,
Key::D,
Key::E,
Key::F,
Key::F, // 15
Key::G,
Key::H,
Key::I,
Key::J,
Key::K,
Key::K, // 20
Key::L,
Key::M,
Key::N,
Key::O,
Key::P,
Key::P, // 25
Key::Q,
Key::R,
Key::S,
Key::T,
Key::U,
Key::U, // 30
Key::V,
Key::W,
Key::X,
@ -455,12 +455,12 @@ fn num2key(num: Value) -> Option<Key> {
Key::F2,
Key::F3,
Key::F4,
Key::F5,
Key::F5, // 40
Key::F6,
Key::F7,
Key::F8,
Key::F9,
Key::F10,
Key::F10, // 45
Key::F11,
Key::F12,
Key::F13,
@ -468,18 +468,18 @@ fn num2key(num: Value) -> Option<Key> {
Key::F15, // 50
Key::Down, // 51
Key::Left,
Key::Right,
Key::Up,
Key::Left, // 52
Key::Right, // 53
Key::Up, // 54
Key::Apostrophe,
Key::Backquote,
Key::Backquote, // 56 (a backtick)
Key::Backslash, // 57
Key::Comma,
Key::Equal,
Key::LeftBracket,
Key::LeftBracket, // 60 [
Key::Minus,
Key::Period,
Key::RightBracket,
Key::RightBracket, // 63 ] *This does not work due to a bug in the library we use - PR is sent upstream https://github.com/emoon/rust_minifb/pull/222*
Key::Semicolon,
Key::Slash, // 65
Key::Backspace,

@ -8,6 +8,7 @@ use crsn::module::{CrsnExtension, ParseRes};
use crsn::sexp::SourcePosition;
use crsn::asm::data::literal::Value;
use crate::exec::{OPT_AUTO_BLIT, OPT_FRAME_RATE, OPT_UPSCALE};
use minifb::Key;
mod defs;
mod parse;
@ -36,9 +37,124 @@ impl CrsnExtension for ScreenOps {
fn get_constant_value<'a>(&self, name: &str) -> Option<Value>
{
match name {
"SCREEN_AUTO_BLIT" => Some(OPT_AUTO_BLIT),
"SCREEN_AUTO_BLIT" | "SCREEN_AUTOBLIT" => Some(OPT_AUTO_BLIT),
"SCREEN_FPS" => Some(OPT_FRAME_RATE),
"SCREEN_UPSCALE" => Some(OPT_UPSCALE),
"MBTN_LEFT" => Some(0),
"MBTN_RIGHT" => Some(1),
"MBTN_MIDDLE" | "MBTN_MID" => Some(2),
"KEY_0" => Some(Key::Key0 as Value), // 0
"KEY_1" => Some(Key::Key1 as Value),
"KEY_2" => Some(Key::Key2 as Value),
"KEY_3" => Some(Key::Key3 as Value),
"KEY_4" => Some(Key::Key4 as Value),
"KEY_5" => Some(Key::Key5 as Value),
"KEY_6" => Some(Key::Key6 as Value),
"KEY_7" => Some(Key::Key7 as Value),
"KEY_8" => Some(Key::Key8 as Value),
"KEY_9" => Some(Key::Key9 as Value), // 9
"KEY_A" => Some(Key::A as Value), // 10
"KEY_B" => Some(Key::B as Value),
"KEY_C" => Some(Key::C as Value),
"KEY_D" => Some(Key::D as Value),
"KEY_E" => Some(Key::E as Value),
"KEY_F" => Some(Key::F as Value), // 15
"KEY_G" => Some(Key::G as Value),
"KEY_H" => Some(Key::H as Value),
"KEY_I" => Some(Key::I as Value),
"KEY_J" => Some(Key::J as Value),
"KEY_K" => Some(Key::K as Value), // 20
"KEY_L" => Some(Key::L as Value),
"KEY_M" => Some(Key::M as Value),
"KEY_N" => Some(Key::N as Value),
"KEY_O" => Some(Key::O as Value),
"KEY_P" => Some(Key::P as Value), // 25
"KEY_Q" => Some(Key::Q as Value),
"KEY_R" => Some(Key::R as Value),
"KEY_S" => Some(Key::S as Value),
"KEY_T" => Some(Key::T as Value),
"KEY_U" => Some(Key::U as Value), // 30
"KEY_V" => Some(Key::V as Value),
"KEY_W" => Some(Key::W as Value),
"KEY_X" => Some(Key::X as Value),
"KEY_Y" => Some(Key::Y as Value),
"KEY_Z" => Some(Key::Z as Value), // 35
"KEY_F1" => Some(Key::F1 as Value), // 36
"KEY_F2" => Some(Key::F2 as Value),
"KEY_F3" => Some(Key::F3 as Value),
"KEY_F4" => Some(Key::F4 as Value),
"KEY_F5" => Some(Key::F5 as Value), // 40
"KEY_F6" => Some(Key::F6 as Value),
"KEY_F7" => Some(Key::F7 as Value),
"KEY_F8" => Some(Key::F8 as Value),
"KEY_F9" => Some(Key::F9 as Value),
"KEY_F10" => Some(Key::F10 as Value), // 45
"KEY_F11" => Some(Key::F11 as Value),
"KEY_F12" => Some(Key::F12 as Value),
"KEY_F13" => Some(Key::F13 as Value),
"KEY_F14" => Some(Key::F14 as Value),
"KEY_F15" => Some(Key::F15 as Value), // 50
"KEY_Down" => Some(Key::Down as Value), // 51
"KEY_Left" => Some(Key::Left as Value), // 52
"KEY_Right" => Some(Key::Right as Value), // 53
"KEY_Up" => Some(Key::Up as Value), // 54
"KEY_Apos" => Some(Key::Apostrophe as Value),
"KEY_Backtick" => Some(Key::Backquote as Value), // 56 (a backtick)
"KEY_Backslash" => Some(Key::Backslash as Value), // 57
"KEY_Comma" => Some(Key::Comma as Value),
"KEY_Equal" => Some(Key::Equal as Value),
"KEY_BracketL" => Some(Key::LeftBracket as Value), // 60 [
"KEY_Minus" => Some(Key::Minus as Value),
"KEY_Period" => Some(Key::Period as Value),
"KEY_BracketR" => Some(Key::RightBracket as Value), // 63 ] *This does not work due to a bug in the library we use - PR is sent upstream https://github.com/emoon/rust_minifb/pull/222*
"KEY_Semicolon" => Some(Key::Semicolon as Value),
"KEY_Slash" => Some(Key::Slash as Value), // 65
"KEY_Backspace" => Some(Key::Backspace as Value),
"KEY_Delete" => Some(Key::Delete as Value),
"KEY_End" => Some(Key::End as Value),
"KEY_Enter" => Some(Key::Enter as Value),
"KEY_Escape" => Some(Key::Escape as Value), // 70
"KEY_Home" => Some(Key::Home as Value),
"KEY_Insert" => Some(Key::Insert as Value),
"KEY_Menu" => Some(Key::Menu as Value),
"KEY_PageDown" => Some(Key::PageDown as Value),
"KEY_PageUp" => Some(Key::PageUp as Value),
"KEY_Pause" => Some(Key::Pause as Value), // 76
"KEY_Space" => Some(Key::Space as Value),
"KEY_Tab" => Some(Key::Tab as Value),
"KEY_NumLock" => Some(Key::NumLock as Value),
"KEY_CapsLock" => Some(Key::CapsLock as Value),
"KEY_ScrollLock" => Some(Key::ScrollLock as Value),
"KEY_ShiftL" => Some(Key::LeftShift as Value),
"KEY_ShiftR" => Some(Key::RightShift as Value),
"KEY_CtrlL" => Some(Key::LeftCtrl as Value),
"KEY_CtrlR" => Some(Key::RightCtrl as Value),
"KEY_KP0" => Some(Key::NumPad0 as Value), // 86
"KEY_KP1" => Some(Key::NumPad1 as Value),
"KEY_KP2" => Some(Key::NumPad2 as Value),
"KEY_KP3" => Some(Key::NumPad3 as Value),
"KEY_KP4" => Some(Key::NumPad4 as Value),
"KEY_KP5" => Some(Key::NumPad5 as Value),
"KEY_KP6" => Some(Key::NumPad6 as Value),
"KEY_KP7" => Some(Key::NumPad7 as Value),
"KEY_KP8" => Some(Key::NumPad8 as Value),
"KEY_KP9" => Some(Key::NumPad9 as Value),
"KEY_KPDot" => Some(Key::NumPadDot as Value),
"KEY_KPSlash" => Some(Key::NumPadSlash as Value),
"KEY_KPAsterisk" => Some(Key::NumPadAsterisk as Value),
"KEY_KPMinus" => Some(Key::NumPadMinus as Value),
"KEY_KPPlus" => Some(Key::NumPadPlus as Value),
"KEY_KPEnter" => Some(Key::NumPadEnter as Value), // 100
"KEY_AltL" => Some(Key::LeftAlt as Value),
"KEY_AltR" => Some(Key::RightAlt as Value),
"KEY_WinL" | "KEY_SuperL" | "KEY_MetaL" => Some(Key::LeftSuper as Value),
"KEY_WinR" | "KEY_SuperR" | "KEY_MetaR" => Some(Key::RightSuper as Value),
_ => None
}
}

@ -1,130 +1,125 @@
(
; simple GOL with screen and a buffer + DRAWING!!!
; Middle-click to payse or resume
; Middle-click to payse or resume
; (hold the button until paused - there is a sleep between generations and checking buttons)
;
; When paused, draw with left (white) and right (black) mouse buttons
;
; Resume by clicking middle again.
(def GENERATION_MS 200)
; Real pixel size
(sc-init 400 400)
; Upscaling factor (bug pixels)
(sc-opt SCREEN_UPSCALE 10)
; Number of big pixels
(def W 40)
(def H 40)
; !!! If you change size, also update the following constants.
; Compile-time math is not implemented yet.
(def XMAX 39) ; W-1
(def YMAX 39) ; H-1
(def NCELLS 1600) ; W*H
; --- end of config ---
(sc-opt SCREEN_AUTO_BLIT 0)
(sc-erase 0) ; all black
(sym ng g15)
(mkbf ng NCELLS)
; one glider
(bfwr @ng 1 1)
(bfwr @ng 42 1)
(bfwr @ng 80 1)
(bfwr @ng 81 1)
(bfwr @ng 82 1)
; another glider
(bfwr @ng 16 1)
(bfwr @ng 55 1)
(bfwr @ng 95 1)
(bfwr @ng 96 1)
(bfwr @ng 97 1)
(def LBTN 0)
(def RBTN 1)
(def MBTN 2)
(:loop)
(sc-poll)
; Drawing
(sc-mbtn _ MBTN
(sc-mbtn _ MBTN_MID
(nz?
(:release)
(sc-poll)
(mslp 10)
(sc-mbtn _ MBTN (nz? (j :release)))
(sc-mbtn _ MBTN_MID (nz? (j :release)))
(:mousing)
(sc-poll)
(mslp 10)
(ld r3 -1)
(sc-mbtn _ LBTN)
(sc-mbtn _ MBTN_LEFT)
(ld.nz r3 1)
(sc-mbtn _ RBTN)
(sc-mbtn _ MBTN_RIGHT)
(ld.nz r3 0)
(tst r3 (nneg?
(sc-mouse r0 r1)
(tst r3)
(sc-wr.nz r0 r1 #ffffff)
(sc-wr.z r0 r1 #000000)
(sc-blit)
(mul r1 W)
(add r0 r1)
(ld8 r3:8 r3)
(bfwr @ng r0 r3)
))
(sc-mbtn _ MBTN
))
(sc-mbtn _ MBTN_MID
(z? (j :mousing)))
(:release2)
(sc-poll)
(mslp 10)
(sc-mbtn _ MBTN (nz? (j :release2)))
(sc-mbtn _ MBTN_MID (nz? (j :release2)))
)
)
)
(call Display)
(sc-blit)
(mslp GENERATION_MS)
(j :loop)
(proc CountNeighbors x y
(sym xx r4)
(sym yy r5)
(sym i r6)
(sym count r7)
(sym count r7)
; yeah this sucks. it's correct, though
(:a)
(add yy y -1 (neg? (j :d)))
(add yy y -1 (neg? (j :d)))
(add xx x -1 (neg? (j :b)))
(mul i yy W)
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:b)
(mul i yy W)
(add i x)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:c)
(add xx x 1)
(cmp xx W (ge? (j :d)))
@ -132,16 +127,16 @@
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:d)
(:d)
(add xx x -1 (neg? (j :f)))
(mul i y W)
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
; there is no E
(:f)
(add xx x 1)
(cmp xx W (ge? (j :g)))
@ -149,26 +144,26 @@
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:g)
(add yy y 1)
(add yy y 1)
(cmp yy H (ge? (j :end)))
(add xx x -1 (neg? (j :h)))
(mul i yy W)
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:h)
(add yy y 1)
(add yy y 1)
(cmp yy H (ge? (j :end)))
(mul i yy W)
(add i x)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:i)
(add yy y 1)
(add yy y 1)
(cmp yy H (ge? (j :end)))
(add xx x 1)
(cmp xx W (ge? (j :end)))
@ -176,59 +171,59 @@
(add i xx)
(bfrd r0 @ng i)
(and r0 0xFF (nz? (inc count)))
(:end)
(ret count)
)
(proc Display
; display and calc next gen
(sym x r4)
(sym y r5)
(sym i r6)
(sym i r6)
(:next)
; The lower byte contains 0 or 1
; the second byte will be filled with the next gen
(bfrd r0 @ng i)
; Show this gen
(and r0 0xFF
(and r0 0xFF
(nz? (sc-wr x y 0xffffff))
(z? (sc-wr x y 0x000000)))
(call CountNeighbors x y)
; stay: 2,3
; die: >3
; born: 3
(cmp res0 2
(cmp res0 2
(eq? (ld8 r0:8 r0)) ; stasis
(ne?
(tst r0
(z?
(cmp res0 3 (eq? (ld8 r0:8 1))) ; birth
)
(nz?
(cmp res0 3 (eq? (ld8 r0:8 1))) ; stay alive
(tst r0
(z?
(cmp res0 3 (eq? (ld8 r0:8 1))) ; birth
)
(nz?
(cmp res0 3 (eq? (ld8 r0:8 1))) ; stay alive
)
)
)
)
(bfwr @ng i r0)
(inc i)
(inc x)
(cmp x W
(ne? (j :next)))
(ld x 0)
(inc y)
(cmp y H
(cmp y H
(eq? (j :next2)))
(j :next)
; Shift all by 8 to the right (generation shift)
(:next2)
(dec i)

@ -0,0 +1,58 @@
(
; Helper to check key codes of physical keys
(sc-init 200 200)
(lds @cout "Press keys in the window to see their codes...\n")
(sym pressed r15)
(mkbf pressed 256)
(:loop)
(sc-poll)
(mslp 10)
(sym cnt r14)
(ld cnt 0)
(:next)
(sc-key _ cnt
(inval? (nop))
(nz?
(bfrd r1 @pressed cnt
(z?
(call printnum cnt)
(lds @cout " PRESS\n")
(bfwr @pressed cnt 1)
(rng r0 0 #ffffff)
(sc-erase r0)
(sc-blit)
)
)
)
(z?
(bfrd r1 @pressed cnt
(nz?
(call printnum cnt)
(lds @cout " RELEASE\n")
(bfwr @pressed cnt 0)
)
)
)
)
(inc cnt)
(cmp cnt 256 (ne? (j :next)))
(j :loop)
; this is a version if itoa that prints a number
(proc printnum num
(mkbf r15)
(ld r1 num)
(tst r1 (<0? (mul r1 -1)))
(:next)
(mod r0 r1 10)
(add r0 '0')
(bfrpush @r15 r0)
(div r1 10 (z?
(tst num (<0? (bfrpush @r15 '-')))
(lds @cout @r15)
(del @r15)
(ret)))
(j :next)
)
)
Loading…
Cancel
Save