duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 042c35e0db71d58e1d88aabb1224420474700693
parent b546fde88a1543b2a298157a61a427066cf55c23
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue, 20 Dec 2022 12:41:00 -0500

emul/uxn: controller!

You can try it with "f<< tests/manual/uxn/ctrl.fs" I've changed the Home button
to Right Shift, but otherwise everything works.

I've also added uxn docs at doc/uxn

Diffstat:
Mfs/doc/ps2.txt | 5+++++
Afs/doc/uxn.txt | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afs/emul/uxn/gui.fs | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dfs/emul/uxn/screen.fs | 120-------------------------------------------------------------------------------
Mfs/sys/ps2.fs | 14+++++++-------
Afs/tests/manual/uxn/ctrl.fs | 5+++++
Afs/tests/manual/uxn/ctrl.tal | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfs/tests/manual/uxn/mandel.fs | 2+-
Mfs/tests/manual/uxn/pixdance.fs | 2+-
Mfs/tests/manual/uxn/rect.fs | 2+-
Mfs/tests/manual/uxn/sprite.fs | 2+-
11 files changed, 405 insertions(+), 131 deletions(-)

diff --git a/fs/doc/ps2.txt b/fs/doc/ps2.txt @@ -20,6 +20,11 @@ This subsystem only supports PS/2 Set 1 for now and provides these words: ps2@? ( -- keycode? f ) Calls (ps2@?) and yields the result as-is, but also update the ps2mods flags. +ps2kcset1>ascii ( kc -- is-released c ) + Given a keycode from Set 1 "kc", yield the corresponding ASCII character. + "is-released" is a flag being 1 if "kc" indicates that the key has been + released and 0 if it indicates that the key has been pressed. + ps2keyset1 ( -- c ) Blocks until a key is released (which implies it has been pressed) from the keyboard and yield its associated ASCII value according to PS/2 Set 1, diff --git a/fs/doc/uxn.txt b/fs/doc/uxn.txt @@ -0,0 +1,75 @@ +# uxn emulator + +There's a uxn emulator along with varvara device implementation living in +emul/uxn. Loading emul/uxn/vm.fs exposes this API: + +Device + An exported structure to allow direct access to the device memory area. See + emul/uxn/vm.c for field list. + +uxn_init ( -- ) + Initialize stacks and zero-out all device data and DEI/DEO handler pointers to + "null" handlers (will simply read/write from/to "Device dat"). + +uxn_ram ( -- a ) + Address, on the host, of the 64K memory area for the uxn VM. You will + typically want to put your bytecode at uxn_ram + $100. + +uxn_dev ( port -- dev ) + Yields the address of the Device structure corresponding to "port", a number + between 0 and 15. + +uxn_exec ( frompc -- ) + Repeatedly execute instructions from memory, starting at PC "frompc". Stop + when a BRK is encountered. You'll typically want to call this with, + frompc=$100, but varvara device handlers also call this with frompc=vector. + +## Varvara + +uxn is a lot more fun when combined with varvara, its companion set of virtual +devices. Dusk splits varvara in two: the "console" part and the "gui" part. + +The console part is loaded through emul/uxn/varvara.fs and exposes this: + +varvara_init ( -- ) + Initialize the uxn VM devices with DEI/DEO handlers for System, Console and + File devices. + +uxn_cli ( -- ) + Initialize uxn, varvara and then call uxn_exec with frompc=$100. + +## Varvara GUI + +The GUI part of varvara is loaded through emul/uxn/gui.fs: + +gui_init ( -- ) + Puts the screen into graphical mode and initializes the Screen and Controller + devices. If your console isn't graphical (that is, 100% of console + implementations in Dusk at the moment), this locks you out of the computer, so + don't call this interactively without a way to get out of it again. + +gui_deinit ( -- ) + Put the screen back to text mode. + +uxn_gui ( -- ) + Initializes uxn, varvara and put the screen in graphical mode. Then, call + uxn_exec with frompc=$100, and then enter the "graphical loop". That is: + + 1. Call Screen vector if nonzero + 2. Check for controller input + 3. Update Controller device accordingly and call vector if needed. + 4. Check if Escape key has been pressed then released. + 5. If yes, deinit screen and exit loop. If no, goto 1. + +## uxntal + +You can assemble ".tal" file with the uxntal assembler at asm/uxntal.fs. When +loaded, exposes this API: + +uxntal ( srchdl -- res ) + Read IO handler "srchdl" until EOF and spits the resulting bytecode to StdOut. + Yields a numberical result code which is 0 on success and nonzero on error. + +tal>vm ( path -- res ) + Conveniently wraps "uxntal" for a common case: open a file path "path" (a + string) and assemble it at uxn_ram + $100. diff --git a/fs/emul/uxn/gui.fs b/fs/emul/uxn/gui.fs @@ -0,0 +1,137 @@ +\ Varvara GUI devices implementation +require /sys/draw.fs +?f<< /lib/bit.fs +?f<< /emul/uxn/varvara.fs + +\ FG Mask: to properly handle FG/BG logic, we need to know which pixels are +\ "filled" on the FG layer, that is, have a non-zero color. When it is, a draw +\ operation on the BG layer will have no effect. +\ Let's say, for now, that maximum supported resolution is 1024x768 +1024 768 * 8 / const FGMASKSZ +create _fgmask FGMASKSZ allot + +: _fg' ( x y -- bit a ) + scrwidth * + 8 /mod ( bit a ) _fgmask + ; +: _fg! ( x y id -- ) + >r _fg' dup c@ ( bit a n ) + rot r> if bit1! else bit0! then ( a n ) + swap c! ; +: _fg? ( x y -- f ) _fg' c@ swap bit? ; + +\ example: $5678 for "r" means ID0=5 ID1=6 ID2=7 ID3=8 +: _extract ( systemrgb id -- rgb8 ) + 3 -^ << << rshift $f and ( rgb4 ) 4 lshift ; +\ get color from uxn's System.(r|g|b) for specified ID (0-3) +: screencolor ( id -- color ) >r \ V1=id + 0 uxn_dev Device dat 8 + ( 'r ) + dup short@ r@ _extract ( 'r r8 ) + swap 1+ 1+ dup short@ r@ _extract ( r8 'g g8 ) + swap 1+ 1+ short@ r> _extract ( r8 g8 b8 ) rgbcolor ; +: _drawpixel ( x y pixel -- ) + 3 and screencolor ( x y color ) + rot> pixel' pixel! ; +: _drawlayer ( x y pixel fg? -- ) + if >r 2dup r@ _fg! r> _drawpixel + else >r 2dup _fg? if 2drop rdrop else r> _drawpixel then then ; +:c void _drawlayer(ushort x, ushort y, uchar pixel, int fg); + +: screendei ( dev port -- c ) case + $2 of = drop scrwidth 8 rshift endof + $3 of = drop scrwidth $ff and endof + $4 of = drop scrheight 8 rshift endof + $5 of = drop scrheight $ff and endof + Device dat r@ + c@ endcase ; + +: _pixel ( dev -- ) >r \ V1=dev + $8 r@ devshort@ ( x ) $a r@ devshort@ ( x y ) + $6 r@ Device dat + c@ ( x y auto ) + dup 2 and if ( y+ ) over 1+ $a r@ devshort! then ( x y auto ) + 1 and if ( x+ ) over 1+ $8 r@ devshort! then ( x y ) + $e r> Device dat + c@ ( x y pixel ) + dup $40 and _drawlayer ; + +\ Let's go with C for _blit(), the Forth version is ugly +\ 2bit channel * 4bit blend +:c static uchar _blending[$40] = { + 0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, + 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}; + +:c static uchar _opaque[$10] = { + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}; + +:c void _blit(ushort x, ushort y, uchar *sprite, int spriteopts) { + int i, j, row, blend, rx, ry; + int color = spriteopts & $f; + int opaque = _opaque[color]; + int twobpp = spriteopts & $80; + int fg = spriteopts & $40; + + for(i=0; i<8; ++i) { + row = sprite[i] | (twobpp ? sprite[i + 8] : 0) << 8; + // TODO: "ry = spriteopts & $20 ? y + 7 - i : y + i" doesn't compile + if (spriteopts & $20) ry = y + 7 - i; else ry = y + i; + for(j=0; j<8; ++j) { + if (spriteopts & $10) rx = x + 7 - j; else rx = x + j; + blend = ((row & $80) >> 3) | ((row & $8000) >> 10); + if (opaque || blend) { + blend = _blending[blend | color]; + _drawlayer(rx, ry, blend, fg); + } + row <<= 1; + } + } +} + +: _sprite ( dev -- ) + $f over Device dat + c@ >r \ V1=spriteopts + $8 over devshort@ >r $a over devshort@ >r \ V2=x V3=y + $c over devshort@ uxn_ram + >r ( dev ) \ V4=sprite' + $6 over Device dat + c@ swap ( auto dev ) + over $1 and if $8 over V2 8 + rot> devshort! then ( auto dev ) + over $2 and if $a over V3 8 + rot> devshort! then ( auto dev ) + drop dup 4 rshift ( length ) 1+ >r begin ( auto ) + V2 V3 V4 V1 _blit ( auto ) + dup $1 and if 8 to+ V3 then + dup $2 and if 8 to+ V2 then + dup $4 and if 8 to+ V4 V1 $80 and if 8 to+ V4 then then + next ( auto ) drop rfree ; + +: screendeo ( dev port -- ) + 0 to@! rgbchanged if \ we need to fill the screen with the new color + 0 screencolor scrwidth scrheight 0 0 drawrect then + case ( dev ) \ V1=case + $e of = _pixel endof + $f of = _sprite endof + drop endcase ; + +\ Check for key presses and return whether the GUI program should exit (when ESC +\ is pressed). +: controllerloop ( -- f ) + ps2@? if + $8 uxn_dev >r \ V1=dev + ps2mods $f000 and 8 rshift ( kc arrows ) + ps2mods PS2_MOD_CTRL and bool or ( kc buttons ) + ps2mods PS2_MOD_ALT and bool << or ( kc buttons ) + ps2mods PS2_MOD_LSHIFT and bool << << or ( kc buttons ) + ps2mods PS2_MOD_RSHIFT and bool << << << or ( kc buttons ) + r@ Device dat 2 + c! ( kc ) + ps2kcset1>ascii swap not if drop 0 then ( c-or-0 ) + dup r@ Device dat 3 + c! ( c-or-0 ) + $1b = + r> Device dat short@ ?dup if uxn_exec then ( f ) + else 0 then ; + +\ TODO depend on more generic versions of vesamode! vgatext! and ps2@? +: gui_init + _fgmask FGMASKSZ 0 fill + $2 ['] screendei ['] screendeo uxn_set_dev + $112 vesamode! ; + +: gui_deinit vgatext! ; + +: uxn_gui ( -- ) + uxn_init varvara_init gui_init $100 uxn_exec begin ( ) + $2 uxn_dev Device dat short@ ?dup if uxn_exec then controllerloop until + gui_deinit ; diff --git a/fs/emul/uxn/screen.fs b/fs/emul/uxn/screen.fs @@ -1,120 +0,0 @@ -\ Varvara screen implementation -require /sys/draw.fs -?f<< /lib/bit.fs -?f<< /emul/uxn/varvara.fs - -\ FG Mask: to properly handle FG/BG logic, we need to know which pixels are -\ "filled" on the FG layer, that is, have a non-zero color. When it is, a draw -\ operation on the BG layer will have no effect. -\ Let's say, for now, that maximum supported resolution is 1024x768 -1024 768 * 8 / const FGMASKSZ -create _fgmask FGMASKSZ allot - -: _fg' ( x y -- bit a ) - scrwidth * + 8 /mod ( bit a ) _fgmask + ; -: _fg! ( x y id -- ) - >r _fg' dup c@ ( bit a n ) - rot r> if bit1! else bit0! then ( a n ) - swap c! ; -: _fg? ( x y -- f ) _fg' c@ swap bit? ; - -\ example: $5678 for "r" means ID0=5 ID1=6 ID2=7 ID3=8 -: _extract ( systemrgb id -- rgb8 ) - 3 -^ << << rshift $f and ( rgb4 ) 4 lshift ; -\ get color from uxn's System.(r|g|b) for specified ID (0-3) -: screencolor ( id -- color ) >r \ V1=id - 0 uxn_dev Device dat 8 + ( 'r ) - dup short@ r@ _extract ( 'r r8 ) - swap 1+ 1+ dup short@ r@ _extract ( r8 'g g8 ) - swap 1+ 1+ short@ r> _extract ( r8 g8 b8 ) rgbcolor ; -: _drawpixel ( x y pixel -- ) - 3 and screencolor ( x y color ) - rot> pixel' pixel! ; -: _drawlayer ( x y pixel fg? -- ) - if >r 2dup r@ _fg! r> _drawpixel - else >r 2dup _fg? if 2drop rdrop else r> _drawpixel then then ; -:c void _drawlayer(ushort x, ushort y, uchar pixel, int fg); - -: screendei ( dev port -- c ) case - $2 of = drop scrwidth 8 rshift endof - $3 of = drop scrwidth $ff and endof - $4 of = drop scrheight 8 rshift endof - $5 of = drop scrheight $ff and endof - Device dat r@ + c@ endcase ; - -: _pixel ( dev -- ) >r \ V1=dev - $8 r@ devshort@ ( x ) $a r@ devshort@ ( x y ) - $6 r@ Device dat + c@ ( x y auto ) - dup 2 and if ( y+ ) over 1+ $a r@ devshort! then ( x y auto ) - 1 and if ( x+ ) over 1+ $8 r@ devshort! then ( x y ) - $e r> Device dat + c@ ( x y pixel ) - dup $40 and _drawlayer ; - -\ Let's go with C for _blit(), the Forth version is ugly -\ 2bit channel * 4bit blend -:c static uchar _blending[$40] = { - 0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0, - 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, - 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, - 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}; - -:c static uchar _opaque[$10] = { - 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}; - -:c void _blit(ushort x, ushort y, uchar *sprite, int spriteopts) { - int i, j, row, blend, rx, ry; - int color = spriteopts & $f; - int opaque = _opaque[color]; - int twobpp = spriteopts & $80; - int fg = spriteopts & $40; - - for(i=0; i<8; ++i) { - row = sprite[i] | (twobpp ? sprite[i + 8] : 0) << 8; - // TODO: "ry = spriteopts & $20 ? y + 7 - i : y + i" doesn't compile - if (spriteopts & $20) ry = y + 7 - i; else ry = y + i; - for(j=0; j<8; ++j) { - if (spriteopts & $10) rx = x + 7 - j; else rx = x + j; - blend = ((row & $80) >> 3) | ((row & $8000) >> 10); - if (opaque || blend) { - blend = _blending[blend | color]; - _drawlayer(rx, ry, blend, fg); - } - row <<= 1; - } - } -} - -: _sprite ( dev -- ) - $f over Device dat + c@ >r \ V1=spriteopts - $8 over devshort@ >r $a over devshort@ >r \ V2=x V3=y - $c over devshort@ uxn_ram + >r ( dev ) \ V4=sprite' - $6 over Device dat + c@ swap ( auto dev ) - over $1 and if $8 over V2 8 + rot> devshort! then ( auto dev ) - over $2 and if $a over V3 8 + rot> devshort! then ( auto dev ) - drop dup 4 rshift ( length ) 1+ >r begin ( auto ) - V2 V3 V4 V1 _blit ( auto ) - dup $1 and if 8 to+ V3 then - dup $2 and if 8 to+ V2 then - dup $4 and if 8 to+ V4 V1 $80 and if 8 to+ V4 then then - next ( auto ) drop rfree ; - -: screendeo ( dev port -- ) - 0 to@! rgbchanged if \ we need to fill the screen with the new color - 0 screencolor scrwidth scrheight 0 0 drawrect then - case ( dev ) \ V1=case - $e of = _pixel endof - $f of = _sprite endof - drop endcase ; - -\ TODO depend on more generic versions of vesamode! vgatext! and ps2@? -: screen_init - _fgmask FGMASKSZ 0 fill - $2 ['] screendei ['] screendeo uxn_set_dev - $112 vesamode! ; - -: screen_deinit vgatext! ; - -: uxn_gui ( -- ) - 8042ps2$ uxn_init varvara_init screen_init $100 uxn_exec begin ( ) - $2 uxn_dev Device dat short@ ?dup if uxn_exec then ps2@? until - drop screen_deinit ; diff --git a/fs/sys/ps2.fs b/fs/sys/ps2.fs @@ -37,7 +37,7 @@ alias abort (ps2@?) ( -- keycode? f ) \ 0 1 2 3 4 5 6 7 8 9 a b c d e f create _maplower $80 nc, -0 0 '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '=' BS $09 +0 $1b '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '=' BS $09 'q' 'w' 'e' 'r' 't' 'y' 'u' 'i' 'o' 'p' '[' ']' CR $82 'a' 's' 'd' 'f' 'g' 'h' 'j' 'k' 'l' ';' ''' '`' $80 '\' 'z' 'x' 'c' 'v' 'b' 'n' 'm' ',' '.' '/' $81 '*' $84 SPC $88 $90 $91 $92 $93 $94 @@ -49,7 +49,7 @@ $95 $96 $97 $98 $99 $89 $8a '7' '8' '9' '-' '4' '5' '6' '+' '1' \ Same values, but shifted \ 0 1 2 3 4 5 6 7 8 9 a b c d e f create _mapupper $80 nc, -0 0 '!' '@' '#' '$' '%' '^' '&' '*' '(' ')' '_' '+' BS $09 +0 $1b '!' '@' '#' '$' '%' '^' '&' '*' '(' ')' '_' '+' BS $09 'Q' 'W' 'E' 'R' 'T' 'Y' 'U' 'I' 'O' 'P' '{' '}' CR $82 'A' 'S' 'D' 'F' 'G' 'H' 'J' 'K' 'L' ':' '"' '~' $80 '|' 'Z' 'X' 'C' 'V' 'B' 'N' 'M' '<' '>' '?' $81 '*' $84 SPC $88 $90 $91 $92 $93 $94 @@ -65,19 +65,19 @@ create _mapextended $80 nc, 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 $8d 0 0 $8e 0 $8f 0 0 -$8c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 $8c 0 0 $8e 0 $8f 0 0 +$8d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -: _map@ ( kc -- is-released c-or-0 ) +: ps2kcset1>ascii ( kc -- is-released c-or-0 ) dup $80 and swap dup $7f and swap 8 rshift if _mapextended else _shift? if _mapupper else _maplower then then + c@ ; : ps2@? ( -- keycode? f ) (ps2@?) dup if - over _map@ dup $f0 and $80 = if ( kc f is-released mod-id ) + over ps2kcset1>ascii dup $f0 and $80 = if ( kc f is-released mod-id ) $0f and swap if ( kc f mod-id ) \ key released, unset mod $fe swap lshift ps2mods and to ps2mods else ( kc f mod-id ) \ key pressed, set mod @@ -89,7 +89,7 @@ $8c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ Poll ps2@, apply shift logic, return the corresponding ASCII code. : ps2keyset1 ( -- c ) begin - begin ps2@? until ( kc ) _map@ ( is-released c-or-0 ) + begin ps2@? until ( kc ) ps2kcset1>ascii ( is-released c-or-0 ) swap if \ released, do nothing drop 0 else \ pressed diff --git a/fs/tests/manual/uxn/ctrl.fs b/fs/tests/manual/uxn/ctrl.fs @@ -0,0 +1,5 @@ +?f<< /asm/uxntal.fs +?f<< /emul/uxn/gui.fs + +S" /tests/manual/uxn/ctrl.tal" tal>vm drop +uxn_gui diff --git a/fs/tests/manual/uxn/ctrl.tal b/fs/tests/manual/uxn/ctrl.tal @@ -0,0 +1,172 @@ +( Source: https://git.sr.ht/~rabbits/uxn + Filename: projects/examples/devices/controller.tal + License: /license/dll-uxn.txt ) +( Controller: + Buttons should highlight on press and display the button and key bytes. ) + +|00 @System &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 +|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 +|80 @Controller &vector $2 &button $1 &key $1 + +|0000 + +@center + &x $2 &y $2 +@frame + &w $2 &h $2 &x0 $2 &y0 $2 &x1 $2 &y1 $2 + +|0100 ( -> ) + + ( theme ) + #0fff .System/r DEO2 + #0f0f .System/g DEO2 + #0f0f .System/b DEO2 + ( find center ) + .Screen/width DEI2 #01 SFT2 .center/x STZ2 + .Screen/height DEI2 #01 SFT2 .center/y STZ2 + ( place controller ) + #0068 .frame/w STZ2 + #0030 .frame/h STZ2 + .center/x LDZ2 .frame/w LDZ2 #01 SFT2 SUB2 .frame/x0 STZ2 + .center/y LDZ2 .frame/h LDZ2 #01 SFT2 SUB2 .frame/y0 STZ2 + .frame/x0 LDZ2 .frame/w LDZ2 ADD2 .frame/x1 STZ2 + .frame/y0 LDZ2 .frame/h LDZ2 ADD2 .frame/y1 STZ2 + ( vectors ) + ;on-button .Controller/vector DEO2 + ( frame ) + .frame/x0 LDZ2 .frame/y0 LDZ2 + .frame/x1 LDZ2 .frame/y1 LDZ2 + #03 ;line-rect JSR2 + + ,draw-controller JSR + +BRK + +@on-button ( -> ) + + ,draw-controller JSR + + ( print stack on start button ) + .Controller/button DEI #08 EQU [ JMP BRK ] #010e DEO + +BRK + +@draw-controller ( -- ) + + .Controller/button DEI STH + + ( d-pad ) + .frame/x0 LDZ2 #0010 ADD2 .Screen/x DEO2 + .frame/y0 LDZ2 #0010 ADD2 .Screen/y DEO2 + ;controller-icn/dpad-up .Screen/addr DEO2 + #03 STHkr #04 SFT #01 AND SUB .Screen/sprite DEO + .Screen/y DEI2 #0010 ADD2 .Screen/y DEO2 + ;controller-icn/dpad-down .Screen/addr DEO2 + #03 STHkr #05 SFT #01 AND SUB .Screen/sprite DEO + .Screen/y DEI2 #0008 SUB2 .Screen/y DEO2 + .Screen/x DEI2 #0008 SUB2 .Screen/x DEO2 + ;controller-icn/dpad-left .Screen/addr DEO2 + #03 STHkr #06 SFT #01 AND SUB .Screen/sprite DEO + .Screen/x DEI2 #0010 ADD2 .Screen/x DEO2 + ;controller-icn/dpad-right .Screen/addr DEO2 + #03 STHkr #07 SFT #01 AND SUB .Screen/sprite DEO + .Screen/x DEI2 #0008 SUB2 .Screen/x DEO2 + ;controller-icn/dpad .Screen/addr DEO2 + #03 .Screen/sprite DEO + + ( options ) + .center/y LDZ2 #0009 ADD2 .Screen/y DEO2 + .center/x LDZ2 #0009 SUB2 .Screen/x DEO2 + ;controller-icn/option .Screen/addr DEO2 + #03 STHkr #03 SFT #01 AND SUB .Screen/sprite DEO + .center/x LDZ2 #0004 ADD2 .Screen/x DEO2 + ;controller-icn/option .Screen/addr DEO2 + #03 STHkr #02 SFT #01 AND SUB .Screen/sprite DEO + + ( buttons ) + .center/y LDZ2 .Screen/y DEO2 + .center/x LDZ2 #0018 ADD2 .Screen/x DEO2 + ;controller-icn/button .Screen/addr DEO2 + #03 STHkr #01 SFT #01 AND SUB .Screen/sprite DEO + .Screen/y DEI2 #000a ADD2 .Screen/y DEO2 + ;font-hex/b .Screen/addr DEO2 + #03 .Screen/sprite DEO + + .center/y LDZ2 .Screen/y DEO2 + .center/x LDZ2 #0024 ADD2 .Screen/x DEO2 + ;controller-icn/button .Screen/addr DEO2 + #03 STHr #01 AND SUB .Screen/sprite DEO + .Screen/y DEI2 #000a ADD2 .Screen/y DEO2 + ;font-hex/a .Screen/addr DEO2 + #03 .Screen/sprite DEO + + .center/x LDZ2 #0010 SUB2 .Screen/x DEO2 + .center/y LDZ2 #0010 SUB2 .Screen/y DEO2 + #01 .Screen/auto DEO + .Controller/button DEI2 ,draw-short JSR + #00 .Screen/auto DEO + +JMP2r + +( generics ) + +@draw-short ( short* -- ) + + SWP ,draw-byte JSR + +@draw-byte ( byte -- ) + + DUP #04 SFT ,draw-hex JSR + +@draw-hex ( char -- ) + + #00 SWP #0f AND #30 SFT2 ;font-hex ADD2 .Screen/addr DEO2 + #03 .Screen/sprite DEO + +JMP2r + +@line-rect ( x1* y1* x2* y2* color -- ) + + STH + DUP2 ,&ver-y2 STR2 ,&hor-y2 STR2 + DUP2 ,&ver-x2 STR2 ,&hor-x2 STR2 + DUP2 ,&ver-y1 STR2 ,&hor-y1 STR2 + DUP2 ,&ver-x1 STR2 ,&hor-x1 STR2 + ( horizontal ) + [ LIT2 &hor-x2 $2 ] INC2 [ LIT2 &hor-x1 $2 ] + &hor + DUP2 .Screen/x DEO2 + [ LIT2 &hor-y1 $2 ] .Screen/y DEO2 STHkr .Screen/pixel DEOk + [ LIT2 &hor-y2 $2 ] .Screen/y DEO2 DEO + INC2 GTH2k ,&hor JCN + POP2 POP2 + ( vertical ) + [ LIT2 &ver-y2 $2 ] [ LIT2 &ver-y1 $2 ] + &ver + DUP2 .Screen/y DEO2 + [ LIT2 &ver-x1 $2 ] .Screen/x DEO2 STHkr .Screen/pixel DEOk + [ LIT2 &ver-x2 $2 ] .Screen/x DEO2 DEO + INC2 GTH2k ,&ver JCN + POP2 POP2 + POPr + +JMP2r + +@controller-icn + &dpad ffff ffff ffff ffff + &dpad-up 7eff e7c3 ffff ffff + &dpad-down ffff ffff c3e7 ff7e + &dpad-left 7fff efcf cfef ff7f + &dpad-right feff f7f3 f3f7 fffe + &option 0000 7eff ff7e 0000 + &button 3c7e ffff ffff 7e3c + +@font-hex + 007c 8282 8282 827c 0030 1010 1010 1010 + 007c 8202 7c80 80fe 007c 8202 1c02 827c + 000c 1424 4484 fe04 00fe 8080 7c02 827c + 007c 8280 fc82 827c 00fe 0202 0408 1010 + 007c 8282 7c82 827c 007c 8282 7e02 827c + &a 007c 8202 7e82 827e &b 00fc 8282 fc82 82fc + 007c 8280 8080 827c 00fc 8282 8282 82fc + 00fe 8080 fe80 80fe 00fe 8080 f080 8080 diff --git a/fs/tests/manual/uxn/mandel.fs b/fs/tests/manual/uxn/mandel.fs @@ -1,6 +1,6 @@ \ Test varvara's screen by drawing a mandelbrot on screen ?f<< /asm/uxntal.fs -?f<< /emul/uxn/screen.fs +?f<< /emul/uxn/gui.fs S" /tests/manual/uxn/mandel.tal" tal>vm drop uxn_gui diff --git a/fs/tests/manual/uxn/pixdance.fs b/fs/tests/manual/uxn/pixdance.fs @@ -1,6 +1,6 @@ \ Test varvara's screen vector by progressively drawing pixels ?f<< /asm/uxntal.fs -?f<< /emul/uxn/screen.fs +?f<< /emul/uxn/gui.fs S" /tests/manual/uxn/pixdance.tal" tal>vm drop uxn_gui diff --git a/fs/tests/manual/uxn/rect.fs b/fs/tests/manual/uxn/rect.fs @@ -1,6 +1,6 @@ \ Test varvara's screen by drawing a rect on screen ?f<< /asm/uxntal.fs -?f<< /emul/uxn/screen.fs +?f<< /emul/uxn/gui.fs S" /tests/manual/uxn/rect.tal" tal>vm drop uxn_gui diff --git a/fs/tests/manual/uxn/sprite.fs b/fs/tests/manual/uxn/sprite.fs @@ -1,5 +1,5 @@ ?f<< /asm/uxntal.fs -?f<< /emul/uxn/screen.fs +?f<< /emul/uxn/gui.fs S" /tests/manual/uxn/sprite.tal" tal>vm drop uxn_gui