From d89a9ec5d38294d41399218cef1eab9e9682dafd Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 16 Jul 2021 09:14:28 -0700 Subject: . --- html/apps/ex13.mu.html | 87 ++++ html/apps/ex9.mu.html | 4 +- html/apps/img.mu.html | 1217 ------------------------------------------------ 3 files changed, 89 insertions(+), 1219 deletions(-) create mode 100644 html/apps/ex13.mu.html delete mode 100644 html/apps/img.mu.html (limited to 'html/apps') diff --git a/html/apps/ex13.mu.html b/html/apps/ex13.mu.html new file mode 100644 index 00000000..a5fc7c5e --- /dev/null +++ b/html/apps/ex13.mu.html @@ -0,0 +1,87 @@ + + + + +Mu - apps/ex13.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/apps/ex13.mu +
+ 1 # Load an image from disk and display it on screen.
+ 2 #
+ 3 # Build the code disk:
+ 4 #   $ ./translate apps/ex13.mu                       # generates code.img
+ 5 # Load a pbm, pgm or ppm image (no more than 255 levels) in the data disk
+ 6 #   $ dd if=/dev/zero of=data.img count=20160
+ 7 #   $ dd if=___ of=data.img conv=notrunc
+ 8 # Run:
+ 9 #   $ qemu-system-i386 -hda code.img -hdb data.img
+10 
+11 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+12   var img-storage: image
+13   var img/esi: (addr image) <- address img-storage
+14   load-image img, data-disk
+15   render-image screen, img, 0/x, 0/y, 0x300/width, 0x300/height
+16 }
+17 
+18 fn load-image self: (addr image), data-disk: (addr disk) {
+19   var s-storage: (stream byte 0x200000)  # 512* 0x1000 sectors
+20   var s/ebx: (addr stream byte) <- address s-storage
+21   load-sectors data-disk, 0/lba, 0x1000/sectors, s
+22   initialize-image self, s
+23 }
+
+ + + diff --git a/html/apps/ex9.mu.html b/html/apps/ex9.mu.html index 54a158b2..6fa4649b 100644 --- a/html/apps/ex9.mu.html +++ b/html/apps/ex9.mu.html @@ -78,14 +78,14 @@ if ('onhashchange' in window) { 18 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 19 var text-storage: (stream byte 0x200) 20 var text/esi: (addr stream byte) <- address text-storage -21 load-sectors data-disk, 0/lba, 1/num-sectors, text +21 load-sectors data-disk, 0/lba, 1/num-sectors, text 22 23 var word-count/eax: int <- word-count text 24 25 var result-storage: (stream byte 0x10) 26 var result/edi: (addr stream byte) <- address result-storage 27 write-int32-decimal result, word-count -28 store-sectors data-disk, 0/lba, 1/num-sectors, result +28 store-sectors data-disk, 0/lba, 1/num-sectors, result 29 } 30 31 fn word-count in: (addr stream byte) -> _/eax: int { diff --git a/html/apps/img.mu.html b/html/apps/img.mu.html deleted file mode 100644 index e3117aa2..00000000 --- a/html/apps/img.mu.html +++ /dev/null @@ -1,1217 +0,0 @@ - - - - -Mu - apps/img.mu - - - - - - - - - - -https://github.com/akkartik/mu/blob/main/apps/img.mu -
-   1 # load an image from disk and display it on screen
-   2 #
-   3 # To build:
-   4 #   $ ./translate apps/img.mu                       # generates code.img
-   5 # Load a pbm, pgm or ppm image (no more than 255 levels) in the data disk
-   6 #   $ dd if=/dev/zero of=data.img count=20160
-   7 #   $ dd if=x.pbm of=data.img conv=notrunc
-   8 # or
-   9 #   $ dd if=t.pgm of=data.img conv=notrunc
-  10 # or
-  11 #   $ dd if=snail.ppm of=data.img conv=notrunc
-  12 # To run:
-  13 #   $ qemu-system-i386 -hda code.img -hdb data.img
-  14 
-  15 type image {
-  16   type: int  # supported types:
-  17              #  1: portable bitmap (P1) - pixels 0 or 1
-  18              #  2: portable greymap (P2) - pixels 1-byte greyscale values
-  19              #  3: portable pixmap (P3) - pixels 3-byte rgb values
-  20   max: int
-  21   width: int
-  22   height: int
-  23   data: (handle array byte)
-  24 }
-  25 
-  26 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
-  27   var img-storage: image
-  28   var img/esi: (addr image) <- address img-storage
-  29   load-image img, data-disk
-  30   render-image screen, img, 0/x, 0/y, 0x300/width, 0x300/height
-  31 }
-  32 
-  33 fn load-image self: (addr image), data-disk: (addr disk) {
-  34   # data-disk -> stream
-  35   var s-storage: (stream byte 0x200000)  # 512* 0x1000 sectors
-  36   var s/ebx: (addr stream byte) <- address s-storage
-  37   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sectors from data disk", 3/fg, 0/bg
-  38   move-cursor-to-left-margin-of-next-line 0/screen
-  39   load-sectors data-disk, 0/lba, 0x100/sectors, s
-  40   load-sectors data-disk, 0x100/lba, 0x100/sectors, s
-  41   load-sectors data-disk, 0x200/lba, 0x100/sectors, s
-  42   load-sectors data-disk, 0x300/lba, 0x100/sectors, s
-  43   load-sectors data-disk, 0x400/lba, 0x100/sectors, s
-  44   load-sectors data-disk, 0x500/lba, 0x100/sectors, s
-  45   load-sectors data-disk, 0x600/lba, 0x100/sectors, s
-  46   load-sectors data-disk, 0x700/lba, 0x100/sectors, s
-  47   load-sectors data-disk, 0x800/lba, 0x100/sectors, s
-  48   load-sectors data-disk, 0x900/lba, 0x100/sectors, s
-  49   load-sectors data-disk, 0xa00/lba, 0x100/sectors, s
-  50   load-sectors data-disk, 0xb00/lba, 0x100/sectors, s
-  51   load-sectors data-disk, 0xc00/lba, 0x100/sectors, s
-  52   load-sectors data-disk, 0xd00/lba, 0x100/sectors, s
-  53   load-sectors data-disk, 0xe00/lba, 0x100/sectors, s
-  54   load-sectors data-disk, 0xf00/lba, 0x100/sectors, s
-  55   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsing", 3/fg, 0/bg
-  56   move-cursor-to-left-margin-of-next-line 0/screen
-  57   initialize-image self, s
-  58 }
-  59 
-  60 fn initialize-image _self: (addr image), in: (addr stream byte) {
-  61   var self/esi: (addr image) <- copy _self
-  62   var mode-storage: slice
-  63   var mode/ecx: (addr slice) <- address mode-storage
-  64   next-word in, mode
-  65   {
-  66     var P1?/eax: boolean <- slice-equal? mode, "P1"
-  67     compare P1?, 0/false
-  68     break-if-=
-  69     var type-a/eax: (addr int) <- get self, type
-  70     copy-to *type-a, 1/ppm
-  71     initialize-image-from-pbm self, in
-  72     return
-  73   }
-  74   {
-  75     var P2?/eax: boolean <- slice-equal? mode, "P2"
-  76     compare P2?, 0/false
-  77     break-if-=
-  78     var type-a/eax: (addr int) <- get self, type
-  79     copy-to *type-a, 2/pgm
-  80     initialize-image-from-pgm self, in
-  81     return
-  82   }
-  83   {
-  84     var P3?/eax: boolean <- slice-equal? mode, "P3"
-  85     compare P3?, 0/false
-  86     break-if-=
-  87     var type-a/eax: (addr int) <- get self, type
-  88     copy-to *type-a, 3/ppm
-  89     initialize-image-from-ppm self, in
-  90     return
-  91   }
-  92   abort "initialize-image: unrecognized image type"
-  93 }
-  94 
-  95 # dispatch to a few variants with mostly identical boilerplate
-  96 fn render-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
-  97   var img/esi: (addr image) <- copy _img
-  98   var type-a/eax: (addr int) <- get img, type
-  99   {
- 100     compare *type-a, 1/pbm
- 101     break-if-!=
- 102     render-pbm-image screen, img, xmin, ymin, width, height
- 103     return
- 104   }
- 105   {
- 106     compare *type-a, 2/pgm
- 107     break-if-!=
- 108     var img2-storage: image
- 109     var img2/edi: (addr image) <- address img2-storage
- 110     dither-pgm-unordered img, img2
- 111     render-raw-image screen, img2, xmin, ymin, width, height
- 112     return
- 113   }
- 114   {
- 115     compare *type-a, 3/ppm
- 116     break-if-!=
- 117     var img2-storage: image
- 118     var img2/edi: (addr image) <- address img2-storage
- 119     dither-ppm-unordered img, img2
- 120     render-raw-image screen, img2, xmin, ymin, width, height
- 121     return
- 122   }
- 123   abort "render-image: unrecognized image type"
- 124 }
- 125 
- 126 ## helpers
- 127 
- 128 # import a black-and-white ascii bitmap (each pixel is 0 or 1)
- 129 fn initialize-image-from-pbm _self: (addr image), in: (addr stream byte) {
- 130   var self/esi: (addr image) <- copy _self
- 131   var curr-word-storage: slice
- 132   var curr-word/ecx: (addr slice) <- address curr-word-storage
- 133   # load width, height
- 134   next-word in, curr-word
- 135   var tmp/eax: int <- parse-decimal-int-from-slice curr-word
- 136   var width/edx: int <- copy tmp
- 137   next-word in, curr-word
- 138   tmp <- parse-decimal-int-from-slice curr-word
- 139   var height/ebx: int <- copy tmp
- 140   # save width, height
- 141   var dest/eax: (addr int) <- get self, width
- 142   copy-to *dest, width
- 143   dest <- get self, height
- 144   copy-to *dest, height
- 145   # initialize data
- 146   var capacity/edx: int <- copy width
- 147   capacity <- multiply height
- 148   var data-ah/edi: (addr handle array byte) <- get self, data
- 149   populate data-ah, capacity
- 150   var _data/eax: (addr array byte) <- lookup *data-ah
- 151   var data/edi: (addr array byte) <- copy _data
- 152   var i/ebx: int <- copy 0
- 153   {
- 154     compare i, capacity
- 155     break-if->=
- 156     next-word in, curr-word
- 157     var src/eax: int <- parse-decimal-int-from-slice curr-word
- 158     {
- 159       var dest/ecx: (addr byte) <- index data, i
- 160       copy-byte-to *dest, src
- 161     }
- 162     i <- increment
- 163     loop
- 164   }
- 165 }
- 166 
- 167 # render a black-and-white ascii bitmap (each pixel is 0 or 1)
- 168 fn render-pbm-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
- 169   var img/esi: (addr image) <- copy _img
- 170   # yratio = height/img->height
- 171   var img-height-a/eax: (addr int) <- get img, height
- 172   var img-height/xmm0: float <- convert *img-height-a
- 173   var yratio/xmm1: float <- convert height
- 174   yratio <- divide img-height
- 175   # xratio = width/img->width
- 176   var img-width-a/eax: (addr int) <- get img, width
- 177   var img-width/ebx: int <- copy *img-width-a
- 178   var img-width-f/xmm0: float <- convert img-width
- 179   var xratio/xmm2: float <- convert width
- 180   xratio <- divide img-width-f
- 181   # esi = img->data
- 182   var img-data-ah/eax: (addr handle array byte) <- get img, data
- 183   var _img-data/eax: (addr array byte) <- lookup *img-data-ah
- 184   var img-data/esi: (addr array byte) <- copy _img-data
- 185   var len/edi: int <- length img-data
- 186   #
- 187   var one/eax: int <- copy 1
- 188   var one-f/xmm3: float <- convert one
- 189   var width-f/xmm4: float <- convert width
- 190   var height-f/xmm5: float <- convert height
- 191   var zero/eax: int <- copy 0
- 192   var zero-f/xmm0: float <- convert zero
- 193   var y/xmm6: float <- copy zero-f
- 194   {
- 195     compare y, height-f
- 196     break-if-float>=
- 197     var imgy-f/xmm5: float <- copy y
- 198     imgy-f <- divide yratio
- 199     var imgy/edx: int <- truncate imgy-f
- 200     var x/xmm7: float <- copy zero-f
- 201     {
- 202       compare x, width-f
- 203       break-if-float>=
- 204       var imgx-f/xmm5: float <- copy x
- 205       imgx-f <- divide xratio
- 206       var imgx/ecx: int <- truncate imgx-f
- 207       var idx/eax: int <- copy imgy
- 208       idx <- multiply img-width
- 209       idx <- add imgx
- 210       # error info in case we rounded wrong and 'index' will fail bounds-check
- 211       compare idx, len
- 212       {
- 213         break-if-<
- 214         set-cursor-position 0/screen, 0x20/x 0x20/y
- 215         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgx, 3/fg 0/bg
- 216         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgy, 4/fg 0/bg
- 217         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 5/fg 0/bg
- 218       }
- 219       var src-a/eax: (addr byte) <- index img-data, idx
- 220       var src/eax: byte <- copy-byte *src-a
- 221       var color-int/eax: int <- copy src
- 222       {
- 223         compare color-int, 0/black
- 224         break-if-=
- 225         color-int <- copy 0xf/white
- 226       }
- 227       var screenx/ecx: int <- convert x
- 228       screenx <- add xmin
- 229       var screeny/edx: int <- convert y
- 230       screeny <- add ymin
- 231       pixel screen, screenx, screeny, color-int
- 232       x <- add one-f
- 233       loop
- 234     }
- 235     y <- add one-f
- 236     loop
- 237   }
- 238 }
- 239 
- 240 # import a greyscale ascii "greymap" (each pixel is a shade of grey from 0 to 255)
- 241 fn initialize-image-from-pgm _self: (addr image), in: (addr stream byte) {
- 242   var self/esi: (addr image) <- copy _self
- 243   var curr-word-storage: slice
- 244   var curr-word/ecx: (addr slice) <- address curr-word-storage
- 245   # load width, height
- 246   next-word in, curr-word
- 247   var tmp/eax: int <- parse-decimal-int-from-slice curr-word
- 248   var width/edx: int <- copy tmp
- 249   next-word in, curr-word
- 250   tmp <- parse-decimal-int-from-slice curr-word
- 251   var height/ebx: int <- copy tmp
- 252   # check and save color levels
- 253   next-word in, curr-word
- 254   {
- 255     tmp <- parse-decimal-int-from-slice curr-word
- 256     compare tmp, 0xff
- 257     break-if-=
- 258     draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "levels of grey is not 255; continuing and hoping for the best", 0x2b/fg 0/bg
- 259   }
- 260   var dest/edi: (addr int) <- get self, max
- 261   copy-to *dest, tmp
- 262   # save width, height
- 263   dest <- get self, width
- 264   copy-to *dest, width
- 265   dest <- get self, height
- 266   copy-to *dest, height
- 267   # initialize data
- 268   var capacity/edx: int <- copy width
- 269   capacity <- multiply height
- 270   var data-ah/edi: (addr handle array byte) <- get self, data
- 271   populate data-ah, capacity
- 272   var _data/eax: (addr array byte) <- lookup *data-ah
- 273   var data/edi: (addr array byte) <- copy _data
- 274   var i/ebx: int <- copy 0
- 275   {
- 276     compare i, capacity
- 277     break-if->=
- 278     next-word in, curr-word
- 279     var src/eax: int <- parse-decimal-int-from-slice curr-word
- 280     {
- 281       var dest/ecx: (addr byte) <- index data, i
- 282       copy-byte-to *dest, src
- 283     }
- 284     i <- increment
- 285     loop
- 286   }
- 287 }
- 288 
- 289 # render a greyscale ascii "greymap" (each pixel is a shade of grey from 0 to 255) by quantizing the shades
- 290 fn render-pgm-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
- 291   var img/esi: (addr image) <- copy _img
- 292   # yratio = height/img->height
- 293   var img-height-a/eax: (addr int) <- get img, height
- 294   var img-height/xmm0: float <- convert *img-height-a
- 295   var yratio/xmm1: float <- convert height
- 296   yratio <- divide img-height
- 297   # xratio = width/img->width
- 298   var img-width-a/eax: (addr int) <- get img, width
- 299   var img-width/ebx: int <- copy *img-width-a
- 300   var img-width-f/xmm0: float <- convert img-width
- 301   var xratio/xmm2: float <- convert width
- 302   xratio <- divide img-width-f
- 303   # esi = img->data
- 304   var img-data-ah/eax: (addr handle array byte) <- get img, data
- 305   var _img-data/eax: (addr array byte) <- lookup *img-data-ah
- 306   var img-data/esi: (addr array byte) <- copy _img-data
- 307   var len/edi: int <- length img-data
- 308   #
- 309   var one/eax: int <- copy 1
- 310   var one-f/xmm3: float <- convert one
- 311   var width-f/xmm4: float <- convert width
- 312   var height-f/xmm5: float <- convert height
- 313   var zero/eax: int <- copy 0
- 314   var zero-f/xmm0: float <- convert zero
- 315   var y/xmm6: float <- copy zero-f
- 316   {
- 317     compare y, height-f
- 318     break-if-float>=
- 319     var imgy-f/xmm5: float <- copy y
- 320     imgy-f <- divide yratio
- 321     var imgy/edx: int <- truncate imgy-f
- 322     var x/xmm7: float <- copy zero-f
- 323     {
- 324       compare x, width-f
- 325       break-if-float>=
- 326       var imgx-f/xmm5: float <- copy x
- 327       imgx-f <- divide xratio
- 328       var imgx/ecx: int <- truncate imgx-f
- 329       var idx/eax: int <- copy imgy
- 330       idx <- multiply img-width
- 331       idx <- add imgx
- 332       # error info in case we rounded wrong and 'index' will fail bounds-check
- 333       compare idx, len
- 334       {
- 335         break-if-<
- 336         set-cursor-position 0/screen, 0x20/x 0x20/y
- 337         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgx, 3/fg 0/bg
- 338         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgy, 4/fg 0/bg
- 339         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 5/fg 0/bg
- 340       }
- 341       var src-a/eax: (addr byte) <- index img-data, idx
- 342       var src/eax: byte <- copy-byte *src-a
- 343       var color-int/eax: int <- nearest-grey src
- 344       var screenx/ecx: int <- convert x
- 345       screenx <- add xmin
- 346       var screeny/edx: int <- convert y
- 347       screeny <- add ymin
- 348       pixel screen, screenx, screeny, color-int
- 349       x <- add one-f
- 350       loop
- 351     }
- 352     y <- add one-f
- 353     loop
- 354   }
- 355 }
- 356 
- 357 fn nearest-grey level-255: byte -> _/eax: int {
- 358   var result/eax: int <- copy level-255
- 359   result <- shift-right 4
- 360   result <- add 0x10
- 361   return result
- 362 }
- 363 
- 364 fn dither-pgm-unordered-monochrome _src: (addr image), _dest: (addr image) {
- 365   var src/esi: (addr image) <- copy _src
- 366   var dest/edi: (addr image) <- copy _dest
- 367   # copy 'width'
- 368   var src-width-a/eax: (addr int) <- get src, width
- 369   var tmp/eax: int <- copy *src-width-a
- 370   var src-width: int
- 371   copy-to src-width, tmp
- 372   {
- 373     var dest-width-a/edx: (addr int) <- get dest, width
- 374     copy-to *dest-width-a, tmp
- 375   }
- 376   # copy 'height'
- 377   var src-height-a/eax: (addr int) <- get src, height
- 378   var tmp/eax: int <- copy *src-height-a
- 379   var src-height: int
- 380   copy-to src-height, tmp
- 381   {
- 382     var dest-height-a/ecx: (addr int) <- get dest, height
- 383     copy-to *dest-height-a, tmp
- 384   }
- 385   # transform 'data'
- 386   var capacity/ebx: int <- copy src-width
- 387   capacity <- multiply src-height
- 388   var dest/edi: (addr image) <- copy _dest
- 389   var dest-data-ah/eax: (addr handle array byte) <- get dest, data
- 390   populate dest-data-ah, capacity
- 391   var _dest-data/eax: (addr array byte) <- lookup *dest-data-ah
- 392   var dest-data/edi: (addr array byte) <- copy _dest-data
- 393   # needs a buffer to temporarily hold more than 256 levels of precision
- 394   var errors-storage: (array int 0xc0000)
- 395   var errors/ebx: (addr array int) <- address errors-storage
- 396   var src-data-ah/eax: (addr handle array byte) <- get src, data
- 397   var _src-data/eax: (addr array byte) <- lookup *src-data-ah
- 398   var src-data/esi: (addr array byte) <- copy _src-data
- 399   var y/edx: int <- copy 0
- 400   {
- 401     compare y, src-height
- 402     break-if->=
- 403     var x/ecx: int <- copy 0
- 404     {
- 405       compare x, src-width
- 406       break-if->=
- 407       var curr/eax: byte <- _read-pgm-buffer src-data, x, y, src-width
- 408       var curr-int/eax: int <- copy curr
- 409       curr-int <- shift-left 0x10  # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow
- 410       var error/esi: int <- _read-dithering-error errors, x, y, src-width
- 411       error <- add curr-int
- 412       $_dither-pgm-unordered-monochrome:update-error: {
- 413         compare error, 0x800000
- 414         {
- 415           break-if->=
- 416           _write-raw-buffer dest-data, x, y, src-width, 0/black
- 417           break $_dither-pgm-unordered-monochrome:update-error
- 418         }
- 419         _write-raw-buffer dest-data, x, y, src-width, 1/white
- 420         error <- subtract 0xff0000
- 421       }
- 422       _diffuse-dithering-error-floyd-steinberg errors, x, y, src-width, src-height, error
- 423       x <- increment
- 424       loop
- 425     }
- 426     move-cursor-to-left-margin-of-next-line 0/screen
- 427     y <- increment
- 428     loop
- 429   }
- 430 }
- 431 
- 432 fn dither-pgm-unordered _src: (addr image), _dest: (addr image) {
- 433   var src/esi: (addr image) <- copy _src
- 434   var dest/edi: (addr image) <- copy _dest
- 435   # copy 'width'
- 436   var src-width-a/eax: (addr int) <- get src, width
- 437   var tmp/eax: int <- copy *src-width-a
- 438   var src-width: int
- 439   copy-to src-width, tmp
- 440   {
- 441     var dest-width-a/edx: (addr int) <- get dest, width
- 442     copy-to *dest-width-a, tmp
- 443   }
- 444   # copy 'height'
- 445   var src-height-a/eax: (addr int) <- get src, height
- 446   var tmp/eax: int <- copy *src-height-a
- 447   var src-height: int
- 448   copy-to src-height, tmp
- 449   {
- 450     var dest-height-a/ecx: (addr int) <- get dest, height
- 451     copy-to *dest-height-a, tmp
- 452   }
- 453   # compute scaling factor 255/max
- 454   var target-scale/eax: int <- copy 0xff
- 455   var scale-f/xmm7: float <- convert target-scale
- 456   var src-max-a/eax: (addr int) <- get src, max
- 457   var tmp-f/xmm0: float <- convert *src-max-a
- 458   scale-f <- divide tmp-f
- 459   # transform 'data'
- 460   var capacity/ebx: int <- copy src-width
- 461   capacity <- multiply src-height
- 462   var dest/edi: (addr image) <- copy _dest
- 463   var dest-data-ah/eax: (addr handle array byte) <- get dest, data
- 464   populate dest-data-ah, capacity
- 465   var _dest-data/eax: (addr array byte) <- lookup *dest-data-ah
- 466   var dest-data/edi: (addr array byte) <- copy _dest-data
- 467   # needs a buffer to temporarily hold more than 256 levels of precision
- 468   var errors-storage: (array int 0xc0000)
- 469   var errors/ebx: (addr array int) <- address errors-storage
- 470   var src-data-ah/eax: (addr handle array byte) <- get src, data
- 471   var _src-data/eax: (addr array byte) <- lookup *src-data-ah
- 472   var src-data/esi: (addr array byte) <- copy _src-data
- 473   var y/edx: int <- copy 0
- 474   {
- 475     compare y, src-height
- 476     break-if->=
- 477     var x/ecx: int <- copy 0
- 478     {
- 479       compare x, src-width
- 480       break-if->=
- 481       var initial-color/eax: byte <- _read-pgm-buffer src-data, x, y, src-width
- 482       # . scale to 255 levels
- 483       var initial-color-int/eax: int <- copy initial-color
- 484       var initial-color-f/xmm0: float <- convert initial-color-int
- 485       initial-color-f <- multiply scale-f
- 486       initial-color-int <- convert initial-color-f
- 487       var error/esi: int <- _read-dithering-error errors, x, y, src-width
- 488       # error += (initial-color << 16)
- 489       {
- 490         var tmp/eax: int <- copy initial-color-int
- 491         tmp <- shift-left 0x10  # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow
- 492         error <- add tmp
- 493       }
- 494       # nearest-color = nearest(error >> 16)
- 495       var nearest-color/eax: int <- copy error
- 496       nearest-color <- shift-right-signed 0x10
- 497       {
- 498         compare nearest-color, 0
- 499         break-if->=
- 500         nearest-color <- copy 0
- 501       }
- 502       {
- 503         compare nearest-color, 0xf0
- 504         break-if-<=
- 505         nearest-color <- copy 0xf0
- 506       }
- 507       # . truncate last 4 bits
- 508       nearest-color <- and 0xf0
- 509       # error -= (nearest-color << 16)
- 510       {
- 511         var tmp/eax: int <- copy nearest-color
- 512         tmp <- shift-left 0x10
- 513         error <- subtract tmp
- 514       }
- 515       # color-index = (nearest-color >> 4 + 16)
- 516       var color-index/eax: int <- copy nearest-color
- 517       color-index <- shift-right 4
- 518       color-index <- add 0x10
- 519       var color-index-byte/eax: byte <- copy-byte color-index
- 520       _write-raw-buffer dest-data, x, y, src-width, color-index-byte
- 521       _diffuse-dithering-error-floyd-steinberg errors, x, y, src-width, src-height, error
- 522       x <- increment
- 523       loop
- 524     }
- 525     y <- increment
- 526     loop
- 527   }
- 528 }
- 529 
- 530 # Use Floyd-Steinberg algorithm for diffusing error at x, y in a 2D grid of
- 531 # dimensions (width, height)
- 532 #
- 533 # https://tannerhelland.com/2012/12/28/dithering-eleven-algorithms-source-code.html
- 534 #
- 535 # Error is currently a fixed-point number with 16-bit fraction. But
- 536 # interestingly this function doesn't care about that.
- 537 fn _diffuse-dithering-error-floyd-steinberg errors: (addr array int), x: int, y: int, width: int, height: int, error: int {
- 538   {
- 539     compare error, 0
- 540     break-if-!=
- 541     return
- 542   }
- 543   var width-1/esi: int <- copy width
- 544   width-1 <- decrement
- 545   var height-1/edi: int <- copy height
- 546   height-1 <- decrement
- 547   # delta = error/16
- 548 #?   show-errors errors, width, height, x, y
- 549   var delta/ecx: int <- copy error
- 550   delta <- shift-right-signed 4
- 551   # In Floyd-Steinberg, each pixel X transmits its errors to surrounding
- 552   # pixels in the following proportion:
- 553   #           X     7/16
- 554   #     3/16  5/16  1/16
- 555   var x/edx: int <- copy x
- 556   {
- 557     compare x, width-1
- 558     break-if->=
- 559     var tmp/eax: int <- copy 7
- 560     tmp <- multiply delta
- 561     var xright/edx: int <- copy x
- 562     xright <- increment
- 563     _accumulate-dithering-error errors, xright, y, width, tmp
- 564   }
- 565   var y/ebx: int <- copy y
- 566   {
- 567     compare y, height-1
- 568     break-if-<
- 569     return
- 570   }
- 571   var ybelow: int
- 572   copy-to ybelow, y
- 573   increment ybelow
- 574   {
- 575     compare x, 0
- 576     break-if-<=
- 577     var tmp/eax: int <- copy 3
- 578     tmp <- multiply delta
- 579     var xleft/edx: int <- copy x
- 580     xleft <- decrement
- 581     _accumulate-dithering-error errors, xleft, ybelow, width, tmp
- 582   }
- 583   {
- 584     var tmp/eax: int <- copy 5
- 585     tmp <- multiply delta
- 586     _accumulate-dithering-error errors, x, ybelow, width, tmp
- 587   }
- 588   {
- 589     compare x, width-1
- 590     break-if->=
- 591     var xright/edx: int <- copy x
- 592     xright <- increment
- 593     _accumulate-dithering-error errors, xright, ybelow, width, delta
- 594   }
- 595 #?   show-errors errors, width, height, x, y
- 596 }
- 597 
- 598 fn _accumulate-dithering-error errors: (addr array int), x: int, y: int, width: int, error: int {
- 599   var curr/esi: int <- _read-dithering-error errors, x, y, width
- 600   curr <- add error
- 601   _write-dithering-error errors, x, y, width, curr
- 602 }
- 603 
- 604 fn _read-dithering-error _errors: (addr array int), x: int, y: int, width: int -> _/esi: int {
- 605   var errors/esi: (addr array int) <- copy _errors
- 606   var idx/ecx: int <- copy y
- 607   idx <- multiply width
- 608   idx <- add x
- 609   var result-a/eax: (addr int) <- index errors, idx
- 610   return *result-a
- 611 }
- 612 
- 613 fn _write-dithering-error _errors: (addr array int), x: int, y: int, width: int, val: int {
- 614   var errors/esi: (addr array int) <- copy _errors
- 615   var idx/ecx: int <- copy y
- 616   idx <- multiply width
- 617   idx <- add x
- 618 #?   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 7/fg 0/bg
- 619 #?   move-cursor-to-left-margin-of-next-line 0/screen
- 620   var src/eax: int <- copy val
- 621   var dest-a/edi: (addr int) <- index errors, idx
- 622   copy-to *dest-a, src
- 623 }
- 624 
- 625 fn _read-pgm-buffer _buf: (addr array byte), x: int, y: int, width: int -> _/eax: byte {
- 626   var buf/esi: (addr array byte) <- copy _buf
- 627   var idx/ecx: int <- copy y
- 628   idx <- multiply width
- 629   idx <- add x
- 630   var result-a/eax: (addr byte) <- index buf, idx
- 631   var result/eax: byte <- copy-byte *result-a
- 632   return result
- 633 }
- 634 
- 635 fn _write-raw-buffer _buf: (addr array byte), x: int, y: int, width: int, val: byte {
- 636   var buf/esi: (addr array byte) <- copy _buf
- 637   var idx/ecx: int <- copy y
- 638   idx <- multiply width
- 639   idx <- add x
- 640   var src/eax: byte <- copy val
- 641   var dest-a/edi: (addr byte) <- index buf, idx
- 642   copy-byte-to *dest-a, src
- 643 }
- 644 
- 645 # some debugging helpers
- 646 fn show-errors errors: (addr array int), width: int, height: int, x: int, y: int {
- 647   compare y, 1
- 648   {
- 649     break-if-=
- 650     return
- 651   }
- 652   compare x, 0
- 653   {
- 654     break-if-=
- 655     return
- 656   }
- 657   var y/edx: int <- copy 0
- 658   {
- 659     compare y, height
- 660     break-if->=
- 661     var x/ecx: int <- copy 0
- 662     {
- 663       compare x, width
- 664       break-if->=
- 665       var error/esi: int <- _read-dithering-error errors, x, y, width
- 666       psd "e", error, 5/fg, x, y
- 667       x <- increment
- 668       loop
- 669     }
- 670     move-cursor-to-left-margin-of-next-line 0/screen
- 671     y <- increment
- 672     loop
- 673   }
- 674 }
- 675 
- 676 fn psd s: (addr array byte), d: int, fg: int, x: int, y: int {
- 677   {
- 678     compare y, 0x18
- 679     break-if->=
- 680     return
- 681   }
- 682   {
- 683     compare y, 0x1c
- 684     break-if-<=
- 685     return
- 686   }
- 687   {
- 688     compare x, 0x40
- 689     break-if->=
- 690     return
- 691   }
- 692 #?   {
- 693 #?     compare x, 0x48
- 694 #?     break-if-<=
- 695 #?     return
- 696 #?   }
- 697   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg 0/bg
- 698   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, d, fg 0/bg
- 699 }
- 700 
- 701 fn psx s: (addr array byte), d: int, fg: int, x: int, y: int {
- 702 #?   {
- 703 #?     compare y, 0x60
- 704 #?     break-if->=
- 705 #?     return
- 706 #?   }
- 707 #?   {
- 708 #?     compare y, 0x6c
- 709 #?     break-if-<=
- 710 #?     return
- 711 #?   }
- 712   {
- 713     compare x, 0x20
- 714     break-if->=
- 715     return
- 716   }
- 717 #?   {
- 718 #?     compare x, 0x6c
- 719 #?     break-if-<=
- 720 #?     return
- 721 #?   }
- 722   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg 0/bg
- 723   draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, d, fg 0/bg
- 724 }
- 725 
- 726 # import a color ascii "pixmap" (each pixel consists of 3 shades of r/g/b from 0 to 255)
- 727 fn initialize-image-from-ppm _self: (addr image), in: (addr stream byte) {
- 728   var self/esi: (addr image) <- copy _self
- 729   var curr-word-storage: slice
- 730   var curr-word/ecx: (addr slice) <- address curr-word-storage
- 731   # load width, height
- 732   next-word in, curr-word
- 733   var tmp/eax: int <- parse-decimal-int-from-slice curr-word
- 734   var width/edx: int <- copy tmp
- 735   next-word in, curr-word
- 736   tmp <- parse-decimal-int-from-slice curr-word
- 737   var height/ebx: int <- copy tmp
- 738   next-word in, curr-word
- 739   # check color levels
- 740   {
- 741     tmp <- parse-decimal-int-from-slice curr-word
- 742     compare tmp, 0xff
- 743     break-if-=
- 744     abort "initialize-image-from-ppm: supports exactly 255 levels per rgb channel"
- 745   }
- 746   var dest/edi: (addr int) <- get self, max
- 747   copy-to *dest, tmp
- 748   # save width, height
- 749   dest <- get self, width
- 750   copy-to *dest, width
- 751   dest <- get self, height
- 752   copy-to *dest, height
- 753   # initialize data
- 754   var capacity/edx: int <- copy width
- 755   capacity <- multiply height
- 756   # . multiply by 3 for the r/g/b channels
- 757   var tmp/eax: int <- copy capacity
- 758   tmp <- shift-left 1
- 759   capacity <- add tmp
- 760   #
- 761   var data-ah/edi: (addr handle array byte) <- get self, data
- 762   populate data-ah, capacity
- 763   var _data/eax: (addr array byte) <- lookup *data-ah
- 764   var data/edi: (addr array byte) <- copy _data
- 765   var i/ebx: int <- copy 0
- 766   {
- 767     compare i, capacity
- 768     break-if->=
- 769     next-word in, curr-word
- 770     var src/eax: int <- parse-decimal-int-from-slice curr-word
- 771     {
- 772       var dest/ecx: (addr byte) <- index data, i
- 773       copy-byte-to *dest, src
- 774     }
- 775     i <- increment
- 776     loop
- 777   }
- 778 }
- 779 
- 780 # import a color ascii "pixmap" (each pixel consists of 3 shades of r/g/b from 0 to 255)
- 781 fn render-ppm-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
- 782   var img/esi: (addr image) <- copy _img
- 783   # yratio = height/img->height
- 784   var img-height-a/eax: (addr int) <- get img, height
- 785   var img-height/xmm0: float <- convert *img-height-a
- 786   var yratio/xmm1: float <- convert height
- 787   yratio <- divide img-height
- 788   # xratio = width/img->width
- 789   var img-width-a/eax: (addr int) <- get img, width
- 790   var img-width/ebx: int <- copy *img-width-a
- 791   var img-width-f/xmm0: float <- convert img-width
- 792   var xratio/xmm2: float <- convert width
- 793   xratio <- divide img-width-f
- 794   # esi = img->data
- 795   var img-data-ah/eax: (addr handle array byte) <- get img, data
- 796   var _img-data/eax: (addr array byte) <- lookup *img-data-ah
- 797   var img-data/esi: (addr array byte) <- copy _img-data
- 798   var len/edi: int <- length img-data
- 799   #
- 800   var one/eax: int <- copy 1
- 801   var one-f/xmm3: float <- convert one
- 802   var width-f/xmm4: float <- convert width
- 803   var height-f/xmm5: float <- convert height
- 804   var zero/eax: int <- copy 0
- 805   var zero-f/xmm0: float <- convert zero
- 806   var y/xmm6: float <- copy zero-f
- 807   {
- 808     compare y, height-f
- 809     break-if-float>=
- 810     var imgy-f/xmm5: float <- copy y
- 811     imgy-f <- divide yratio
- 812     var imgy/edx: int <- truncate imgy-f
- 813     var x/xmm7: float <- copy zero-f
- 814     {
- 815       compare x, width-f
- 816       break-if-float>=
- 817       var imgx-f/xmm5: float <- copy x
- 818       imgx-f <- divide xratio
- 819       var imgx/ecx: int <- truncate imgx-f
- 820       var idx/eax: int <- copy imgy
- 821       idx <- multiply img-width
- 822       idx <- add imgx
- 823       # . multiply by 3 for the r/g/b channels
- 824       {
- 825         var tmp/ecx: int <- copy idx
- 826         tmp <- shift-left 1
- 827         idx <- add tmp
- 828       }
- 829       # error info in case we rounded wrong and 'index' will fail bounds-check
- 830       compare idx, len
- 831       {
- 832         break-if-<
- 833         set-cursor-position 0/screen, 0x20/x 0x20/y
- 834         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgx, 3/fg 0/bg
- 835         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgy, 4/fg 0/bg
- 836         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 5/fg 0/bg
- 837       }
- 838       # r channel
- 839       var r: int
- 840       {
- 841         var src-a/eax: (addr byte) <- index img-data, idx
- 842         var src/eax: byte <- copy-byte *src-a
- 843         copy-to r, src
- 844       }
- 845       idx <- increment
- 846       # g channel
- 847       var g: int
- 848       {
- 849         var src-a/eax: (addr byte) <- index img-data, idx
- 850         var src/eax: byte <- copy-byte *src-a
- 851         copy-to g, src
- 852       }
- 853       idx <- increment
- 854       # b channel
- 855       var b: int
- 856       {
- 857         var src-a/eax: (addr byte) <- index img-data, idx
- 858         var src/eax: byte <- copy-byte *src-a
- 859         copy-to b, src
- 860       }
- 861       idx <- increment
- 862       # plot nearest color
- 863       var color/eax: int <- nearest-color-euclidean r, g, b
- 864       var screenx/ecx: int <- convert x
- 865       screenx <- add xmin
- 866       var screeny/edx: int <- convert y
- 867       screeny <- add ymin
- 868       pixel screen, screenx, screeny, color
- 869       x <- add one-f
- 870       loop
- 871     }
- 872     y <- add one-f
- 873     loop
- 874   }
- 875 }
- 876 
- 877 fn dither-ppm-unordered _src: (addr image), _dest: (addr image) {
- 878   var src/esi: (addr image) <- copy _src
- 879   var dest/edi: (addr image) <- copy _dest
- 880   # copy 'width'
- 881   var src-width-a/eax: (addr int) <- get src, width
- 882   var tmp/eax: int <- copy *src-width-a
- 883   var src-width: int
- 884   copy-to src-width, tmp
- 885   {
- 886     var dest-width-a/edx: (addr int) <- get dest, width
- 887     copy-to *dest-width-a, tmp
- 888   }
- 889   # copy 'height'
- 890   var src-height-a/eax: (addr int) <- get src, height
- 891   var tmp/eax: int <- copy *src-height-a
- 892   var src-height: int
- 893   copy-to src-height, tmp
- 894   {
- 895     var dest-height-a/ecx: (addr int) <- get dest, height
- 896     copy-to *dest-height-a, tmp
- 897   }
- 898   # compute scaling factor 255/max
- 899   var target-scale/eax: int <- copy 0xff
- 900   var scale-f/xmm7: float <- convert target-scale
- 901   var src-max-a/eax: (addr int) <- get src, max
- 902   var tmp-f/xmm0: float <- convert *src-max-a
- 903   scale-f <- divide tmp-f
- 904   # allocate 'data'
- 905   var capacity/ebx: int <- copy src-width
- 906   capacity <- multiply src-height
- 907   var dest/edi: (addr image) <- copy _dest
- 908   var dest-data-ah/eax: (addr handle array byte) <- get dest, data
- 909   populate dest-data-ah, capacity
- 910   var _dest-data/eax: (addr array byte) <- lookup *dest-data-ah
- 911   var dest-data/edi: (addr array byte) <- copy _dest-data
- 912   # error buffers per r/g/b channel
- 913   var red-errors-storage: (array int 0xc0000)
- 914   var tmp/eax: (addr array int) <- address red-errors-storage
- 915   var red-errors: (addr array int)
- 916   copy-to red-errors, tmp
- 917   var green-errors-storage: (array int 0xc0000)
- 918   var tmp/eax: (addr array int) <- address green-errors-storage
- 919   var green-errors: (addr array int)
- 920   copy-to green-errors, tmp
- 921   var blue-errors-storage: (array int 0xc0000)
- 922   var tmp/eax: (addr array int) <- address blue-errors-storage
- 923   var blue-errors: (addr array int)
- 924   copy-to blue-errors, tmp
- 925   # transform 'data'
- 926   var src-data-ah/eax: (addr handle array byte) <- get src, data
- 927   var _src-data/eax: (addr array byte) <- lookup *src-data-ah
- 928   var src-data/esi: (addr array byte) <- copy _src-data
- 929   var y/edx: int <- copy 0
- 930   {
- 931     compare y, src-height
- 932     break-if->=
- 933     var x/ecx: int <- copy 0
- 934     {
- 935       compare x, src-width
- 936       break-if->=
- 937       # - update errors and compute color levels for current pixel in each channel
- 938       # update red-error with current image pixel
- 939       var red-error: int
- 940       {
- 941         var tmp/esi: int <- _read-dithering-error red-errors, x, y, src-width
- 942         copy-to red-error, tmp
- 943       }
- 944       {
- 945         var tmp/eax: int <- _ppm-error src-data, x, y, src-width, 0/red, scale-f
- 946         add-to red-error, tmp
- 947       }
- 948       # recompute red channel for current pixel
- 949       var red-level: int
- 950       {
- 951         var tmp/eax: int <- _error-to-ppm-channel red-error
- 952         copy-to red-level, tmp
- 953       }
- 954       # update green-error with current image pixel
- 955       var green-error: int
- 956       {
- 957         var tmp/esi: int <- _read-dithering-error green-errors, x, y, src-width
- 958         copy-to green-error, tmp
- 959       }
- 960       {
- 961         var tmp/eax: int <- _ppm-error src-data, x, y, src-width, 1/green, scale-f
- 962         add-to green-error, tmp
- 963       }
- 964       # recompute green channel for current pixel
- 965       var green-level: int
- 966       {
- 967         var tmp/eax: int <- _error-to-ppm-channel green-error
- 968         copy-to green-level, tmp
- 969       }
- 970       # update blue-error with current image pixel
- 971       var blue-error: int
- 972       {
- 973         var tmp/esi: int <- _read-dithering-error blue-errors, x, y, src-width
- 974         copy-to blue-error, tmp
- 975       }
- 976       {
- 977         var tmp/eax: int <- _ppm-error src-data, x, y, src-width, 2/blue, scale-f
- 978         add-to blue-error, tmp
- 979       }
- 980       # recompute blue channel for current pixel
- 981       var blue-level: int
- 982       {
- 983         var tmp/eax: int <- _error-to-ppm-channel blue-error
- 984         copy-to blue-level, tmp
- 985       }
- 986       # - figure out the nearest color
- 987 #?       {
- 988 #?         compare red-level, 0x80
- 989 #?         break-if->
- 990 #?         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, red-level, 4/fg 0/bg
- 991 #?         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, green-level, 2/fg 0/bg
- 992 #?         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, blue-level, 9/fg 0/bg
- 993 #?       }
- 994       var nearest-color-index/eax: int <- nearest-color-euclidean red-level, green-level, blue-level
- 995       {
- 996         var nearest-color-index-byte/eax: byte <- copy-byte nearest-color-index
- 997         _write-raw-buffer dest-data, x, y, src-width, nearest-color-index-byte
- 998       }
- 999       # - diffuse errors
-1000       var red-level: int
-1001       var green-level: int
-1002       var blue-level: int
-1003       {
-1004         var tmp-red-level/ecx: int <- copy 0
-1005         var tmp-green-level/edx: int <- copy 0
-1006         var tmp-blue-level/ebx: int <- copy 0
-1007         tmp-red-level, tmp-green-level, tmp-blue-level <- color-rgb nearest-color-index
-1008         copy-to red-level, tmp-red-level
-1009         copy-to green-level, tmp-green-level
-1010         copy-to blue-level, tmp-blue-level
-1011       }
-1012       # update red-error
-1013       var red-level-error/eax: int <- copy red-level
-1014       red-level-error <- shift-left 0x10
-1015       subtract-from red-error, red-level-error
-1016       _diffuse-dithering-error-floyd-steinberg red-errors, x, y, src-width, src-height, red-error
-1017       # update green-error
-1018       var green-level-error/eax: int <- copy green-level
-1019       green-level-error <- shift-left 0x10
-1020       subtract-from green-error, green-level-error
-1021       _diffuse-dithering-error-floyd-steinberg green-errors, x, y, src-width, src-height, green-error
-1022       # update blue-error
-1023       var blue-level-error/eax: int <- copy blue-level
-1024       blue-level-error <- shift-left 0x10
-1025       subtract-from blue-error, blue-level-error
-1026       _diffuse-dithering-error-floyd-steinberg blue-errors, x, y, src-width, src-height, blue-error
-1027       #
-1028       x <- increment
-1029       loop
-1030     }
-1031     y <- increment
-1032     loop
-1033   }
-1034 }
-1035 
-1036 # convert a single channel for a single image pixel to error space
-1037 fn _ppm-error buf: (addr array byte), x: int, y: int, width: int, channel: int, _scale-f: float -> _/eax: int {
-1038   # current image pixel
-1039   var initial-level/eax: byte <- _read-ppm-buffer buf, x, y, width, channel
-1040   # scale to 255 levels
-1041   var initial-level-int/eax: int <- copy initial-level
-1042   var initial-level-f/xmm0: float <- convert initial-level-int
-1043   var scale-f/xmm1: float <- copy _scale-f
-1044   initial-level-f <- multiply scale-f
-1045   initial-level-int <- convert initial-level-f
-1046   # switch to fixed-point with 16 bits of precision
-1047   initial-level-int <- shift-left 0x10
-1048   return initial-level-int
-1049 }
-1050 
-1051 fn _error-to-ppm-channel error: int -> _/eax: int {
-1052   # clamp(error >> 16)
-1053   var result/esi: int <- copy error
-1054   result <- shift-right-signed 0x10
-1055   {
-1056     compare result, 0
-1057     break-if->=
-1058     result <- copy 0
-1059   }
-1060   {
-1061     compare result, 0xff
-1062     break-if-<=
-1063     result <- copy 0xff
-1064   }
-1065   return result
-1066 }
-1067 
-1068 # read from a buffer containing alternating bytes from r/g/b channels
-1069 fn _read-ppm-buffer _buf: (addr array byte), x: int, y: int, width: int, channel: int -> _/eax: byte {
-1070   var buf/esi: (addr array byte) <- copy _buf
-1071   var idx/ecx: int <- copy y
-1072   idx <- multiply width
-1073   idx <- add x
-1074   var byte-idx/edx: int <- copy 3
-1075   byte-idx <- multiply idx
-1076   byte-idx <- add channel
-1077   var result-a/eax: (addr byte) <- index buf, byte-idx
-1078   var result/eax: byte <- copy-byte *result-a
-1079   return result
-1080 }
-1081 
-1082 # each byte in the image data is a color of the current palette
-1083 fn render-raw-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
-1084   var img/esi: (addr image) <- copy _img
-1085   # yratio = height/img->height
-1086   var img-height-a/eax: (addr int) <- get img, height
-1087   var img-height/xmm0: float <- convert *img-height-a
-1088   var yratio/xmm1: float <- convert height
-1089   yratio <- divide img-height
-1090   # xratio = width/img->width
-1091   var img-width-a/eax: (addr int) <- get img, width
-1092   var img-width/ebx: int <- copy *img-width-a
-1093   var img-width-f/xmm0: float <- convert img-width
-1094   var xratio/xmm2: float <- convert width
-1095   xratio <- divide img-width-f
-1096   # esi = img->data
-1097   var img-data-ah/eax: (addr handle array byte) <- get img, data
-1098   var _img-data/eax: (addr array byte) <- lookup *img-data-ah
-1099   var img-data/esi: (addr array byte) <- copy _img-data
-1100   var len/edi: int <- length img-data
-1101   #
-1102   var one/eax: int <- copy 1
-1103   var one-f/xmm3: float <- convert one
-1104   var width-f/xmm4: float <- convert width
-1105   var height-f/xmm5: float <- convert height
-1106   var zero/eax: int <- copy 0
-1107   var zero-f/xmm0: float <- convert zero
-1108   var y/xmm6: float <- copy zero-f
-1109   {
-1110     compare y, height-f
-1111     break-if-float>=
-1112     var imgy-f/xmm5: float <- copy y
-1113     imgy-f <- divide yratio
-1114     var imgy/edx: int <- truncate imgy-f
-1115     var x/xmm7: float <- copy zero-f
-1116     {
-1117       compare x, width-f
-1118       break-if-float>=
-1119       var imgx-f/xmm5: float <- copy x
-1120       imgx-f <- divide xratio
-1121       var imgx/ecx: int <- truncate imgx-f
-1122       var idx/eax: int <- copy imgy
-1123       idx <- multiply img-width
-1124       idx <- add imgx
-1125       # error info in case we rounded wrong and 'index' will fail bounds-check
-1126       compare idx, len
-1127       {
-1128         break-if-<
-1129         set-cursor-position 0/screen, 0x20/x 0x20/y
-1130         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgx, 3/fg 0/bg
-1131         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgy, 4/fg 0/bg
-1132         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 5/fg 0/bg
-1133       }
-1134       var color-a/eax: (addr byte) <- index img-data, idx
-1135       var color/eax: byte <- copy-byte *color-a
-1136       var color-int/eax: int <- copy color
-1137       var screenx/ecx: int <- convert x
-1138       screenx <- add xmin
-1139       var screeny/edx: int <- convert y
-1140       screeny <- add ymin
-1141       pixel screen, screenx, screeny, color-int
-1142       x <- add one-f
-1143       loop
-1144     }
-1145     y <- add one-f
-1146     loop
-1147   }
-1148 }
-
- - - -- cgit 1.4.1-2-gfad0