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.
This commit is contained in:
Kartik K. Agaram 2021-04-19 21:05:57 -07:00
parent c22874a97f
commit 34596b6ee9
2 changed files with 147 additions and 74 deletions

View File

@ -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
}

View File

@ -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
}
}