7507 - baremetal: drawing text down then right

This commit is contained in:
Kartik Agaram 2021-01-12 23:52:24 -08:00
parent 8a81faecbe
commit 4413168269
4 changed files with 204 additions and 1 deletions

View File

@ -8,6 +8,7 @@ draw-grapheme: # screen: (addr screen), g: grapheme, x: int, y: int, color: int
52/push-edx
53/push-ebx
56/push-esi
# TODO: support fake screen; we currently assume 'screen' is always 0 (real)
# var letter-bitmap/esi = font[g]
8b/-> *(ebp+0xc) 6/r32/esi
c1 4/subop/shift-left %esi 4/imm8
@ -57,6 +58,12 @@ draw-grapheme: # screen: (addr screen), g: grapheme, x: int, y: int, color: int
#
eb/jump loop/disp8
}
# Save default coordinates for a future call to draw-grapheme
8b/-> *(ebp+0x10) 0/r32/eax
81 0/subop/add %eax 8/imm32
89/<- *Default-next-x 0/r32/eax
8b/-> *(ebp+0x14) 0/r32/eax
89/<- *Default-next-y 0/r32/eax
$draw-grapheme:end:
# . restore registers
5e/pop-to-esi
@ -68,3 +75,24 @@ $draw-grapheme:end:
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
cursor-position: # screen: (addr screen) -> _/eax: int, _/ecx: int
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# TODO: support fake screen; we currently assume 'screen' is always 0 (real)
8b/-> *Default-next-x 0/r32/eax
8b/-> *Default-next-y 1/r32/ecx
$cursor-position:end:
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
== data
Default-next-x:
0/imm32
Default-next-y:
0/imm32

View File

@ -1,6 +1,7 @@
sig pixel screen: (addr screen), x: int, y: int, color: int
sig read-key kbd: (addr keyboard) -> _/eax: byte
sig draw-grapheme screen: (addr screen), g: grapheme, x: int, y: int, color: int
sig cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int
sig clear-stream f: (addr stream _)
sig rewind-stream f: (addr stream _)
sig write f: (addr stream byte), s: (addr array byte)

View File

