about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-04-19 21:05:57 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-04-19 21:05:57 -0700
commit34596b6ee9811a3f1a5bf94d307f6527cb7467b1 (patch)
treef443bd426bce78e677f0b4879cec0775156e6b1c
parentc22874a97f9e22f00b78b46b0647ea97325370f4 (diff)
downloadmu-34596b6ee9811a3f1a5bf94d307f6527cb7467b1.tar.gz
reimplement pixel graphics
Before: we always drew pixels atop characters, and we only drew pixels
that were explicitly requested.

After: we always draw pixels atop characters, and we only draw pixels that
don't have color 0.

Both semantics should be identical as long as pixels are never drawn atop
characters.
-rw-r--r--500fake-screen.mu151
-rw-r--r--shell/sandbox.mu70
2 files changed, 147 insertions, 74 deletions
diff --git a/500fake-screen.mu b/500fake-screen.mu
index 90944ed0..01df2d5e 100644
--- a/500fake-screen.mu
+++ b/500fake-screen.mu
@@ -19,7 +19,7 @@ type screen {
   cursor-x: int  # [0..width)
   cursor-y: int  # [0..height)
   # pixel graphics
-  pixels: (handle stream pixel)  # sparse representation
+  pixels: (handle array byte)
 }
 
 type screen-cell {
@@ -28,12 +28,6 @@ type screen-cell {
   background-color: int
 }
 
-type pixel {
-  x: int  # [0..width*font-width)
-  y: int  # [0..height*font-height)
-  color: int  # [0..256)
-}
-
 fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-graphics?: boolean {
   var screen/esi: (addr screen) <- copy _screen
   var tmp/eax: int <- copy 0
@@ -46,17 +40,24 @@ fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-grap
   dest <- get screen, height
   tmp <- copy height
   copy-to *dest, tmp
-  # screen->data = new screen-cell[width*height]
+  # populate screen->data
   {
-    var data-addr/edi: (addr handle array screen-cell) <- get screen, data
-    tmp <- multiply width
-    populate data-addr, tmp
+    var data-ah/edi: (addr handle array screen-cell) <- get screen, data
+    var capacity/eax: int <- copy width
+    capacity <- multiply height
+    populate data-ah, capacity
+  }
+  # if necessary, populate screen->pixels
+  {
+    compare pixel-graphics?, 0/false
+    break-if-=
+    var pixels-ah/edi: (addr handle array byte) <- get screen, pixels
+    var capacity/eax: int <- copy width
+    capacity <- shift-left 3/log2-font-width
+    capacity <- multiply height
+    capacity <- shift-left 4/log2-font-height
+    populate pixels-ah, capacity
   }
-  # allocate space for 16 pixels per 16x8 character. So one column of pixels
-  # per character.
-  var pixels-ah/ecx: (addr handle stream pixel) <- get screen, pixels
-  tmp <- shift-left 4
-  populate-stream pixels-ah, tmp
   # screen->cursor-x = 0
   dest <- get screen, cursor-x
   copy-to *dest, 0
@@ -136,7 +137,7 @@ fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
     abort "screen-cell-index: negative y"
   }
   {
-    var ymax/eax: (addr int) <- get screen, width
+    var ymax/eax: (addr int) <- get screen, height
     var ycurr/ecx: int <- copy y
     compare ycurr, *ymax
     break-if-<
@@ -254,9 +255,8 @@ fn clear-screen _screen: (addr screen) {
     loop
   }
   set-cursor-position screen, 0, 0
-  var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels
-  var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah
-  clear-stream dest-stream
+  var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+  var pixels/eax: (addr array byte) <- lookup *pixels-ah
 }
 
 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
@@ -285,11 +285,37 @@ fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
     y <- increment
     loop
   }
