diff --git a/apps/tile.mu b/apps/tile.mu index 905ae9ac..c7067e83 100644 --- a/apps/tile.mu +++ b/apps/tile.mu @@ -1,4 +1,11 @@ # Randomly tile from a given set of tiles +# +# To build: +# $ git clone https://github.com/akkartik/mu +# $ cd mu +# $ ./translate apps/tile.mu +# To run: +# $ qemu-system-i386 code.img type tile { data: (handle array handle array int) @@ -13,7 +20,7 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) #? set-tile tiles, 0/idx, 1 0 0, 0 1 0, 0 0 1 #? set-tile tiles, 1/idx, 0 0 1, 0 1 0, 1 0 0 - # https://post.lurk.org/@paul/107425083075253587 + # https://pbat.ch/wiki/trikuf var tiles-storage: (array tile 0x62) var tiles/esi: (addr array tile) <- address tiles-storage set-tile tiles, 0x00/idx, 1 1 1, 0 1 0, 0 0 0 @@ -123,7 +130,7 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) } var step/eax: int <- copy 0 { - render-random screen, tiles, 0xc/pixels-per-tile, step + render-random screen, tiles, 4/pixels-per-cell, step { var key/eax: byte <- read-key keyboard compare key, 0 @@ -194,15 +201,16 @@ fn render-tiles screen: (addr screen), _tiles: (addr array tile) { #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, i, 0x31, 0 var tile/eax: (addr tile) <- index tiles, i var start-x/edx: int <- copy i - start-x <- and 0xf # 16 cells per row - start-x <- shift-left 4/pixels-per-cell + start-x <- and 0xf/tiles-per-row-minus-one + start-x <- shift-left 5 # ceil(log(3 * pixels-per-cell)) start-x <- add 0x20/left-margin +#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, start-x, 0x31 0 var start-y/ebx: int <- copy i - start-y <- shift-right 4 # 16 cells per row - start-y <- shift-left 4/pixels-per-cell + start-y <- shift-right 4/log2-tiles-per-row + start-y <- shift-left 5 # ceil(log(3 * pixels-per-cell)) start-y <- add 0x20/top-margin #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, start-x, 0x31, 0 - render-tile screen, tile, start-x, start-y, 4/pixels-per-cell # 4 * 3 + 4 = 16 pixels wide + render-tile screen, tile, start-x, start-y, 8/pixels-per-cell i <- increment loop } @@ -229,6 +237,8 @@ fn render-tile screen: (addr screen), _tile: (addr tile), start-x: int, start-y: var curr/eax: (addr int) <- index curr-row, j var color/eax: int <- copy *curr color <- shift-left 1 +#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 9 0 +#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 0xc 0 draw-rect2 screen, x y, n n, color j <- increment x <- add n @@ -240,7 +250,7 @@ fn render-tile screen: (addr screen), _tile: (addr tile), start-x: int, start-y: } } -fn render-random screen: (addr screen), _tiles: (addr array tile), n: int, seed: int { +fn render-random screen: (addr screen), _tiles: (addr array tile), pixels-per-cell: int, seed: int { draw-rect screen, 0 0, 0x400 0x300, 8 var tiles/esi: (addr array tile) <- copy _tiles var rand/edi: int <- next-random seed @@ -255,17 +265,21 @@ fn render-random screen: (addr screen), _tiles: (addr array tile), n: int, seed: break-if->= var i/eax: int <- remainder rand, num-tiles var tile/eax: (addr tile) <- index tiles, i - render-tile-without-margin screen, tile, x, y, 4/pixels-per-cell - x <- add n + render-tile-without-margin screen, tile, x, y, pixels-per-cell + x <- add pixels-per-cell + x <- add pixels-per-cell + x <- add pixels-per-cell rand <- next-random rand loop } - y <- add n + y <- add pixels-per-cell + y <- add pixels-per-cell + y <- add pixels-per-cell loop } } -fn render-tile-without-margin screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, n: int { +fn render-tile-without-margin screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, pixels-per-cell: int { var tile/esi: (addr tile) <- copy _tile var y/ecx: int <- copy start-y var rows-ah/eax: (addr handle array handle array int) <- get tile, data @@ -284,13 +298,13 @@ fn render-tile-without-margin screen: (addr screen), _tile: (addr tile), start-x var curr/eax: (addr int) <- index curr-row, j var color/eax: int <- copy *curr color <- shift-left 1 - draw-rect2 screen, x y, n n, color + draw-rect2 screen, x y, pixels-per-cell pixels-per-cell, color j <- increment - x <- add n + x <- add pixels-per-cell loop } i <- increment - y <- add n + y <- add pixels-per-cell loop } } diff --git a/html/apps/tile.mu.html b/html/apps/tile.mu.html index 856fd715..480ef619 100644 --- a/html/apps/tile.mu.html +++ b/html/apps/tile.mu.html @@ -63,308 +63,322 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/apps/tile.mu
   1 # Randomly tile from a given set of tiles
