about summary refs log tree commit diff stats
path: root/baremetal
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2021-01-16 11:35:31 -0800
committerKartik Agaram <vc@akkartik.com>2021-01-16 15:32:26 -0800
commit6efc1ebed7131a8cd88aafdce8eaa8ee0260d692 (patch)
tree8a919443e3a3774b95484b82d9f2d3b11ece564e /baremetal
parent3d6c6e5286b1ea3744db0ff32445cc2082ca5110 (diff)
downloadmu-6efc1ebed7131a8cd88aafdce8eaa8ee0260d692.tar.gz
7529 - baremetal: fake screen
Diffstat (limited to 'baremetal')
-rw-r--r--baremetal/308allocate-array.subx25
-rw-r--r--baremetal/500text-screen.mu192
-rw-r--r--baremetal/boot.hex4
3 files changed, 214 insertions, 7 deletions
diff --git a/baremetal/308allocate-array.subx b/baremetal/308allocate-array.subx
new file mode 100644
index 00000000..5cc0fe1b
--- /dev/null
+++ b/baremetal/308allocate-array.subx
@@ -0,0 +1,25 @@
+# 2-arg version of allocate-array.
+# Really only intended to be called from code generated by mu.subx.
+
+== code
+
+allocate-array2:  # ad: (addr allocation-descriptor), array-len: int, elem-size: int, out: (addr handle array _)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    52/push-edx
+    #
+    8b/-> *(ebp+0xc) 0/r32/eax
+    f7 4/subop/multiply-into-edx-eax *(ebp+0x10)
+    # TODO: check edx for overflow
+    (allocate-array *(ebp+8) %eax *(ebp+0x14))
+$allocate-array2:end:
+    # . restore registers
+    5a/pop-to-edx
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
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
+}
diff --git a/baremetal/boot.hex b/baremetal/boot.hex
index 3f78ca7a..1fc316c5 100644
--- a/baremetal/boot.hex
+++ b/baremetal/boot.hex
@@ -58,13 +58,13 @@
   # calls, so we don't need to initialize the stack.
 
 # 0e:
-  # load second sector from disk
+  # load some sectors from disk
   b4 02  # ah <- 2  # read sectors from disk
   # dl comes conveniently initialized at boot time with the index of the device being booted
   b5 00  # ch <- 0  # cylinder 0
   b6 00  # dh <- 0  # track 0
   b1 02  # cl <- 2  # second sector, 1-based
-  b0 20  # al <- 32  # number of sectors to read; all sectors must be in a single track
+  b0 3e  # al <- 62  # number of sectors to read; all sectors must be in a single track
   # address to write sectors to = es:bx = 0x7e00, contiguous with boot segment
   bb 00 00  # bx <- 0
   8e c3  # es <- bx