From 6efc1ebed7131a8cd88aafdce8eaa8ee0260d692 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 16 Jan 2021 11:35:31 -0800 Subject: 7529 - baremetal: fake screen --- baremetal/308allocate-array.subx | 25 +++++ baremetal/500text-screen.mu | 192 ++++++++++++++++++++++++++++++++++++++- baremetal/boot.hex | 4 +- 3 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 baremetal/308allocate-array.subx (limited to 'baremetal') 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 -- cgit 1.4.1-2-gfad0