-  2 
-  3 type tile {
-  4   data: (handle array handle array int)
-  5 }
-  6 
-  7 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
-  8   # basic maze
-  9   # 10 PRINT CHR$(205.5 + RND(1))
- 10   # GOTO 10
- 11 #?   var tiles-storage: (array tile 2)
- 12 #?   var tiles/esi: (addr array tile) <- address tiles-storage
- 13 #?   set-tile tiles, 0/idx, 1 0 0, 0 1 0, 0 0 1
- 14 #?   set-tile tiles, 1/idx, 0 0 1, 0 1 0, 1 0 0
- 15 
- 16   # https://post.lurk.org/@paul/107425083075253587
- 17   var tiles-storage: (array tile 0x62)
- 18   var tiles/esi: (addr array tile) <- address tiles-storage
- 19   set-tile tiles, 0x00/idx, 1 1 1, 0 1 0, 0 0 0
- 20   set-tile tiles, 0x01/idx, 0 1 1, 1 1 0, 0 0 0
- 21   set-tile tiles, 0x02/idx, 1 1 1, 1 0 1, 0 0 0
- 22   set-tile tiles, 0x03/idx, 1 1 0, 0 1 1, 0 0 0
- 23   set-tile tiles, 0x04/idx, 0 0 0, 1 1 1, 0 0 0
- 24   set-tile tiles, 0x05/idx, 1 0 0, 1 1 1, 0 0 0
- 25   set-tile tiles, 0x06/idx, 0 1 0, 1 1 1, 0 0 0
- 26   set-tile tiles, 0x07/idx, 0 0 1, 1 1 1, 0 0 0
- 27   set-tile tiles, 0x08/idx, 1 0 1, 1 1 1, 0 0 0
- 28   set-tile tiles, 0x09/idx, 0 1 1, 1 1 0, 1 0 0
- 29   set-tile tiles, 0x0a/idx, 0 1 1, 0 0 1, 1 0 0
- 30   set-tile tiles, 0x0b/idx, 1 1 1, 0 0 1, 1 0 0
- 31   set-tile tiles, 0x0c/idx, 1 1 1, 1 0 1, 1 0 0
- 32   set-tile tiles, 0x0d/idx, 0 0 0, 1 1 1, 1 0 0
- 33   set-tile tiles, 0x0e/idx, 1 0 0, 1 1 1, 1 0 0
- 34   set-tile tiles, 0x0f/idx, 0 1 0, 1 1 1, 1 0 0
- 35   set-tile tiles, 0x10/idx, 0 0 1, 1 1 1, 1 0 0
- 36   set-tile tiles, 0x11/idx, 1 0 1, 1 1 1, 1 0 0
- 37   set-tile tiles, 0x12/idx, 1 0 1, 0 0 0, 0 1 0
- 38   set-tile tiles, 0x13/idx, 1 1 1, 0 0 0, 0 1 0
- 39   set-tile tiles, 0x14/idx, 1 1 1, 0 1 0, 0 1 0
- 40   set-tile tiles, 0x15/idx, 0 1 1, 1 1 0, 0 1 0
- 41   set-tile tiles, 0x16/idx, 1 1 0, 0 1 1, 0 1 0
- 42   set-tile tiles, 0x17/idx, 0 0 0, 1 1 1, 0 1 0
- 43   set-tile tiles, 0x18/idx, 1 0 0, 1 1 1, 0 1 0
- 44   set-tile tiles, 0x19/idx, 0 1 0, 1 1 1, 0 1 0
- 45   set-tile tiles, 0x1a/idx, 0 0 1, 1 1 1, 0 1 0
- 46   set-tile tiles, 0x1b/idx, 1 0 1, 1 1 1, 0 1 0
- 47   set-tile tiles, 0x1c/idx, 1 0 1, 0 0 0, 1 1 0
- 48   set-tile tiles, 0x1d/idx, 0 1 1, 0 0 0, 1 1 0
- 49   set-tile tiles, 0x1e/idx, 1 1 1, 0 0 0, 1 1 0
- 50   set-tile tiles, 0x1f/idx, 0 0 1, 1 0 0, 1 1 0
- 51   set-tile tiles, 0x20/idx, 1 0 1, 1 0 0, 1 1 0
- 52   set-tile tiles, 0x21/idx, 1 1 1, 1 0 0, 1 1 0
- 53   set-tile tiles, 0x22/idx, 0 1 1, 0 1 0, 1 1 0
- 54   set-tile tiles, 0x23/idx, 1 1 1, 0 1 0, 1 1 0
- 55   set-tile tiles, 0x24/idx, 0 0 0, 0 1 1, 1 1 0
- 56   set-tile tiles, 0x25/idx, 0 1 0, 0 1 1, 1 1 0
- 57   set-tile tiles, 0x26/idx, 1 1 0, 0 1 1, 1 1 0
- 58   set-tile tiles, 0x27/idx, 0 0 1, 0 1 1, 1 1 0
- 59   set-tile tiles, 0x28/idx, 1 1 0, 1 0 0, 0 0 1
- 60   set-tile tiles, 0x29/idx, 1 1 1, 1 0 0, 0 0 1
- 61   set-tile tiles, 0x2a/idx, 1 1 1, 1 0 1, 0 0 1
- 62   set-tile tiles, 0x2b/idx, 1 1 0, 0 1 1, 0 0 1
- 63   set-tile tiles, 0x2c/idx, 0 0 0, 1 1 1, 0 0 1
- 64   set-tile tiles, 0x2d/idx, 1 0 0, 1 1 1, 0 0 1
- 65   set-tile tiles, 0x2e/idx, 0 1 0, 1 1 1, 0 0 1
- 66   set-tile tiles, 0x2f/idx, 0 0 1, 1 1 1, 0 0 1
- 67   set-tile tiles, 0x30/idx, 1 0 1, 1 1 1, 0 0 1
- 68   set-tile tiles, 0x31/idx, 0 1 0, 0 0 0, 1 0 1
- 69   set-tile tiles, 0x32/idx, 1 1 0, 0 0 0, 1 0 1
- 70   set-tile tiles, 0x33/idx, 0 1 1, 0 0 0, 1 0 1
- 71   set-tile tiles, 0x34/idx, 1 1 1, 0 0 0, 1 0 1
- 72   set-tile tiles, 0x35/idx, 1 1 0, 1 0 0, 1 0 1
- 73   set-tile tiles, 0x36/idx, 1 1 1, 1 0 0, 1 0 1
- 74   set-tile tiles, 0x37/idx, 0 1 1, 0 0 1, 1 0 1
- 75   set-tile tiles, 0x38/idx, 1 1 1, 0 0 1, 1 0 1
- 76   set-tile tiles, 0x39/idx, 1 1 1, 1 0 1, 1 0 1
- 77   set-tile tiles, 0x3a/idx, 0 0 0, 1 1 1, 1 0 1
- 78   set-tile tiles, 0x3b/idx, 1 0 0, 1 1 1, 1 0 1
- 79   set-tile tiles, 0x3c/idx, 0 1 0, 1 1 1, 1 0 1
- 80   set-tile tiles, 0x3d/idx, 0 0 1, 1 1 1, 1 0 1
- 81   set-tile tiles, 0x3e/idx, 1 0 1, 1 1 1, 1 0 1
- 82   set-tile tiles, 0x3f/idx, 1 1 0, 0 0 0, 0 1 1
- 83   set-tile tiles, 0x40/idx, 1 0 1, 0 0 0, 0 1 1
- 84   set-tile tiles, 0x41/idx, 1 1 1, 0 0 0, 0 1 1
- 85   set-tile tiles, 0x42/idx, 1 1 0, 0 1 0, 0 1 1
- 86   set-tile tiles, 0x43/idx, 1 1 1, 0 1 0, 0 1 1
- 87   set-tile tiles, 0x44/idx, 0 0 0, 1 1 0, 0 1 1
- 88   set-tile tiles, 0x45/idx, 1 0 0, 1 1 0, 0 1 1
- 89   set-tile tiles, 0x46/idx, 0 1 0, 1 1 0, 0 1 1
- 90   set-tile tiles, 0x47/idx, 0 1 1, 1 1 0, 0 1 1
- 91   set-tile tiles, 0x48/idx, 1 0 0, 0 0 1, 0 1 1
- 92   set-tile tiles, 0x49/idx, 1 0 1, 0 0 1, 0 1 1
- 93   set-tile tiles, 0x4a/idx, 1 1 1, 0 0 1, 0 1 1
- 94   set-tile tiles, 0x4b/idx, 0 1 0, 0 0 0, 1 1 1
- 95   set-tile tiles, 0x4c/idx, 1 1 0, 0 0 0, 1 1 1
- 96   set-tile tiles, 0x4d/idx, 1 0 1, 0 0 0, 1 1 1
- 97   set-tile tiles, 0x4e/idx, 0 1 1, 0 0 0, 1 1 1
- 98   set-tile tiles, 0x4f/idx, 1 1 1, 0 0 0, 1 1 1
- 99   set-tile tiles, 0x50/idx, 1 1 0, 1 0 0, 1 1 1
-100   set-tile tiles, 0x51/idx, 0 0 1, 1 0 0, 1 1 1
-101   set-tile tiles, 0x52/idx, 1 0 1, 1 0 0, 1 1 1
-102   set-tile tiles, 0x53/idx, 1 1 1, 1 0 0, 1 1 1
-103   set-tile tiles, 0x54/idx, 0 0 0, 0 1 0, 1 1 1
-104   set-tile tiles, 0x55/idx, 0 1 0, 0 1 0, 1 1 1
-105   set-tile tiles, 0x56/idx, 1 1 0, 0 1 0, 1 1 1
-106   set-tile tiles, 0x57/idx, 0 1 1, 0 1 0, 1 1 1
-107   set-tile tiles, 0x58/idx, 1 1 1, 0 1 0, 1 1 1
-108   set-tile tiles, 0x59/idx, 1 0 0, 0 0 1, 1 1 1
-109   set-tile tiles, 0x5a/idx, 1 0 1, 0 0 1, 1 1 1
-110   set-tile tiles, 0x5b/idx, 0 1 1, 0 0 1, 1 1 1
-111   set-tile tiles, 0x5c/idx, 1 1 1, 0 0 1, 1 1 1
-112   set-tile tiles, 0x5d/idx, 0 0 0, 1 0 1, 1 1 1
-113   set-tile tiles, 0x5e/idx, 1 0 0, 1 0 1, 1 1 1
-114   set-tile tiles, 0x5f/idx, 0 0 1, 1 0 1, 1 1 1
-115   set-tile tiles, 0x60/idx, 1 0 1, 1 0 1, 1 1 1
-116   set-tile tiles, 0x61/idx, 1 1 1, 1 0 1, 1 1 1
-117 
-118   render-tiles screen, tiles
-119   {
-120     var key/eax: byte <- read-key keyboard
-121     compare key, 0
-122     loop-if-=
-123   }
-124   var step/eax: int <- copy 0
-125   {
-126     render-random screen, tiles, 0xc/pixels-per-tile, step
-127     {
-128       var key/eax: byte <- read-key keyboard
-129       compare key, 0
-130       loop-if-=
-131     }
-132     step <- increment
-133     loop
-134   }
-135 }
-136 
-137 fn set-tile _tiles: (addr array tile), _idx: int, n0: int, n1: int, n2: int, n3: int, n4: int, n5: int, n6: int, n7: int, n8: int {
-138   var tiles/eax: (addr array tile) <- copy _tiles
-139   var idx/ecx: int <- copy _idx
-140   var tile/edi: (addr tile) <- index tiles, idx
-141   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
-142   populate rows-ah, 3
-143   var _rows/eax: (addr array handle array int) <- lookup *rows-ah
-144   var rows/edi: (addr array handle array int) <- copy _rows
-145   var row0-ah/eax: (addr handle array int) <- index rows, 0
-146   populate row0-ah, 3
-147   var row0/eax: (addr array int) <- lookup *row0-ah
-148   var x0/ecx: (addr int) <- index row0, 0
-149   var src/esi: int <- copy n0
-150   copy-to *x0, src
-151   var x1/ecx: (addr int) <- index row0, 1
-152   var src/esi: int <- copy n1
-153   copy-to *x1, src
-154   var x2/ecx: (addr int) <- index row0, 2
-155   var src/esi: int <- copy n2
-156   copy-to *x2, src
-157   var row1-ah/eax: (addr handle array int) <- index rows, 1
-158   populate row1-ah, 3
-159   var row1/eax: (addr array int) <- lookup *row1-ah
-160   var x3/ecx: (addr int) <- index row1, 0
-161   var src/esi: int <- copy n3
-162   copy-to *x3, src
-163   var x4/ecx: (addr int) <- index row1, 1
-164   var src/esi: int <- copy n4
-165   copy-to *x4, src
-166   var x5/ecx: (addr int) <- index row1, 2
-167   var src/esi: int <- copy n5
-168   copy-to *x5, src
-169   var row2-ah/eax: (addr handle array int) <- index rows, 2
-170   populate row2-ah, 3
-171   var row2/eax: (addr array int) <- lookup *row2-ah
-172   var x6/ecx: (addr int) <- index row2, 0
-173   var src/esi: int <- copy n6
-174   copy-to *x6, src
-175   var x7/ecx: (addr int) <- index row2, 1
-176   var src/esi: int <- copy n7
-177   copy-to *x7, src
-178   var x8/ecx: (addr int) <- index row2, 2
-179   var src/esi: int <- copy n8
-180   copy-to *x8, src
-181 }
-182 
-183 fn render-tiles screen: (addr screen), _tiles: (addr array tile) {
-184   draw-rect screen, 0 0, 0x400 0x300, 8
-185   var tiles/esi: (addr array tile) <- copy _tiles
-186   var num-tiles: int
-187   var tmp/eax: int <- length tiles
-188   copy-to num-tiles, tmp
-189 #?   draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, num-tiles, 0x31, 0
-190   var i/ecx: int <- copy 0
-191   {
-192     compare i, num-tiles
-193     break-if->=
-194 #?     draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, i, 0x31, 0
-195     var tile/eax: (addr tile) <- index tiles, i
-196     var start-x/edx: int <- copy i
-197     start-x <- and 0xf  # 16 cells per row
-198     start-x <- shift-left 4/pixels-per-cell
-199     start-x <- add 0x20/left-margin
-200     var start-y/ebx: int <- copy i
-201     start-y <- shift-right 4  # 16 cells per row
-202     start-y <- shift-left 4/pixels-per-cell
-203     start-y <- add 0x20/top-margin
-204 #?     draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, start-x, 0x31, 0
-205     render-tile screen, tile, start-x, start-y, 4/pixels-per-cell  # 4 * 3 + 4 = 16 pixels wide
-206     i <- increment
-207     loop
-208   }
-209 }
-210 
-211 fn render-tile screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, n: int {
-212   var tile/esi: (addr tile) <- copy _tile
-213   var y/ecx: int <- copy start-y
-214   y <- add 4/margin-top
-215   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
-216   var rows/eax: (addr array handle array int) <- lookup *rows-ah
-217   var i/ebx: int <- copy 0
-218   {
-219     compare i, 3
-220     break-if->=
-221     var x/edx: int <- copy start-x
-222     x <- add 4/margin-left
-223     var curr-row-ah/eax: (addr handle array int) <- index rows, i
-224     var curr-row/eax: (addr array int) <- lookup *curr-row-ah
-225     var j/edi: int <- copy 0
-226     {
-227       compare j, 3
-228       break-if->=
-229       var curr/eax: (addr int) <- index curr-row, j
-230       var color/eax: int <- copy *curr
-231       color <- shift-left 1
-232       draw-rect2 screen, x y, n n, color
-233       j <- increment
-234       x <- add n
-235       loop
-236     }
-237     i <- increment
-238     y <- add n
-239     loop
-240   }
-241 }
-242 
-243 fn render-random screen: (addr screen), _tiles: (addr array tile), n: int, seed: int {
-244   draw-rect screen, 0 0, 0x400 0x300, 8
-245   var tiles/esi: (addr array tile) <- copy _tiles
-246   var rand/edi: int <- next-random seed
-247   var num-tiles/ebx: int <- length tiles
-248   var y/ecx: int <- copy 0
-249   {
-250     compare y, 0x300
-251     break-if->=
-252     var x/edx: int <- copy 0
-253     {
-254       compare x, 0x400
-255       break-if->=
-256       var i/eax: int <- remainder rand, num-tiles
-257       var tile/eax: (addr tile) <- index tiles, i
-258       render-tile-without-margin screen, tile, x, y, 4/pixels-per-cell
-259       x <- add n
-260       rand <- next-random rand
-261       loop
-262     }
-263     y <- add n
-264     loop
-265   }
-266 }
-267 
-268 fn render-tile-without-margin screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, n: int {
-269   var tile/esi: (addr tile) <- copy _tile
-270   var y/ecx: int <- copy start-y
-271   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
-272   var rows/eax: (addr array handle array int) <- lookup *rows-ah
-273   var i/ebx: int <- copy 0
-274   {
-275     compare i, 3
-276     break-if->=
-277     var x/edx: int <- copy start-x
-278     var curr-row-ah/eax: (addr handle array int) <- index rows, i
-279     var curr-row/eax: (addr array int) <- lookup *curr-row-ah
-280     var j/edi: int <- copy 0
-281     {
-282       compare j, 3
-283       break-if->=
-284       var curr/eax: (addr int) <- index curr-row, j
-285       var color/eax: int <- copy *curr
-286       color <- shift-left 1
-287       draw-rect2 screen, x y, n n, color
-288       j <- increment
-289       x <- add n
-290       loop
-291     }
-292     i <- increment
-293     y <- add n
-294     loop
-295   }
-296 }
-297 
-298 fn remainder a: int, b: int -> _/eax: int {
-299   var q/eax: int <- copy 0
-300   var r/edx: int <- copy 0
-301   q, r <- integer-divide a, b
-302   return r
-303 }
+  2 #
+  3 # To build:
+  4 #   $ git clone https://github.com/akkartik/mu
+  5 #   $ cd mu
+  6 #   $ ./translate apps/tile.mu
+  7 # To run:
+  8 #   $ qemu-system-i386 code.img
+  9 
+ 10 type tile {
+ 11   data: (handle array handle array int)
+ 12 }
+ 13 
+ 14 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+ 15   # basic maze
+ 16   # 10 PRINT CHR$(205.5 + RND(1))
+ 17   # GOTO 10
+ 18 #?   var tiles-storage: (array tile 2)
+ 19 #?   var tiles/esi: (addr array tile) <- address tiles-storage
+ 20 #?   set-tile tiles, 0/idx, 1 0 0, 0 1 0, 0 0 1
+ 21 #?   set-tile tiles, 1/idx, 0 0 1, 0 1 0, 1 0 0
+ 22 
+ 23   # https://pbat.ch/wiki/trikuf
+ 24   var tiles-storage: (array tile 0x62)
+ 25   var tiles/esi: (addr array tile) <- address tiles-storage
+ 26   set-tile tiles, 0x00/idx, 1 1 1, 0 1 0, 0 0 0
+ 27   set-tile tiles, 0x01/idx, 0 1 1, 1 1 0, 0 0 0
+ 28   set-tile tiles, 0x02/idx, 1 1 1, 1 0 1, 0 0 0
+ 29   set-tile tiles, 0x03/idx, 1 1 0, 0 1 1, 0 0 0
+ 30   set-tile tiles, 0x04/idx, 0 0 0, 1 1 1, 0 0 0
+ 31   set-tile tiles, 0x05/idx, 1 0 0, 1 1 1, 0 0 0
+ 32   set-tile tiles, 0x06/idx, 0 1 0, 1 1 1, 0 0 0
+ 33   set-tile tiles, 0x07/idx, 0 0 1, 1 1 1, 0 0 0
+ 34   set-tile tiles, 0x08/idx, 1 0 1, 1 1 1, 0 0 0
+ 35   set-tile tiles, 0x09/idx, 0 1 1, 1 1 0, 1 0 0
+ 36   set-tile tiles, 0x0a/idx, 0 1 1, 0 0 1, 1 0 0
+ 37   set-tile tiles, 0x0b/idx, 1 1 1, 0 0 1, 1 0 0
+ 38   set-tile tiles, 0x0c/idx, 1 1 1, 1 0 1, 1 0 0
+ 39   set-tile tiles, 0x0d/idx, 0 0 0, 1 1 1, 1 0 0
+ 40   set-tile tiles, 0x0e/idx, 1 0 0, 1 1 1, 1 0 0
+ 41   set-tile tiles, 0x0f/idx, 0 1 0, 1 1 1, 1 0 0
+ 42   set-tile tiles, 0x10/idx, 0 0 1, 1 1 1, 1 0 0
+ 43   set-tile tiles, 0x11/idx, 1 0 1, 1 1 1, 1 0 0
+ 44   set-tile tiles, 0x12/idx, 1 0 1, 0 0 0, 0 1 0
+ 45   set-tile tiles, 0x13/idx, 1 1 1, 0 0 0, 0 1 0
+ 46   set-tile tiles, 0x14/idx, 1 1 1, 0 1 0, 0 1 0
+ 47   set-tile tiles, 0x15/idx, 0 1 1, 1 1 0, 0 1 0
+ 48   set-tile tiles, 0x16/idx, 1 1 0, 0 1 1, 0 1 0
+ 49   set-tile tiles, 0x17/idx, 0 0 0, 1 1 1, 0 1 0
+ 50   set-tile tiles, 0x18/idx, 1 0 0, 1 1 1, 0 1 0
+ 51   set-tile tiles, 0x19/idx, 0 1 0, 1 1 1, 0 1 0
+ 52   set-tile tiles, 0x1a/idx, 0 0 1, 1 1 1, 0 1 0
+ 53   set-tile tiles, 0x1b/idx, 1 0 1, 1 1 1, 0 1 0
+ 54   set-tile tiles, 0x1c/idx, 1 0 1, 0 0 0, 1 1 0
+ 55   set-tile tiles, 0x1d/idx, 0 1 1, 0 0 0, 1 1 0
+ 56   set-tile tiles, 0x1e/idx, 1 1 1, 0 0 0, 1 1 0
+ 57   set-tile tiles, 0x1f/idx, 0 0 1, 1 0 0, 1 1 0
+ 58   set-tile tiles, 0x20/idx, 1 0 1, 1 0 0, 1 1 0
+ 59   set-tile tiles, 0x21/idx, 1 1 1, 1 0 0, 1 1 0
+ 60   set-tile tiles, 0x22/idx, 0 1 1, 0 1 0, 1 1 0
+ 61   set-tile tiles, 0x23/idx, 1 1 1, 0 1 0, 1 1 0
+ 62   set-tile tiles, 0x24/idx, 0 0 0, 0 1 1, 1 1 0
+ 63   set-tile tiles, 0x25/idx, 0 1 0, 0 1 1, 1 1 0
+ 64   set-tile tiles, 0x26/idx, 1 1 0, 0 1 1, 1 1 0
+ 65   set-tile tiles, 0x27/idx, 0 0 1, 0 1 1, 1 1 0
+ 66   set-tile tiles, 0x28/idx, 1 1 0, 1 0 0, 0 0 1
+ 67   set-tile tiles, 0x29/idx, 1 1 1, 1 0 0, 0 0 1
+ 68   set-tile tiles, 0x2a/idx, 1 1 1, 1 0 1, 0 0 1
+ 69   set-tile tiles, 0x2b/idx, 1 1 0, 0 1 1, 0 0 1
+ 70   set-tile tiles, 0x2c/idx, 0 0 0, 1 1 1, 0 0 1
+ 71   set-tile tiles, 0x2d/idx, 1 0 0, 1 1 1, 0 0 1
+ 72   set-tile tiles, 0x2e/idx, 0 1 0, 1 1 1, 0 0 1
+ 73   set-tile tiles, 0x2f/idx, 0 0 1, 1 1 1, 0 0 1
+ 74   set-tile tiles, 0x30/idx, 1 0 1, 1 1 1, 0 0 1
+ 75   set-tile tiles, 0x31/idx, 0 1 0, 0 0 0, 1 0 1
+ 76   set-tile tiles, 0x32/idx, 1 1 0, 0 0 0, 1 0 1
+ 77   set-tile tiles, 0x33/idx, 0 1 1, 0 0 0, 1 0 1
+ 78   set-tile tiles, 0x34/idx, 1 1 1, 0 0 0, 1 0 1
+ 79   set-tile tiles, 0x35/idx, 1 1 0, 1 0 0, 1 0 1
+ 80   set-tile tiles, 0x36/idx, 1 1 1, 1 0 0, 1 0 1
+ 81   set-tile tiles, 0x37/idx, 0 1 1, 0 0 1, 1 0 1
+ 82   set-tile tiles, 0x38/idx, 1 1 1, 0 0 1, 1 0 1
+ 83   set-tile tiles, 0x39/idx, 1 1 1, 1 0 1, 1 0 1
+ 84   set-tile tiles, 0x3a/idx, 0 0 0, 1 1 1, 1 0 1
+ 85   set-tile tiles, 0x3b/idx, 1 0 0, 1 1 1, 1 0 1
+ 86   set-tile tiles, 0x3c/idx, 0 1 0, 1 1 1, 1 0 1
+ 87   set-tile tiles, 0x3d/idx, 0 0 1, 1 1 1, 1 0 1
+ 88   set-tile tiles, 0x3e/idx, 1 0 1, 1 1 1, 1 0 1
+ 89   set-tile tiles, 0x3f/idx, 1 1 0, 0 0 0, 0 1 1
+ 90   set-tile tiles, 0x40/idx, 1 0 1, 0 0 0, 0 1 1
+ 91   set-tile tiles, 0x41/idx, 1 1 1, 0 0 0, 0 1 1
+ 92   set-tile tiles, 0x42/idx, 1 1 0, 0 1 0, 0 1 1
+ 93   set-tile tiles, 0x43/idx, 1 1 1, 0 1 0, 0 1 1
+ 94   set-tile tiles, 0x44/idx, 0 0 0, 1 1 0, 0 1 1
+ 95   set-tile tiles, 0x45/idx, 1 0 0, 1 1 0, 0 1 1
+ 96   set-tile tiles, 0x46/idx, 0 1 0, 1 1 0, 0 1 1
+ 97   set-tile tiles, 0x47/idx, 0 1 1, 1 1 0, 0 1 1
+ 98   set-tile tiles, 0x48/idx, 1 0 0, 0 0 1, 0 1 1
+ 99   set-tile tiles, 0x49/idx, 1 0 1, 0 0 1, 0 1 1
+100   set-tile tiles, 0x4a/idx, 1 1 1, 0 0 1, 0 1 1
+101   set-tile tiles, 0x4b/idx, 0 1 0, 0 0 0, 1 1 1
+102   set-tile tiles, 0x4c/idx, 1 1 0, 0 0 0, 1 1 1
+103   set-tile tiles, 0x4d/idx, 1 0 1, 0 0 0, 1 1 1
+104   set-tile tiles, 0x4e/idx, 0 1 1, 0 0 0, 1 1 1
+105   set-tile tiles, 0x4f/idx, 1 1 1, 0 0 0, 1 1 1
+106   set-tile tiles, 0x50/idx, 1 1 0, 1 0 0, 1 1 1
+107   set-tile tiles, 0x51/idx, 0 0 1, 1 0 0, 1 1 1
+108   set-tile tiles, 0x52/idx, 1 0 1, 1 0 0, 1 1 1
+109   set-tile tiles, 0x53/idx, 1 1 1, 1 0 0, 1 1 1
+110   set-tile tiles, 0x54/idx, 0 0 0, 0 1 0, 1 1 1
+111   set-tile tiles, 0x55/idx, 0 1 0, 0 1 0, 1 1 1
+112   set-tile tiles, 0x56/idx, 1 1 0, 0 1 0, 1 1 1
+113   set-tile tiles, 0x57/idx, 0 1 1, 0 1 0, 1 1 1
+114   set-tile tiles, 0x58/idx, 1 1 1, 0 1 0, 1 1 1
+115   set-tile tiles, 0x59/idx, 1 0 0, 0 0 1, 1 1 1
+116   set-tile tiles, 0x5a/idx, 1 0 1, 0 0 1, 1 1 1
+117   set-tile tiles, 0x5b/idx, 0 1 1, 0 0 1, 1 1 1
+118   set-tile tiles, 0x5c/idx, 1 1 1, 0 0 1, 1 1 1
+119   set-tile tiles, 0x5d/idx, 0 0 0, 1 0 1, 1 1 1
+120   set-tile tiles, 0x5e/idx, 1 0 0, 1 0 1, 1 1 1
+121   set-tile tiles, 0x5f/idx, 0 0 1, 1 0 1, 1 1 1
+122   set-tile tiles, 0x60/idx, 1 0 1, 1 0 1, 1 1 1
+123   set-tile tiles, 0x61/idx, 1 1 1, 1 0 1, 1 1 1
+124 
+125   render-tiles screen, tiles
+126   {
+127     var key/eax: byte <- read-key keyboard
+128     compare key, 0
+129     loop-if-=
+130   }
+131   var step/eax: int <- copy 0
+132   {
+133     render-random screen, tiles, 4/pixels-per-cell, step
+134     {
+135       var key/eax: byte <- read-key keyboard
+136       compare key, 0
+137       loop-if-=
+138     }
+139     step <- increment
+140     loop
+141   }
+142 }
+143 
+144 fn set-tile _tiles: (addr array tile), _idx: int, n0: int, n1: int, n2: int, n3: int, n4: int, n5: int, n6: int, n7: int, n8: int {
+145   var tiles/eax: (addr array tile) <- copy _tiles
+146   var idx/ecx: int <- copy _idx
+147   var tile/edi: (addr tile) <- index tiles, idx
+148   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
+149   populate rows-ah, 3
+150   var _rows/eax: (addr array handle array int) <- lookup *rows-ah
+151   var rows/edi: (addr array handle array int) <- copy _rows
+152   var row0-ah/eax: (addr handle array int) <- index rows, 0
+153   populate row0-ah, 3
+154   var row0/eax: (addr array int) <- lookup *row0-ah
+155   var x0/ecx: (addr int) <- index row0, 0
+156   var src/esi: int <- copy n0
+157   copy-to *x0, src
+158   var x1/ecx: (addr int) <- index row0, 1
+159   var src/esi: int <- copy n1
+160   copy-to *x1, src
+161   var x2/ecx: (addr int) <- index row0, 2
+162   var src/esi: int <- copy n2
+163   copy-to *x2, src
+164   var row1-ah/eax: (addr handle array int) <- index rows, 1
+165   populate row1-ah, 3
+166   var row1/eax: (addr array int) <- lookup *row1-ah
+167   var x3/ecx: (addr int) <- index row1, 0
+168   var src/esi: int <- copy n3
+169   copy-to *x3, src
+170   var x4/ecx: (addr int) <- index row1, 1
+171   var src/esi: int <- copy n4
+172   copy-to *x4, src
+173   var x5/ecx: (addr int) <- index row1, 2
+174   var src/esi: int <- copy n5
+175   copy-to *x5, src
+176   var row2-ah/eax: (addr handle array int) <- index rows, 2
+177   populate row2-ah, 3
+178   var row2/eax: (addr array int) <- lookup *row2-ah
+179   var x6/ecx: (addr int) <- index row2, 0
+180   var src/esi: int <- copy n6
+181   copy-to *x6, src
+182   var x7/ecx: (addr int) <- index row2, 1
+183   var src/esi: int <- copy n7
+184   copy-to *x7, src
+185   var x8/ecx: (addr int) <- index row2, 2
+186   var src/esi: int <- copy n8
+187   copy-to *x8, src
+188 }
+189 
+190 fn render-tiles screen: (addr screen), _tiles: (addr array tile) {
+191   draw-rect screen, 0 0, 0x400 0x300, 8
+192   var tiles/esi: (addr array tile) <- copy _tiles
+193   var num-tiles: int
+194   var tmp/eax: int <- length tiles
+195   copy-to num-tiles, tmp
+196 #?   draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, num-tiles, 0x31, 0
+197   var i/ecx: int <- copy 0
+198   {
+199     compare i, num-tiles
+200     break-if->=
+201 #?     draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, i, 0x31, 0
+202     var tile/eax: (addr tile) <- index tiles, i
+203     var start-x/edx: int <- copy i
+204     start-x <- and 0xf/tiles-per-row-minus-one
+205     start-x <- shift-left 5  # ceil(log(3 * pixels-per-cell))
+206     start-x <- add 0x20/left-margin
+207 #?     draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, start-x, 0x31 0
+208     var start-y/ebx: int <- copy i
+209     start-y <- shift-right 4/log2-tiles-per-row
+210     start-y <- shift-left 5  # ceil(log(3 * pixels-per-cell))
+211     start-y <- add 0x20/top-margin
+212 #?     draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, start-x, 0x31, 0
+213     render-tile screen, tile, start-x, start-y, 8/pixels-per-cell
+214     i <- increment
+215     loop
+216   }
+217 }
+218 
+219 fn render-tile screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, n: int {
+220   var tile/esi: (addr tile) <- copy _tile
+221   var y/ecx: int <- copy start-y
+222   y <- add 4/margin-top
+223   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
+224   var rows/eax: (addr array handle array int) <- lookup *rows-ah
+225   var i/ebx: int <- copy 0
+226   {
+227     compare i, 3
+228     break-if->=
+229     var x/edx: int <- copy start-x
+230     x <- add 4/margin-left
+231     var curr-row-ah/eax: (addr handle array int) <- index rows, i
+232     var curr-row/eax: (addr array int) <- lookup *curr-row-ah
+233     var j/edi: int <- copy 0
+234     {
+235       compare j, 3
+236       break-if->=
+237       var curr/eax: (addr int) <- index curr-row, j
+238       var color/eax: int <- copy *curr
+239       color <- shift-left 1
+240 #?       draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 9 0
+241 #?       draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 0xc 0
+242       draw-rect2 screen, x y, n n, color
+243       j <- increment
+244       x <- add n
+245       loop
+246     }
+247     i <- increment
+248     y <- add n
+249     loop
+250   }
+251 }
+252 
+253 fn render-random screen: (addr screen), _tiles: (addr array tile), pixels-per-cell: int, seed: int {
+254   draw-rect screen, 0 0, 0x400 0x300, 8
+255   var tiles/esi: (addr array tile) <- copy _tiles
+256   var rand/edi: int <- next-random seed
+257   var num-tiles/ebx: int <- length tiles
+258   var y/ecx: int <- copy 0
+259   {
+260     compare y, 0x300
+261     break-if->=
+262     var x/edx: int <- copy 0
+263     {
+264       compare x, 0x400
+265       break-if->=
+266       var i/eax: int <- remainder rand, num-tiles
+267       var tile/eax: (addr tile) <- index tiles, i
+268       render-tile-without-margin screen, tile, x, y, pixels-per-cell
+269       x <- add pixels-per-cell
+270       x <- add pixels-per-cell
+271       x <- add pixels-per-cell
+272       rand <- next-random rand
+273       loop
+274     }
+275     y <- add pixels-per-cell
+276     y <- add pixels-per-cell
+277     y <- add pixels-per-cell
+278     loop
+279   }
+280 }
+281 
+282 fn render-tile-without-margin screen: (addr screen), _tile: (addr tile), start-x: int, start-y: int, pixels-per-cell: int {
+283   var tile/esi: (addr tile) <- copy _tile
+284   var y/ecx: int <- copy start-y
+285   var rows-ah/eax: (addr handle array handle array int) <- get tile, data
+286   var rows/eax: (addr array handle array int) <- lookup *rows-ah
+287   var i/ebx: int <- copy 0
+288   {
+289     compare i, 3
+290     break-if->=
+291     var x/edx: int <- copy start-x
+292     var curr-row-ah/eax: (addr handle array int) <- index rows, i
+293     var curr-row/eax: (addr array int) <- lookup *curr-row-ah
+294     var j/edi: int <- copy 0
+295     {
+296       compare j, 3
+297       break-if->=
+298       var curr/eax: (addr int) <- index curr-row, j
+299       var color/eax: int <- copy *curr
+300       color <- shift-left 1
+301       draw-rect2 screen, x y, pixels-per-cell pixels-per-cell, color
+302       j <- increment
+303       x <- add pixels-per-cell
+304       loop
+305     }
+306     i <- increment
+307     y <- add pixels-per-cell
+308     loop
+309   }
+310 }
+311 
+312 fn remainder a: int, b: int -> _/eax: int {
+313   var q/eax: int <- copy 0
+314   var r/edx: int <- copy 0
+315   q, r <- integer-divide a, b
+316   return r
+317 }