commit 41f39e99993a73ca0c89bbfd68a01ae674170ebb
parent be12a3ff69e1946fa3e3084b057eb6177f3466a1
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 2 Jan 2023 22:27:19 -0500
emul/uxn: make varvara screen buffer
Instead of having only a "fg mask", fully buffer 2bit fg/bg colors. The previous
approach didn't work well in cases where the fg pixel was set to 0 and that a
previous bg was present: we didn't know what color that bg pixel was so we
couldn't restore it.
By buffering colors of both layers, this problem is solved.
Diffstat:
2 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/fs/emul/uxn/gui.fs b/fs/emul/uxn/gui.fs
@@ -3,20 +3,19 @@ require /sys/screen.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.
+\ The screen buffer is an array of 8bit pixel, b1:0 being foreground, b3:2 being
+\ background, b7:4 being wasted.
\ Let's say, for now, that maximum supported resolution is 1024x768
-1024 768 * 8 / const FGMASKSZ
-create _fgmask FGMASKSZ allot
+1024 768 * const SCRBUFSZ
+create _scrbuf SCRBUFSZ allot
-: _fg' ( x y -- bit a )
- screen width * + 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? ;
+\ Blends the fg/bg color in the buffer and yield the actual pixel to draw.
+: _scrblend ( x y pixel fg? -- pixel )
+ >r >r screen width * + _scrbuf + dup c@ ( a n )
+ r> r> ( a n pixel fg? )
+ if swap $c and or else << << swap $3 and or then ( a n )
+ tuck swap c! ( n )
+ dup $3 and ?dup if nip else >> >> then ( n ) ;
\ example: $5678 for "r" means ID0=5 ID1=6 ID2=7 ID3=8
: _extract ( systemrgb id -- rgb8 )
@@ -31,8 +30,7 @@ create _fgmask FGMASKSZ allot
3 and screencolor to screen color ( x y )
screen :pos! screen :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 ;
+ >r >r 2dup r> r> _scrblend _drawpixel ;
:c void _drawlayer(ushort x, ushort y, uchar pixel, int fg);
: screendei ( dev port -- c ) case
@@ -137,7 +135,7 @@ create _buf $10 allot \ to check for value changes
r@ Device dat _buf $10 []= if rdrop else r> _?execvector then ;
: gui_init
- _fgmask FGMASKSZ 0 fill
+ _scrbuf SCRBUFSZ 0 fill
$2 ['] screendei ['] screendeo uxn_set_dev
screen :activate ;
diff --git a/fs/tests/manual/uxn/mouse.tal b/fs/tests/manual/uxn/mouse.tal
@@ -47,8 +47,6 @@ BRK
@on-mouse ( -> )
;pointer-icn .Screen/addr DEO2
- ( TODO: clearing the cursor erases the doodling below. It doesn't do it on
- the regular uxnemu. )
( clear last cursor )
.pointer/x LDZ2 .Screen/x DEO2
.pointer/y LDZ2 .Screen/y DEO2