diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-04-19 21:05:57 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-04-19 21:05:57 -0700 |
commit | 34596b6ee9811a3f1a5bf94d307f6527cb7467b1 (patch) | |
tree | f443bd426bce78e677f0b4879cec0775156e6b1c | |
parent | c22874a97f9e22f00b78b46b0647ea97325370f4 (diff) | |
download | mu-34596b6ee9811a3f1a5bf94d307f6527cb7467b1.tar.gz |
reimplement pixel graphics
Before: we always drew pixels atop characters, and we only drew pixels that were explicitly requested. After: we always draw pixels atop characters, and we only draw pixels that don't have color 0. Both semantics should be identical as long as pixels are never drawn atop characters.
-rw-r--r-- | 500fake-screen.mu | 151 | ||||
-rw-r--r-- | shell/sandbox.mu | 70 |
2 files changed, 147 insertions, 74 deletions
diff --git a/500fake-screen.mu b/500fake-screen.mu index 90944ed0..01df2d5e 100644 --- a/500fake-screen.mu +++ b/500fake-screen.mu @@ -19,7 +19,7 @@ type screen { cursor-x: int # [0..width) cursor-y: int # [0..height) # pixel graphics - pixels: (handle stream pixel) # sparse representation + pixels: (handle array byte) } type screen-cell { @@ -28,12 +28,6 @@ type screen-cell { background-color: int } -type pixel { - x: int # [0..width*font-width) - y: int # [0..height*font-height) - color: int # [0..256) -} - fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-graphics?: boolean { var screen/esi: (addr screen) <- copy _screen var tmp/eax: int <- copy 0 @@ -46,17 +40,24 @@ fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-grap dest <- get screen, height tmp <- copy height copy-to *dest, tmp - # screen->data = new screen-cell[width*height] + # populate screen->data { - var data-addr/edi: (addr handle array screen-cell) <- get screen, data - tmp <- multiply width - populate data-addr, tmp + var data-ah/edi: (addr handle array screen-cell) <- get screen, data + var capacity/eax: int <- copy width + capacity <- multiply height + populate data-ah, capacity + } + # if necessary, populate screen->pixels + { + compare pixel-graphics?, 0/false + break-if-= + var pixels-ah/edi: (addr handle array byte) <- get screen, pixels + var capacity/eax: int <- copy width + capacity <- shift-left 3/log2-font-width + capacity <- multiply height + capacity <- shift-left 4/log2-font-height + populate pixels-ah, capacity } - # allocate space for 16 pixels per 16x8 character. So one column of pixels - # per character. - var pixels-ah/ecx: (addr handle stream pixel) <- get screen, pixels - tmp <- shift-left 4 - populate-stream pixels-ah, tmp # screen->cursor-x = 0 dest <- get screen, cursor-x copy-to *dest, 0 @@ -136,7 +137,7 @@ fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int { abort "screen-cell-index: negative y" } { - var ymax/eax: (addr int) <- get screen, width + var ymax/eax: (addr int) <- get screen, height var ycurr/ecx: int <- copy y compare ycurr, *ymax break-if-< @@ -254,9 +255,8 @@ fn clear-screen _screen: (addr screen) { loop } set-cursor-position screen, 0, 0 - var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels - var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah - clear-stream dest-stream + var pixels-ah/eax: (addr handle array byte) <- get screen, pixels + var pixels/eax: (addr array byte) <- lookup *pixels-ah } fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean { @@ -285,11 +285,37 @@ fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean { y <- increment loop } - var pixels-ah/eax: (addr handle stream pixel) <- get screen, pixels - var pixels/eax: (addr stream pixel) <- lookup *pixels-ah - rewind-stream pixels - var result/eax: boolean <- stream-empty? pixels - return result + var pixels-ah/eax: (addr handle array byte) <- get screen, pixels + var pixels/eax: (addr array byte) <- lookup *pixels-ah + var y/ebx: int <- copy 0 + var height-addr/edx: (addr int) <- get screen, height + var height/edx: int <- copy *height-addr + height <- shift-left 4/log2-font-height + { + compare y, height + break-if->= + var width-addr/edx: (addr int) <- get screen, width + var width/edx: int <- copy *width-addr + width <- shift-left 3/log2-font-width + var x/edi: int <- copy 0 + { + compare x, width + break-if->= + var idx/ecx: int <- pixel-index screen, x, y + var color-addr/ecx: (addr byte) <- index pixels, idx + var color/ecx: byte <- copy-byte *color-addr + compare color, 0 + { + break-if-= + return 0/false + } + x <- increment + loop + } + y <- increment + loop + } + return 1/true } fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int { @@ -344,16 +370,16 @@ fn clear-real-screen { fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int { var y/eax: int <- copy ymin - y <- shift-left 4/log-font-height + y <- shift-left 4/log2-font-height var ymax/ecx: int <- copy ymax - ymax <- shift-left 4/log-font-height + ymax <- shift-left 4/log2-font-height { compare y, ymax break-if->= var x/edx: int <- copy xmin - x <- shift-left 3/log-font-width + x <- shift-left 3/log2-font-width var xmax/ebx: int <- copy xmax - xmax <- shift-left 3/log-font-width + xmax <- shift-left 3/log2-font-width { compare x, xmax break-if->= @@ -430,27 +456,52 @@ fn pixel screen: (addr screen), x: int, y: int, color: int { return } # fake screen - # prepare a pixel - var pixel-storage: pixel - var src/ecx: int <- copy x - var dest/edx: (addr int) <- get pixel-storage, x - copy-to *dest, src - src <- copy y - dest <- get pixel-storage, y - copy-to *dest, src - src <- copy color - dest <- get pixel-storage, color - copy-to *dest, src - # save it - var src/ecx: (addr pixel) <- address pixel-storage - var screen/eax: (addr screen) <- copy screen - var dest-stream-ah/eax: (addr handle stream pixel) <- get screen, pixels - var dest-stream/eax: (addr stream pixel) <- lookup *dest-stream-ah + var screen/esi: (addr screen) <- copy screen + var pixels-ah/eax: (addr handle array byte) <- get screen, pixels + var pixels/eax: (addr array byte) <- lookup *pixels-ah { - var full?/eax: boolean <- stream-full? dest-stream - compare full?, 0/false - break-if-= - abort "tried to draw too many pixels on the fake screen; adjust initialize-screen" + compare pixels, 0 + break-if-!= + abort "pixel graphics not enabled for this screen" } - write-to-stream dest-stream, src + var idx/ecx: int <- pixel-index screen, x, y + var dest/ecx: (addr byte) <- index pixels, idx + var src/eax: byte <- copy-byte color + copy-byte-to *dest, src +} + +fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int { + var screen/esi: (addr screen) <- copy _screen + { + compare x, 0 + break-if->= + abort "screen-cell-index: negative x" + } + { + var xmax-a/eax: (addr int) <- get screen, width + var xmax/eax: int <- copy *xmax-a + xmax <- shift-left 3/log2-font-width + compare x, xmax + break-if-< + abort "screen-cell-index: x too high" + } + { + compare y, 0 + break-if->= + abort "screen-cell-index: negative y" + } + { + var ymax-a/eax: (addr int) <- get screen, height + var ymax/eax: int <- copy *ymax-a + ymax <- shift-left 4/log2-font-height + compare y, ymax + break-if-< + abort "screen-cell-index: y too high" + } + var width-addr/eax: (addr int) <- get screen, width + var result/ecx: int <- copy y + result <- multiply *width-addr + result <- shift-left 3/log2-font-width + result <- add x + return result } diff --git a/shell/sandbox.mu b/shell/sandbox.mu index 64fb3fdd..7f3c13e2 100644 --- a/shell/sandbox.mu +++ b/shell/sandbox.mu @@ -293,31 +293,53 @@ fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int } # pixel data { - var left/ebx: int <- copy xmin - left <- add 1/margin-left - left <- shift-left 3/log-font-width - var top/edx: int <- copy ymin - top <- add 1/margin-top - top <- shift-left 4/log-font-height - var pixels-ah/esi: (addr handle stream pixel) <- get target-screen, pixels - var _pixels/eax: (addr stream pixel) <- lookup *pixels-ah - var pixels/esi: (addr stream pixel) <- copy _pixels - rewind-stream pixels + # screen top left pixels x y width height + var tmp/eax: int <- copy xmin + tmp <- add 1/margin-left + tmp <- shift-left 3/log2-font-width + var left: int + copy-to left, tmp + tmp <- copy ymin + tmp <- add 1/margin-top + tmp <- shift-left 4/log2-font-height + var top: int + copy-to top, tmp + var pixels-ah/eax: (addr handle array byte) <- get target-screen, pixels + var _pixels/eax: (addr array byte) <- lookup *pixels-ah + var pixels/edi: (addr array byte) <- copy _pixels + compare pixels, 0 + break-if-= + var y/ebx: int <- copy 0 + var height-addr/edx: (addr int) <- get target-screen, height + var height/edx: int <- copy *height-addr + height <- shift-left 4/log2-font-height { - var done?/eax: boolean <- stream-empty? pixels - compare done?, 0/false - break-if-!= - var curr-pixel: pixel - var curr-pixel-addr/eax: (addr pixel) <- address curr-pixel - read-from-stream pixels, curr-pixel-addr - var curr-x/eax: (addr int) <- get curr-pixel, x - var x/eax: int <- copy *curr-x - x <- add left - var curr-y/ecx: (addr int) <- get curr-pixel, y - var y/ecx: int <- copy *curr-y - y <- add top - var curr-color/edx: (addr int) <- get curr-pixel, color - pixel screen, x, y, *curr-color + compare y, height + break-if->= + var width-addr/edx: (addr int) <- get target-screen, width + var width/edx: int <- copy *width-addr + width <- shift-left 3/log2-font-width + var x/eax: int <- copy 0 + { + compare x, width + break-if->= + { + var idx/ecx: int <- pixel-index target-screen, x, y + var color-addr/ecx: (addr byte) <- index pixels, idx + var color/ecx: byte <- copy-byte *color-addr + var color2/ecx: int <- copy color + compare color2, 0 + break-if-= + var x2/eax: int <- copy x + x2 <- add left + var y2/ebx: int <- copy y + y2 <- add top + pixel screen, x2, y2, color2 + } + x <- increment + loop + } + y <- increment loop } } |