@ -35,6 +35,14 @@ fn draw-text-rightward screen: (addr screen), text: (addr array byte), x: int, x
return xcurr
}
fn draw-text-rightward-from-cursor screen: (addr screen), text: (addr array byte), xmax: int, color: int -> _/eax: 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-rightward screen, text, cursor-x, xmax, cursor-y, color
return result
}
# 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.
@ -86,3 +94,164 @@ fn draw-text-wrapping-right-then-down screen: (addr screen), text: (addr array b
}
return xcurr, ycurr
}
fn draw-text-wrapping-right-then-down-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int -> _/eax: int, _/ecx: int {
var cursor-x/eax: int <- copy 0
var cursor-y/ecx: int <- copy 0
cursor-x, cursor-y <- draw-text-wrapping-right-then-down screen, text, 0, 0, 0x400, 0x300, x, y, color # 1024, 768
return 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 -> _/eax: int, _/ecx: int {
var cursor-x/eax: int <- copy 0
var cursor-y/ecx: int <- copy 0
cursor-x, cursor-y <- cursor-position screen
# we could wrap around if we're too far to the right, but that feels like it
# makes assumptions about text direction
#? var end-x/edx: int <- copy cursor-x
#? end-x <- add 8 # font-width
#? compare end-x, xmax
#? {
#? break-if-<
#? cursor-x <- copy xmin
#? cursor-y <- add 0x10 # font-height
#? }
cursor-x, cursor-y <- draw-text-wrapping-right-then-down screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color
return cursor-x, cursor-y
}
fn draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int -> _/eax: int, _/ecx: int {
var cursor-x/eax: int <- copy 0
var cursor-y/ecx: int <- copy 0
cursor-x, cursor-y <- draw-text-wrapping-right-then-down-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768
return cursor-x, cursor-y
}
## 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, return 0 without modifying the screen
fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y: int, ymax: int, color: int -> _/eax: int {
var stream-storage: (stream byte 0x100)
var stream/esi: (addr stream byte) <- address stream-storage
write stream, text
# check if we have enough space
var ycurr/ecx: int <- copy y
{
compare ycurr, ymax
break-if->
var g/eax: grapheme <- read-grapheme stream
compare g, 0xffffffff # end-of-file
break-if-=
ycurr <- add 0x10 # font-height
loop
}
compare ycurr, ymax
{
break-if-<=
return 0
}
# we do; actually draw
rewind-stream stream
ycurr <- copy y
{
var g/eax: grapheme <- read-grapheme stream
compare g, 0xffffffff # end-of-file
break-if-=
draw-grapheme screen, g, x, ycurr, color
ycurr <- add 0x10 # font-height
loop
}
return ycurr
}
fn draw-text-downward-from-cursor screen: (addr screen), text: (addr array byte), ymax: int, color: int -> _/eax: 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
return result
}
# 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, return 0 without modifying the screen
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 -> _/eax: int, _/ecx: int {
var stream-storage: (stream byte 0x100)
var stream/esi: (addr stream byte) <- address stream-storage
write stream, text
# check if we have enough space
var xcurr/edx: int <- copy x
var ycurr/ecx: int <- copy y
{
compare xcurr, xmax
break-if->=
var g/eax: grapheme <- read-grapheme stream
compare g, 0xffffffff # end-of-file
break-if-=
ycurr <- add 0x10 # font-height
compare ycurr, ymax
{
break-if-<
xcurr <- add 8 # font-width
ycurr <- copy ymin
}
loop
}
compare xcurr, xmax
{
break-if-<
return 0, 0
}
# we do; actually draw
rewind-stream stream
xcurr <- copy x
ycurr <- copy y
{
var g/eax: grapheme <- read-grapheme stream
compare g, 0xffffffff # end-of-file
break-if-=
draw-grapheme screen, g, xcurr, ycurr, color
ycurr <- add 0x10 # font-height
compare ycurr, ymax
{
break-if-<
xcurr <- add 8 # font-width
ycurr <- copy ymin
}
loop
}
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 -> _/eax: int, _/ecx: int {
var cursor-x/eax: int <- copy 0
var cursor-y/ecx: int <- copy 0
cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, 0, 0, 0x400, 0x300, x, y, color # 1024, 768
return 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 -> _/eax: int, _/ecx: 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 <- add 0x10 # font-height
#? compare end-y, ymax
#? {
#? break-if-<
#? cursor-x <- add 8 # font-width
#? 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
return cursor-x, cursor-y
}
fn draw-text-wrapping-down-then-right-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int -> _/eax: int, _/ecx: int {
var cursor-x/eax: int <- copy 0
var cursor-y/ecx: int <- copy 0
cursor-x, cursor-y <- draw-text-wrapping-down-then-right-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768
return cursor-x, cursor-y
}

View File

@ -1,4 +1,4 @@
# Drawing ASCII text incrementally within a bounding box.
# Drawing ASCII text incrementally.
#
# To build a disk image:
# ./translate_mu_baremetal baremetal/ex6.mu # emits disk.img
@ -10,6 +10,7 @@
# Expected output: a box and text that doesn't overflow it
fn main {
# drawing text within a bounding box
draw-box 0, 0xf, 0x1f, 0x79, 0x51, 0x4
var x/eax: int <- copy 0x20
var y/ecx: int <- copy 0x20
@ -17,4 +18,8 @@ fn main {
x, y <- draw-text-wrapping-right-then-down 0, "from ", 0x10, 0x20, 0x78, 0x50, x, y, 0xa
x, y <- draw-text-wrapping-right-then-down 0, "baremetal ", 0x10, 0x20, 0x78, 0x50, x, y, 0xa
x, y <- draw-text-wrapping-right-then-down 0, "Mu!", 0x10, 0x20, 0x78, 0x50, x, y, 0xa
# drawing at the cursor in multiple directions
x, y <- draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0, "abc", 0xa
x, y <- draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "def", 0xa
}