From ac9f94dd6daf63337fe05a22ad4388ab8208e3ca Mon Sep 17 00:00:00 2001 From: neauoire Date: Wed, 14 Apr 2021 12:11:01 -0700 Subject: [PATCH] Optimizing drawing routines --- build.sh | 2 +- projects/examples/gui.picture.usm | 106 ++++++++++--------- projects/examples/gui.shapes.usm | 164 +++++++++--------------------- projects/pictures/ergo100x0c0.chr | Bin 0 -> 6144 bytes projects/pictures/felix0c0c.chr | Bin 0 -> 2304 bytes 5 files changed, 105 insertions(+), 167 deletions(-) create mode 100644 projects/pictures/ergo100x0c0.chr create mode 100644 projects/pictures/felix0c0c.chr diff --git a/build.sh b/build.sh index cc47c2f..aa843ea 100755 --- a/build.sh +++ b/build.sh @@ -32,7 +32,7 @@ else fi echo "Assembling.." -./bin/assembler projects/examples/gui.shapes.usm bin/boot.rom +./bin/assembler projects/examples/gui.picture.usm bin/boot.rom echo "Running.." if [ "${2}" = '--cli' ]; diff --git a/projects/examples/gui.picture.usm b/projects/examples/gui.picture.usm index 08438e9..dbb546e 100644 --- a/projects/examples/gui.picture.usm +++ b/projects/examples/gui.picture.usm @@ -1,13 +1,14 @@ ( GUI Picture ) %RTN { JMP2r } +%8+ { #0008 ADD2 } -;pointer { x 2 y 2 sprite 2 } -;pict { x 2 y 2 width 2 height 2 color 1 addr 2 } +;color { byte 1 } +;position { x 2 y 2 } +;size { width 2 height 2 } |0100 ;System { vector 2 pad 6 r 2 g 2 b 2 } |0120 ;Screen { vector 2 width 2 height 2 pad 2 x 2 y 2 addr 2 color 1 } -|0160 ;Mouse { vector 2 x 2 y 2 state 1 chord 1 } |0170 ;File { vector 2 pad 6 name 2 length 2 load 2 save 2 } ( program ) @@ -15,18 +16,15 @@ |0200 ( theme ) #ac52 =System.r #a362 =System.g #b253 =System.b - ( vectors ) ,on-mouse =Mouse.vector ( vectors ) ,on-transfer =File.vector - ( load ) + ( background ) ,checker_icn #23 ,cover-pattern JSR2 - #0000 #0000 #0100 #0100 #2c ,pict_large ,draw-picture JSR2 + #0008 #0008 #0100 #00c0 #2c ,pict_large ,draw-icn JSR2 + #0020 #00d0 #0020 #0020 #25 ,pict_small ,draw-icn JSR2 - #0128 #0010 #0080 #0080 #2e ,pict_medium ,draw-picture JSR2 - #0020 #00d0 #0020 #0020 #25 ,pict_small ,draw-picture JSR2 - - #0010 #0010 #0020 #0010 #25 ,dvd_icn ,draw-picture JSR2 + #0010 #0010 #0020 #0010 #25 ,dvd_icn ,draw-icn JSR2 ( load ) ,filepath =File.name #4000 =File.length ,img =File.load @@ -35,58 +33,71 @@ BRK @on-transfer ( -> ) ( draw ) #0080 #0020 #0100 #0100 #41 ,img ,draw-chr JSR2 + #0128 #0010 #0080 #0080 #2e ,pict_medium ,draw-icn JSR2 BRK -@on-mouse ( -> ) - - ( clear last cursor ) - ,clear_icn =Screen.addr - ~pointer.x =Screen.x - ~pointer.y =Screen.y - #30 =Screen.color - - ( record pointer positions ) - ~Mouse.x =pointer.x ~Mouse.y =pointer.y - - ( draw new cursor ) - ,pointer_icn =Screen.addr - ~pointer.x =Screen.x - ~pointer.y =Screen.y - #33 =Screen.color - -BRK - -@draw-chr ( x y width height color addr ) +@draw-icn ( x y width height color addr -- ) - DUP2 =Screen.addr =pict.addr =pict.color =pict.height =pict.width DUP2 =Screen.y =pict.y =pict.x + ( load ) =Screen.addr =color =size.height =size.width =position.y =position.x + #0000 ~size.height $ver - ~pict.x =Screen.x + ( save ) OVR2 ~position.y ADD2 =Screen.y + #0000 ~size.width $hor - ( draw ) ~pict.color =Screen.color - ( incr ) ~Screen.x #0008 ADD2 =Screen.x + ( save ) OVR2 ~position.x ADD2 =Screen.x + ( draw ) ~color =Screen.color + ( incr ) ~Screen.addr 8+ =Screen.addr + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$hor JNZ + POP2 POP2 + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$ver JNZ + POP2 POP2 + +RTN + +@draw-chr ( x y width height color addr -- ) + + ( load ) =Screen.addr =color =size.height =size.width =position.y =position.x + #0000 ~size.height + $ver + ( save ) OVR2 ~position.y ADD2 =Screen.y + #0000 ~size.width + $hor + ( save ) OVR2 ~position.x ADD2 =Screen.x + ( draw ) ~color =Screen.color ( incr ) ~Screen.addr #0010 ADD2 =Screen.addr - ~Screen.x ~pict.width ~pict.x ADD2 LTH2 ^$hor JNZ - ( incr ) ~Screen.y #0008 ADD2 =Screen.y - ~Screen.y ~pict.height ~pict.y ADD2 LTH2 ^$ver JNZ + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$hor JNZ + POP2 POP2 + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$ver JNZ + POP2 POP2 RTN -@draw-picture ( x y width height color addr ) +@cover-pattern ( addr color -- ) - DUP2 =Screen.addr =pict.addr =pict.color =pict.height =pict.width DUP2 =Screen.y =pict.y =pict.x + ( load ) =color =Screen.addr + #0000 ~Screen.height $ver - ~pict.x =Screen.x + ( save ) OVR2 =Screen.y + #0000 ~Screen.width $hor - ( draw ) ~pict.color =Screen.color - ( incr ) ~Screen.x #0008 ADD2 =Screen.x - ( incr ) ~Screen.addr #0008 ADD2 =Screen.addr - ~Screen.x ~pict.width ~pict.x ADD2 LTH2 ^$hor JNZ - ( incr ) ~Screen.y #0008 ADD2 =Screen.y - ~Screen.y ~pict.height ~pict.y ADD2 LTH2 ^$ver JNZ + ( save ) OVR2 =Screen.x + ( draw ) ~color =Screen.color + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$hor JNZ + POP2 POP2 + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$ver JNZ + POP2 POP2 RTN +@checker_icn [ f0f0 f0f0 0f0f 0f0f ] + @dvd_icn [ 001f 3f38 3838 787f 00fe fe7e 7777 e3c3 @@ -98,9 +109,6 @@ RTN f000 00e0 fcfc 8000 ] -@clear_icn [ 0000 0000 0000 0000 ] -@pointer_icn [ 80c0 e0f0 f8e0 1000 ] - @pict_small [ ff80 8080 8080 8088 ffff fffc f8f9 f1f4 ffff 0010 c721 2120 ffff 3f0f 0717 c343 diff --git a/projects/examples/gui.shapes.usm b/projects/examples/gui.shapes.usm index 988f68f..9942860 100644 --- a/projects/examples/gui.shapes.usm +++ b/projects/examples/gui.shapes.usm @@ -6,10 +6,15 @@ %8+ { #0008 ADD2 } %ABS2 { DUP2 #000f SFT2 EQU #04 JNZ #ffff MUL2 } -;pict { x 2 y 2 width 2 height 2 color 1 addr 2 } +%SIZE-TO-RECT { + STH2 STH2 OVR2 STH2r ADD2 OVR2 STH2r ADD2 +} ( x y w h -- x1 y1 x2 y2 ) + +( draw requirements ) +;color { byte 1 } + ;rect { x1 2 y1 2 x2 2 y2 2 } ;line { x0 2 y0 2 x 2 y 2 sx 2 sy 2 dx 2 dy 2 e1 2 e2 2 } -;color { byte 1 } ;circle { xc 2 yc 2 x 2 y 2 r 2 d 2 } |0100 ;System { vector 2 pad 6 r 2 g 2 b 2 } @@ -20,43 +25,20 @@ |0200 - ( theme ) #13fd =System.r #1ef3 =System.g #1bf2 =System.b - - #0010 #0020 #0040 #0060 #01 ,fill-rect-fast JSR2 - #0020 #0030 #0050 #0070 #02 ,fill-rect-fast JSR2 - #0030 #0040 #0060 #0080 #03 ,fill-rect-fast JSR2 - #0070 #0020 #00a0 #0060 #01 ,line-rect-slow JSR2 - #0080 #0030 #00b0 #0070 #02 ,line-rect-slow JSR2 - #0090 #0040 #00c0 #0080 #03 ,line-rect-slow JSR2 + ( theme ) #f03f =System.r #f03f =System.g #003f =System.b - #0000 #0080 #0020 #0020 #21 ,pict_small ,draw-picture JSR2 - #0010 #0088 #0020 #0020 #22 ,pict_small ,draw-picture JSR2 - #0020 #0090 #0020 #0020 #23 ,pict_small ,draw-picture JSR2 - #0030 #0098 #0020 #0020 #24 ,pict_small ,draw-picture JSR2 + ( background ) ,checker_icn #23 ,cover-pattern JSR2 - #0020 #0020 #0070 #0080 #01 ,draw-line JSR2 - #0020 #0080 #0070 #0030 #02 ,draw-line JSR2 - #00a0 #0020 #0050 #00b0 #03 ,draw-line JSR2 - #00b0 #0090 #0030 #0010 #01 ,draw-line JSR2 - - #0040 #0040 #0030 #01 ,draw-circle JSR2 - #0070 #0030 #0040 #02 ,draw-circle JSR2 - #0050 #0080 #0050 #03 ,draw-circle JSR2 - - ( benchmark ) - #0000 #0000 #0008 #000f #01 ,fill-rect-fast JSR2 - #0008 #0000 #0010 #000f #02 ,fill-rect-medium JSR2 - #0010 #0000 #0018 #000f #03 ,fill-rect-slow JSR2 - - ( #0000 #0010 #0008 #001f #01 ,line-rect-fast JSR2 ) - #0008 #0010 #000f #001f #02 ,line-rect-medium JSR2 - #0010 #0010 #0017 #001f #03 ,line-rect-slow JSR2 + #0010 #0030 #0020 #0020 SIZE-TO-RECT #01 ,line-slow JSR2 + #0070 #0040 #0010 #01 ,draw-circle JSR2 + #0038 #0030 #0020 #0020 SIZE-TO-RECT #01 ,line-rect JSR2 + #0038 #0058 #0020 #0020 SIZE-TO-RECT #01 ,fill-rect JSR2 BRK -@draw-line ( x1 y1 x2 y2 color ) +@line-slow ( x1 y1 x2 y2 color -- ) - ( load ) =color =line.y0 =line.x0 =line.y =line.x + ( load ) =color -- =line.y0 -- =line.x0 =line.y =line.x ~line.x0 ~line.x SUB2 ABS2 =line.dx ~line.y0 ~line.y SUB2 ABS2 #0000 SWP2 SUB2 =line.dy #ffff #00 ~line.x ~line.x0 LTS2 #0002 MUL2 ADD2 =line.sx @@ -80,43 +62,29 @@ BRK RTN -@line-rect-medium ( x1 y1 x2 y2 color -- ) +@line-rect ( x1 y1 x2 y2 color -- ) - ( load ) =color DUP2 ++ STH2 =rect.y2 =rect.x2 DUP2 STH2 =rect.y1 =rect.x1 + ( load ) =color DUP2 STH2 -- =rect.y2 -- =rect.x2 DUP2 STH2 =rect.y1 =rect.x1 STH2r STH2r $ver ( save ) OVR2 =Screen.y - ( draw ) ~rect.x1 =Screen.x ~color DUP =Screen.color ~rect.x2 =Screen.x =Screen.color + ( draw ) ~rect.x1 =Screen.x ~color DUP =Screen.color + ( draw ) ~rect.x2 =Screen.x =Screen.color ( incr ) SWP2 ++ SWP2 OVR2 OVR2 LTH2 ^$ver JNZ POP2 POP2 - ~rect.x1 ++ ~rect.x2 -- + ~rect.x1 ~rect.x2 $hor ( save ) OVR2 =Screen.x - ( draw ) ~rect.y1 =Screen.y ~color DUP =Screen.color ~rect.y2 =Screen.y =Screen.color + ( draw ) ~rect.y1 =Screen.y ~color DUP =Screen.color + ( draw ) ~rect.y2 =Screen.y =Screen.color ( incr ) SWP2 ++ SWP2 OVR2 OVR2 ++ LTH2 ^$hor JNZ POP2 POP2 -RTN - -@line-rect-slow ( x1 y1 x2 y2 color -- ) - - ( load ) =color =rect.y2 =rect.x2 DUP2 =Screen.y =rect.y1 DUP2 =Screen.x =rect.x1 - $hor - ( incr ) ~Screen.x ++ =Screen.x - ( draw ) ~rect.y1 =Screen.y ~color =Screen.color - ( draw ) ~rect.y2 =Screen.y ~color =Screen.color - ~Screen.x ~rect.x2 LTH2 ^$hor JNZ - ~rect.y1 =Screen.y - $ver - ( draw ) ~rect.x1 =Screen.x ~color =Screen.color - ( draw ) ~rect.x2 =Screen.x ~color =Screen.color - ( incr ) ~Screen.y ++ =Screen.y - ~Screen.y ~rect.y2 ++ LTH2 ^$ver JNZ RTN -@fill-rect-fast ( x1 y1 x2 y2 color -- ) +@fill-rect ( x1 y1 x2 y2 color -- ) =color ( x1 x2 y1 y2 ) ROT2 SWP2 @@ -135,67 +103,20 @@ RTN RTN -@fill-rect-medium ( x1 y1 x2 y2 color -- ) - - ( load ) =color SWP2 =rect.x2 ROT2 =rect.x1 - $ver - ( save ) OVR2 =Screen.y - ~rect.x1 ~rect.x2 - $hor - ( save ) OVR2 =Screen.x - ( draw ) ~color =Screen.color - ( incr ) SWP2 ++ SWP2 - OVR2 OVR2 LTH2 ^$hor JNZ - POP2 POP2 - ( incr ) SWP2 ++ SWP2 - OVR2 OVR2 LTH2 ^$ver JNZ - POP2 POP2 - -RTN - -@fill-rect-slow ( x1 y1 x2 y2 color -- ) - - ( load ) =color =rect.y2 =rect.x2 DUP2 =Screen.y =rect.y1 DUP2 =Screen.x =rect.x1 - $ver - ~rect.x1 =Screen.x - $hor - ( draw ) ~color =Screen.color - ( incr ) ~Screen.x ++ =Screen.x - ~Screen.x ~rect.x2 LTH2 ^$hor JNZ - ( incr ) ~Screen.y ++ =Screen.y - ~Screen.y ~rect.y2 LTH2 ^$ver JNZ - -RTN - -@draw-picture ( x y width height color addr ) - - ( load ) DUP2 =Screen.addr =pict.addr =pict.color =pict.height =pict.width DUP2 =Screen.y =pict.y =pict.x - $ver - ~pict.x =Screen.x - $hor - ( draw ) ~pict.color =Screen.color - ( incr ) ~Screen.x 8+ =Screen.x - ( incr ) ~Screen.addr 8+ =Screen.addr - ~Screen.x ~pict.width ~pict.x ADD2 LTH2 ^$hor JNZ - ( incr ) ~Screen.y 8+ =Screen.y - ~Screen.y ~pict.height ~pict.y ADD2 LTH2 ^$ver JNZ - -RTN - -@draw-circle ( xc yc r color ) +@draw-circle ( xc yc r color -- ) ( load ) =color =circle.r =circle.yc =circle.xc #0000 =circle.x ~circle.r =circle.y - ~circle.r #0002 MUL2 #0003 SUB2 =circle.d + ~circle.r #0002 MUL2 =circle.d ( draw ) ,$seg JSR2 $loop ( incr ) ~circle.x ++ =circle.x - ~circle.d #0000 ++ LTS2 ^$else JNZ + ~circle.d #0001 LTS2 ^$else JNZ ( decr ) ~circle.y -- =circle.y - ~circle.x ~circle.y SUB2 #0004 MUL2 ~circle.d ADD2 #000a ADD2 =circle.d + ~circle.x ~circle.y SUB2 #0004 MUL2 ~circle.d ADD2 =circle.d ,$end JMP2 $else - ~circle.x #0004 MUL2 ~circle.d ADD2 #0006 ADD2 =circle.d + ~circle.x #0004 MUL2 ~circle.d ADD2 =circle.d $end ( draw ) ,$seg JSR2 ~circle.y ~circle.x -- GTS2 ^$loop JNZ @@ -212,14 +133,23 @@ RTN RTN -@pict_small [ +@cover-pattern ( addr color -- ) + + ( load ) =color =Screen.addr + #0000 ~Screen.height + $ver + ( save ) OVR2 =Screen.y + #0000 ~Screen.width + $hor + ( save ) OVR2 =Screen.x + ( draw ) ~color =Screen.color + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$hor JNZ + POP2 POP2 + ( incr ) SWP2 8+ SWP2 + OVR2 OVR2 LTH2 ^$ver JNZ + POP2 POP2 - ff80 8080 8080 8088 ffff fffc f8f9 f1f4 - ffff 0010 c721 2120 ffff 3f0f 0717 c343 - 8888 8080 8080 8080 f0f1 f2f5 f2f1 f0f4 - 1208 804c 9212 4c00 7303 0343 1b1b fbfb - 8080 8f83 8383 8393 f0f3 f1f0 e4c0 80ff - 00c7 c7c6 4606 00ff c3d3 c307 870f 3fff - 8f83 8383 8383 83ff fff7 fdff c0e2 f1ff - 7fef bfff 07af 5fff ffff ffff ffff ffff -] +RTN + +@checker_icn [ f0f0 f0f0 0f0f 0f0f ] diff --git a/projects/pictures/ergo100x0c0.chr b/projects/pictures/ergo100x0c0.chr new file mode 100644 index 0000000000000000000000000000000000000000..cc50cbe1356c751767beec45b2bc05bbaf1c1ef8 GIT binary patch literal 6144 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 P_Wq*4>DYbttH;qdt1}51 literal 0 HcmV?d00001