-  var pixels-ah/eax: (addr handle stream pixel) <- get screen, pixels
-  var pixels/eax: (addr stream pixel) <- lookup *pixels-ah
-  rewind-stream pixels
-  var result/eax: boolean <- stream-empty? pixels
-  return result
+  var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+  var pixels/eax: (addr array byte) <- lookup *pixels-ah
+  var y/ebx: int <- copy 0
+  var height-addr/edx: (addr int) <- get screen, height
+  var height/edx: int <- copy *height-addr
+  height <- shift-left 4/log2-font-height
+  {
+    compare y, height
+    break-if->=
+    var width-addr/edx: (addr int) <- get screen, width
+    var width/edx: int <- copy *width-addr
+    width <- shift-left 3/log2-font-width
+    var x/edi: int <- copy 0
+    {
+      compare x, width
+      break-if->=
+      var idx/ecx: int <- pixel-index screen, x, y
+      var color-addr/ecx: (addr byte) <- index pixels, idx
+      var color/ecx: byte <- copy-byte *color-addr
+      compare color, 0
+      {
+        break-if-=
+        return 0/false
+      }
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+  return 1/true
 }
 
 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
@@ -344,16 +370,16 @@ fn clear-real-screen {
 
 fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
   var y/eax: int <- copy ymin
-  y <- shift-left 4/log-font-height
+  y <- shift-left 4/log2-font-height
   var ymax/ecx: int <- copy ymax
-  ymax <- shift-left 4/log-font-height
+  ymax <- shift-left 4/log2-font-height
   {
     compare y, ymax
     break-if->=
     var x/edx: int <- copy xmin
-    x <- shift-left 3/log-font-width
+    x <- shift-left 3/log2-font-width
     var xmax/ebx: int <- copy xmax
-    xmax <- shift-left 3/log-font-width
+    xmax <- shift-left 3/log2-font-width
     {
       compare x, xmax
       break-if->=
@@ -430,27 +456,52 @@ fn pixel screen: (addr screen), x: int, y: int, color: int {
     return
   }
   # fake screen
-  # prepare a pixel
-  var pixel-storage: pixel
-  var src/ecx: int <- copy x
-  var dest/edx: (addr int) <- get pixel-storage, x
-  copy-to *dest, src
-  src <- copy y
-  dest <- get pixel-storage, y
-  copy-to *dest, src
-  src <- copy color
-  dest <- get pixel-storage, color
-  copy-to *dest, src
-  # save it
-  var src/ecx: (addr pixel) <- address pixel-storage
-  var screen/eax: (addr screen) <- copy screen
-  var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels
-  var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah
+  var screen/esi: (addr screen) <- copy screen
+  var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+  var pixels/eax: (addr array byte) <- lookup *pixels-ah
   {
-    var full?/eax: boolean <- stream-full? dest-stream
-    compare full?, 0/false
-    break-if-=
-    abort "tried to draw too many pixels on the fake screen; adjust initialize-screen"
+    compare pixels, 0
+    break-if-!=
+    abort "pixel graphics not enabled for this screen"
   }
-  write-to-stream dest-stream, src
+  var idx/ecx: int <- pixel-index screen, x, y
+  var dest/ecx: (addr byte) <- index pixels, idx
+  var src/eax: byte <- copy-byte color
+  copy-byte-to *dest, src
+}
+
+fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
+  var screen/esi: (addr screen) <- copy _screen
+  {
+    compare x, 0
+    break-if->=
+    abort "screen-cell-index: negative x"
+  }
+  {
+    var xmax-a/eax: (addr int) <- get screen, width
+    var xmax/eax: int <- copy *xmax-a
+    xmax <- shift-left 3/log2-font-width
+    compare x, xmax
+    break-if-<
+    abort "screen-cell-index: x too high"
+  }
+  {
+    compare y, 0
+    break-if->=
+    abort "screen-cell-index: negative y"
+  }
+  {
+    var ymax-a/eax: (addr int) <- get screen, height
+    var ymax/eax: int <- copy *ymax-a
+    ymax <- shift-left 4/log2-font-height
+    compare y, ymax
+    break-if-<
+    abort "screen-cell-index: y too high"
+  }
+  var width-addr/eax: (addr int) <- get screen, width
+  var result/ecx: int <- copy y
+  result <- multiply *width-addr
+  result <- shift-left 3/log2-font-width
+  result <- add x
+  return result
 }
diff --git a/shell/sandbox.mu b/shell/sandbox.mu
index 64fb3fdd..7f3c13e2 100644
--- a/shell/sandbox.mu
+++ b/shell/sandbox.mu
@@ -293,31 +293,53 @@ fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int
   }
   # pixel data
   {
-    var left/ebx: int <- copy xmin
-    left <- add 1/margin-left
-    left <- shift-left 3/log-font-width
-    var top/edx: int <- copy ymin
-    top <- add 1/margin-top
-    top <- shift-left 4/log-font-height
-    var pixels-ah/esi: (addr handle stream pixel) <- get target-screen, pixels
-    var _pixels/eax: (addr stream pixel) <- lookup *pixels-ah
-    var pixels/esi: (addr stream pixel) <- copy _pixels
-    rewind-stream pixels
+    # screen top left pixels x y width height
+    var tmp/eax: int <- copy xmin
+    tmp <- add 1/margin-left
+    tmp <- shift-left 3/log2-font-width
+    var left: int
+    copy-to left, tmp
+    tmp <- copy ymin
+    tmp <- add 1/margin-top
+    tmp <- shift-left 4/log2-font-height
+    var top: int
+    copy-to top, tmp
+    var pixels-ah/eax: (addr handle array byte) <- get target-screen, pixels
+    var _pixels/eax: (addr array byte) <- lookup *pixels-ah
+    var pixels/edi: (addr array byte) <- copy _pixels
+    compare pixels, 0
+    break-if-=
+    var y/ebx: int <- copy 0
+    var height-addr/edx: (addr int) <- get target-screen, height
+    var height/edx: int <- copy *height-addr
+    height <- shift-left 4/log2-font-height
     {
-      var done?/eax: boolean <- stream-empty? pixels
-      compare done?, 0/false
-      break-if-!=
-      var curr-pixel: pixel
-      var curr-pixel-addr/eax: (addr pixel) <- address curr-pixel
-      read-from-stream pixels, curr-pixel-addr
-      var curr-x/eax: (addr int) <- get curr-pixel, x
-      var x/eax: int <- copy *curr-x
-      x <- add left
-      var curr-y/ecx: (addr int) <- get curr-pixel, y
-      var y/ecx: int <- copy *curr-y
-      y <- add top
-      var curr-color/edx: (addr int) <- get curr-pixel, color
-      pixel screen, x, y, *curr-color
+      compare y, height
+      break-if->=
+      var width-addr/edx: (addr int) <- get target-screen, width
+      var width/edx: int <- copy *width-addr
+      width <- shift-left 3/log2-font-width
+      var x/eax: int <- copy 0
+      {
+        compare x, width
+        break-if->=
+        {
+          var idx/ecx: int <- pixel-index target-screen, x, y
+          var color-addr/ecx: (addr byte) <- index pixels, idx
+          var color/ecx: byte <- copy-byte *color-addr
+          var color2/ecx: int <- copy color
+          compare color2, 0
+          break-if-=
+          var x2/eax: int <- copy x
+          x2 <- add left
+          var y2/ebx: int <- copy y
+          y2 <- add top
+          pixel screen, x2, y2, color2
+        }
+        x <- increment
+        loop
+      }
+      y <- increment
       loop
     }
   }