From 71e4f3812982dba2efb471283d310224e8db363e Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 3 Mar 2021 22:09:50 -0800 Subject: 7842 - new directory organization Baremetal is now the default build target and therefore has its sources at the top-level. Baremetal programs build using the phase-2 Mu toolchain that requires a Linux kernel. This phase-2 codebase which used to be at the top-level is now under the linux/ directory. Finally, the phase-2 toolchain, while self-hosting, has a way to bootstrap from a C implementation, which is now stored in linux/bootstrap. The bootstrap C implementation uses some literate programming tools that are now in linux/bootstrap/tools. So the whole thing has gotten inverted. Each directory should build one artifact and include the main sources (along with standard library). Tools used for building it are relegated to sub-directories, even though those tools are often useful in their own right, and have had lots of interesting programs written using them. A couple of things have gotten dropped in this process: - I had old ways to run on just a Linux kernel, or with a Soso kernel. No more. - I had some old tooling for running a single test at the cursor. I haven't used that lately. Maybe I'll bring it back one day. The reorg isn't done yet. Still to do: - redo documentation everywhere. All the README files, all other markdown, particularly vocabulary.md. - clean up how-to-run comments at the start of programs everywhere - rethink what to do with the html/ directory. Do we even want to keep supporting it? In spite of these shortcomings, all the scripts at the top-level, linux/ and linux/bootstrap are working. The names of the scripts also feel reasonable. This is a good milestone to take stock at. --- 501draw-text.mu | 466 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 501draw-text.mu (limited to '501draw-text.mu') diff --git a/501draw-text.mu b/501draw-text.mu new file mode 100644 index 00000000..9b207361 --- /dev/null +++ b/501draw-text.mu @@ -0,0 +1,466 @@ +# some primitives for moving the cursor without making assumptions about +# raster order +fn move-cursor-left screen: (addr screen) { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + compare cursor-x, 0 + { + break-if-> + return + } + cursor-x <- decrement + set-cursor-position screen, cursor-x, cursor-y +} + +fn move-cursor-right screen: (addr screen) { + var _width/eax: int <- copy 0 + var dummy/ecx: int <- copy 0 + _width, dummy <- screen-size screen + var limit/edx: int <- copy _width + limit <- decrement + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + compare cursor-x, limit + { + break-if-< + return + } + cursor-x <- increment + set-cursor-position screen, cursor-x, cursor-y +} + +fn move-cursor-up screen: (addr screen) { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + compare cursor-y, 0 + { + break-if-> + return + } + cursor-y <- decrement + set-cursor-position screen, cursor-x, cursor-y +} + +fn move-cursor-down screen: (addr screen) { + var dummy/eax: int <- copy 0 + var _height/ecx: int <- copy 0 + dummy, _height <- screen-size screen + var limit/edx: int <- copy _height + limit <- decrement + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + compare cursor-y, limit + { + break-if-< + return + } + cursor-y <- increment + set-cursor-position screen, cursor-x, cursor-y +} + +fn move-cursor-to-start-of-next-line screen: (addr screen) { + var dummy/eax: int <- copy 0 + var _height/ecx: int <- copy 0 + dummy, _height <- screen-size screen + var limit/edx: int <- copy _height + limit <- decrement + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + compare cursor-y, limit + { + break-if-< + return + } + cursor-y <- increment + cursor-x <- copy 0 + set-cursor-position screen, cursor-x, cursor-y +} + +fn draw-grapheme-at-cursor screen: (addr screen), g: grapheme, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + draw-grapheme screen, g, cursor-x, cursor-y, color, background-color +} + +# we can't really render non-ASCII yet, but when we do we'll be ready +fn draw-code-point-at-cursor screen: (addr screen), c: code-point, color: int, background-color: int { + var g/eax: grapheme <- copy c + draw-grapheme-at-cursor screen, g, color, background-color +} + +# draw a single line of text from x, y to xmax +# return the next 'x' coordinate +# if there isn't enough space, truncate +fn draw-text-rightward screen: (addr screen), text: (addr array byte), x: int, xmax: int, y: int, color: int, background-color: int -> _/eax: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, text + var xcurr/eax: int <- draw-stream-rightward screen, stream, x, xmax, y, color, background-color + return xcurr +} + +# draw a single-line stream from x, y to xmax +# return the next 'x' coordinate +# if there isn't enough space, truncate +fn draw-stream-rightward screen: (addr screen), stream: (addr stream byte), x: int, xmax: int, y: int, color: int, background-color: int -> _/eax: int { + var xcurr/ecx: int <- copy x + { + var g/eax: grapheme <- read-grapheme stream + compare g, 0xffffffff/end-of-file + break-if-= + draw-grapheme screen, g, xcurr, y, color, background-color + xcurr <- increment + loop + } + set-cursor-position screen, xcurr, y + return xcurr +} + +fn draw-text-rightward-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int, background-color: int -> _/eax: int { + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + var result/eax: int <- draw-text-rightward screen, text, x, width, y, color, background-color + return result +} + +fn draw-text-rightward-from-cursor screen: (addr screen), text: (addr array byte), xmax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + cursor-x <- draw-text-rightward screen, text, cursor-x, xmax, cursor-y, color, background-color + set-cursor-position screen, cursor-x, cursor-y +} + +fn render-grapheme screen: (addr screen), g: grapheme, xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + compare g, 0xa/newline + var x/eax: int <- copy x + { + break-if-!= + # minimum effort to clear cursor + draw-code-point screen, 0x20/space, x, y, color, background-color + x <- copy xmin + increment y + return x, y + } + draw-grapheme screen, g, x, y, color, background-color + x <- increment + compare x, xmax + { + break-if-< + x <- copy xmin + increment y + } + return x, y +} + +# draw text in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary +# return the next (x, y) coordinate in raster order where drawing stopped +# that way the caller can draw more if given the same min and max bounding-box. +# if there isn't enough space, truncate +fn draw-text-wrapping-right-then-down screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, text + var x/eax: int <- copy _x + var y/ecx: int <- copy _y + x, y <- draw-stream-wrapping-right-then-down screen, stream, xmin, ymin, xmax, ymax, x, y, color, background-color + return x, y +} + +# draw a stream in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary +# return the next (x, y) coordinate in raster order where drawing stopped +# that way the caller can draw more if given the same min and max bounding-box. +# if there isn't enough space, truncate +fn draw-stream-wrapping-right-then-down screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var xcurr/eax: int <- copy x + var ycurr/ecx: int <- copy y + var g/ebx: grapheme <- copy 0 + { + { + var _g/eax: grapheme <- read-grapheme stream + g <- copy _g + } + compare g, 0xffffffff/end-of-file + break-if-= + xcurr, ycurr <- render-grapheme screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color + loop + } + set-cursor-position screen, xcurr, ycurr + return xcurr, ycurr +} + +fn move-cursor-rightward-and-downward screen: (addr screen), xmin: int, xmax: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + cursor-x <- increment + compare cursor-x, xmax + { + break-if-< + cursor-x <- copy xmin + cursor-y <- increment + } + set-cursor-position screen, cursor-x, cursor-y +} + +fn draw-text-wrapping-right-then-down-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var x2/eax: int <- copy 0 + var y2/ecx: int <- copy 0 + x2, y2 <- screen-size screen # width, height + x2, y2 <- draw-text-wrapping-right-then-down screen, text, 0/xmin, 0/ymin, x2, y2, x, y, color, background-color + return x2, y2 # cursor-x, cursor-y +} + +fn draw-text-wrapping-right-then-down-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + var end-x/edx: int <- copy cursor-x + end-x <- increment + compare end-x, xmax + { + break-if-< + cursor-x <- copy xmin + cursor-y <- increment + } + cursor-x, cursor-y <- draw-text-wrapping-right-then-down screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color, background-color +} + +fn draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int, background-color: int { + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + draw-text-wrapping-right-then-down-from-cursor screen, text, 0/xmin, 0/ymin, width, height, color, background-color +} + +fn draw-int32-hex-wrapping-right-then-down screen: (addr screen), n: int, xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write-int32-hex stream, n + var xcurr/edx: int <- copy x + var ycurr/ecx: int <- copy y + { + var g/eax: grapheme <- read-grapheme stream + compare g, 0xffffffff/end-of-file + break-if-= + draw-grapheme screen, g, xcurr, ycurr, color, background-color + xcurr <- increment + compare xcurr, xmax + { + break-if-< + xcurr <- copy xmin + ycurr <- increment + } + loop + } + set-cursor-position screen, xcurr, ycurr + return xcurr, ycurr +} + +fn draw-int32-hex-wrapping-right-then-down-over-full-screen screen: (addr screen), n: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var x2/eax: int <- copy 0 + var y2/ecx: int <- copy 0 + x2, y2 <- screen-size screen # width, height + x2, y2 <- draw-int32-hex-wrapping-right-then-down screen, n, 0/xmin, 0/ymin, x2, y2, x, y, color, background-color + return x2, y2 # cursor-x, cursor-y +} + +fn draw-int32-hex-wrapping-right-then-down-from-cursor screen: (addr screen), n: int, xmin: int, ymin: int, xmax: int, ymax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + var end-x/edx: int <- copy cursor-x + end-x <- increment + compare end-x, xmax + { + break-if-< + cursor-x <- copy xmin + cursor-y <- increment + } + cursor-x, cursor-y <- draw-int32-hex-wrapping-right-then-down screen, n, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color, background-color +} + +fn draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), n: int, color: int, background-color: int { + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + draw-int32-hex-wrapping-right-then-down-from-cursor screen, n, 0/xmin, 0/ymin, width, height, color, background-color +} + +fn draw-int32-decimal-wrapping-right-then-down screen: (addr screen), n: int, xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write-int32-decimal stream, n + var xcurr/edx: int <- copy x + var ycurr/ecx: int <- copy y + { + var g/eax: grapheme <- read-grapheme stream + compare g, 0xffffffff/end-of-file + break-if-= + draw-grapheme screen, g, xcurr, ycurr, color, background-color + xcurr <- increment + compare xcurr, xmax + { + break-if-< + xcurr <- copy xmin + ycurr <- increment + } + loop + } + set-cursor-position screen, xcurr, ycurr + return xcurr, ycurr +} + +fn draw-int32-decimal-wrapping-right-then-down-over-full-screen screen: (addr screen), n: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var x2/eax: int <- copy 0 + var y2/ecx: int <- copy 0 + x2, y2 <- screen-size screen # width, height + x2, y2 <- draw-int32-decimal-wrapping-right-then-down screen, n, 0/xmin, 0/ymin, x2, y2, x, y, color, background-color + return x2, y2 # cursor-x, cursor-y +} + +fn draw-int32-decimal-wrapping-right-then-down-from-cursor screen: (addr screen), n: int, xmin: int, ymin: int, xmax: int, ymax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + var end-x/edx: int <- copy cursor-x + end-x <- increment + compare end-x, xmax + { + break-if-< + cursor-x <- copy xmin + cursor-y <- increment + } + cursor-x, cursor-y <- draw-int32-decimal-wrapping-right-then-down screen, n, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color, background-color +} + +fn draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), n: int, color: int, background-color: int { + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + draw-int32-decimal-wrapping-right-then-down-from-cursor screen, n, 0/xmin, 0/ymin, width, height, color, background-color +} + +## Text direction: down then right + +# draw a single line of text vertically from x, y to ymax +# return the next 'y' coordinate +# if there isn't enough space, truncate +fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y: int, ymax: int, color: int, background-color: int -> _/eax: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, text + var ycurr/eax: int <- draw-stream-downward screen, stream, x, y, ymax, color, background-color + return ycurr +} + +# draw a single-line stream vertically from x, y to ymax +# return the next 'y' coordinate +# if there isn't enough space, truncate +fn draw-stream-downward screen: (addr screen), stream: (addr stream byte), x: int, y: int, ymax: int, color: int, background-color: int -> _/eax: int { + var ycurr/ecx: int <- copy y + { + var g/eax: grapheme <- read-grapheme stream + compare g, 0xffffffff/end-of-file + break-if-= + draw-grapheme screen, g, x, ycurr, color, background-color + ycurr <- increment + loop + } + set-cursor-position screen, x, ycurr + return ycurr +} + +fn draw-text-downward-from-cursor screen: (addr screen), text: (addr array byte), ymax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + var result/eax: int <- draw-text-downward screen, text, cursor-x, cursor-y, ymax, color, background-color +} + +# draw text down and right in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary +# return the next (x, y) coordinate in raster order where drawing stopped +# that way the caller can draw more if given the same min and max bounding-box. +# if there isn't enough space, truncate +fn draw-text-wrapping-down-then-right screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, text + var x/eax: int <- copy _x + var y/ecx: int <- copy _y + x, y <- draw-stream-wrapping-down-then-right screen, stream, xmin, ymin, xmax, ymax, x, y, color, background-color + return x, y +} + +# draw a stream down and right in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary +# return the next (x, y) coordinate in raster order where drawing stopped +# that way the caller can draw more if given the same min and max bounding-box. +# if there isn't enough space, truncate +fn draw-stream-wrapping-down-then-right screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var xcurr/edx: int <- copy x + var ycurr/ecx: int <- copy y + { + var g/eax: grapheme <- read-grapheme stream + compare g, 0xffffffff/end-of-file + break-if-= + draw-grapheme screen, g, xcurr, ycurr, color, background-color + ycurr <- increment + compare ycurr, ymax + { + break-if-< + xcurr <- increment + ycurr <- copy ymin + } + loop + } + set-cursor-position screen, xcurr, ycurr + return xcurr, ycurr +} + +fn draw-text-wrapping-down-then-right-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int { + var x2/eax: int <- copy 0 + var y2/ecx: int <- copy 0 + x2, y2 <- screen-size screen # width, height + x2, y2 <- draw-text-wrapping-down-then-right screen, text, 0/xmin, 0/ymin, x2, y2, x, y, color, background-color + return x2, y2 # cursor-x, cursor-y +} + +fn draw-text-wrapping-down-then-right-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int, background-color: int { + var cursor-x/eax: int <- copy 0 + var cursor-y/ecx: int <- copy 0 + cursor-x, cursor-y <- cursor-position screen + var end-y/edx: int <- copy cursor-y + end-y <- increment + compare end-y, ymax + { + break-if-< + cursor-x <- increment + cursor-y <- copy ymin + } + cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color, background-color +} + +fn draw-text-wrapping-down-then-right-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int, background-color: int { + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + draw-text-wrapping-down-then-right-from-cursor screen, text, 0/xmin, 0/ymin, width, height, color, background-color +} + +# hacky error-handling +# just go into an infinite loop +fn abort e: (addr array byte) { + var dummy1/eax: int <- copy 0 + var dummy2/ecx: int <- copy 0 + dummy1, dummy2 <- draw-text-wrapping-right-then-down-over-full-screen 0/screen, e, 0/x, 0x2f/y, 0xf/fg=white, 0xc/bg=red + { + loop + } +} -- cgit 1.4.1-2-gfad0