about summary refs log tree commit diff stats
path: root/baremetal/500text-screen.mu
diff options
context:
space:
mode:
Diffstat (limited to 'baremetal/500text-screen.mu')
-rw-r--r--baremetal/500text-screen.mu192
1 files changed, 187 insertions, 5 deletions
diff --git a/baremetal/500text-screen.mu b/baremetal/500text-screen.mu
index 525ddb03..5458398b 100644
--- a/baremetal/500text-screen.mu
+++ b/baremetal/500text-screen.mu
@@ -2,6 +2,67 @@
 #
 # Unlike the top-level, this text mode has no scrolling.
 
+# coordinates here don't match top-level
+# Here we're consistent with graphics mode. Top-level is consistent with
+# terminal emulators.
+type screen {
+  width: int
+  height: int
+  data: (handle array screen-cell)
+  cursor-x: int
+  cursor-y: int
+}
+
+type screen-cell {
+  data: grapheme
+  color: int
+}
+
+fn initialize-screen screen: (addr screen), width: int, height: int {
+  var screen-addr/esi: (addr screen) <- copy screen
+  var tmp/eax: int <- copy 0
+  var dest/edi: (addr int) <- copy 0
+  # screen->width = width
+  dest <- get screen-addr, width
+  tmp <- copy width
+  copy-to *dest, tmp
+  # screen->height = height
+  dest <- get screen-addr, height
+  tmp <- copy height
+  copy-to *dest, tmp
+  # screen->data = new screen-cell[width*height]
+  {
+    var data-addr/edi: (addr handle array screen-cell) <- get screen-addr, data
+    tmp <- multiply width
+    populate data-addr, tmp
+  }
+  # screen->cursor-x = 0
+  dest <- get screen-addr, cursor-x
+  copy-to *dest, 0
+  # screen->cursor-y = 0
+  dest <- get screen-addr, cursor-y
+  copy-to *dest, 0
+}
+
+fn screen-size screen: (addr screen) -> _/eax: int, _/ecx: int {
+  var width/eax: int <- copy 0
+  var height/ecx: int <- copy 0
+  compare screen, 0
+  {
+    break-if-!=
+    width <- copy 0x30  # 768/16
+    height <- copy 0x80  # 1024/8
+    return width, height
+  }
+  # fake screen
+  var screen-addr/esi: (addr screen) <- copy screen
+  var tmp/edx: (addr int) <- get screen-addr, width
+  width <- copy *tmp
+  tmp <- get screen-addr, height
+  height <- copy *tmp
+  return width, height
+}
+
 fn draw-grapheme screen: (addr screen), g: grapheme, x: int, y: int, color: int {
   {
     compare screen, 0
@@ -9,7 +70,28 @@ fn draw-grapheme screen: (addr screen), g: grapheme, x: int, y: int, color: int
     draw-grapheme-on-real-screen g, x, y, color
     return
   }
-  # TODO: fake screen
+  # fake screen
+  var screen-addr/esi: (addr screen) <- copy screen
+  var idx/ecx: int <- screen-cell-index screen-addr, x, y
+  var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
+  var data/eax: (addr array screen-cell) <- lookup *data-ah
+  var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+  var dest-cell/ecx: (addr screen-cell) <- index data, offset
+  var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
+  var g2/edx: grapheme <- copy g
+  copy-to *dest-grapheme, g2
+  var dest-color/eax: (addr int) <- get dest-cell, color
+  var color2/edx: grapheme <- copy color
+  copy-to *dest-color, color2
+}
+
+fn screen-cell-index screen-on-stack: (addr screen), x: int, y: int -> _/ecx: int {
+  var screen/esi: (addr screen) <- copy screen-on-stack
+  var height-addr/eax: (addr int) <- get screen, height
+  var result/ecx: int <- copy y
+  result <- multiply *height-addr
+  result <- add x
+  return result
 }
 
 fn cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int {
@@ -21,8 +103,11 @@ fn cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int {
     x, y <- cursor-position-on-real-screen
     return x, y
   }
-  # TODO: fake screen
-  return 0, 0
+  # fake screen
+  var screen-addr/esi: (addr screen) <- copy screen
+  var cursor-x-addr/eax: (addr int) <- get screen-addr, cursor-x
+  var cursor-y-addr/ecx: (addr int) <- get screen-addr, cursor-y
+  return *cursor-x-addr, *cursor-y-addr
 }
 
 fn set-cursor-position screen: (addr screen), x: int, y: int {
@@ -32,7 +117,44 @@ fn set-cursor-position screen: (addr screen), x: int, y: int {
     set-cursor-position-on-real-screen x, y
     return
   }
-  # TODO: fake screen
+  # fake screen
+  var screen-addr/esi: (addr screen) <- copy screen
+  # ignore x < 0
+  {
+    compare x, 0
+    break-if->=
+    return
+  }
+  # ignore x >= width
+  {
+    var width-addr/eax: (addr int) <- get screen-addr, width
+    var width/eax: int <- copy *width-addr
+    compare x, width
+    break-if-<=
+    return
+  }
+  # ignore y < 0
+  {
+    compare y, 0
+    break-if->=
+    return
+  }
+  # ignore y >= height
+  {
+    var height-addr/eax: (addr int) <- get screen-addr, height
+    var height/eax: int <- copy *height-addr
+    compare y, height
+    break-if-<
+    return
+  }
+  # screen->cursor-x = x
+  var dest/edi: (addr int) <- get screen-addr, cursor-x
+  var src/eax: int <- copy x
+  copy-to *dest, src
+  # screen->cursor-y = y
+  dest <- get screen-addr, cursor-y
+  src <- copy y
+  copy-to *dest, src
 }
 
 fn clear-screen screen: (addr screen) {
@@ -42,9 +164,32 @@ fn clear-screen screen: (addr screen) {
     clear-real-screen
     return
   }
-  # TODO: fake screen
+  # fake screen
+  var space/edi: grapheme <- copy 0x20
+  set-cursor-position screen, 0, 0
+  var screen-addr/esi: (addr screen) <- copy screen
+  var y/eax: int <- copy 1
+  var height/ecx: (addr int) <- get screen-addr, height
+  {
+    compare y, *height
+    break-if->
+    var x/edx: int <- copy 1
+    var width/ebx: (addr int) <- get screen-addr, width
+    {
+      compare x, *width
+      break-if->
+      draw-grapheme screen, space, x, y, 0  # color=black
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+  set-cursor-position screen, 0, 0
 }
 
+# there's no grapheme that guarantees to cover every pixel, so we'll bump down
+# to pixels for a real screen
 fn clear-real-screen {
   var y/eax: int <- copy 0
   {
@@ -62,3 +207,40 @@ fn clear-real-screen {
     loop
   }
 }
+
+fn screen-grapheme-at screen-on-stack: (addr screen), x: int, y: int -> _/eax: grapheme {
+  var screen-addr/esi: (addr screen) <- copy screen-on-stack
+  var idx/ecx: int <- screen-cell-index screen-addr, x, y
+  var result/eax: grapheme <- screen-grapheme-at-idx screen-addr, idx
+  return result
+}
+
+fn screen-grapheme-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: grapheme {
+  var screen-addr/esi: (addr screen) <- copy screen-on-stack
+  var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
+  var data/eax: (addr array screen-cell) <- lookup *data-ah
+  var idx/ecx: int <- copy idx-on-stack
+  var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+  var cell/eax: (addr screen-cell) <- index data, offset
+  var src/eax: (addr grapheme) <- get cell, data
+  return *src
+}
+
+fn screen-color-at screen-on-stack: (addr screen), x: int, y: int -> _/eax: int {
+  var screen-addr/esi: (addr screen) <- copy screen-on-stack
+  var idx/ecx: int <- screen-cell-index screen-addr, x, y
+  var result/eax: int <- screen-color-at-idx screen-addr, idx
+  return result
+}
+
+fn screen-color-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: int {
+  var screen-addr/esi: (addr screen) <- copy screen-on-stack
+  var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
+  var data/eax: (addr array screen-cell) <- lookup *data-ah
+  var idx/ecx: int <- copy idx-on-stack
+  var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+  var cell/eax: (addr screen-cell) <- index data, offset
+  var src/eax: (addr int) <- get cell, color
+  var result/eax: int <- copy *src
+  return result
+}