diff options
Diffstat (limited to '103grapheme.subx')
-rw-r--r-- | 103grapheme.subx | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/103grapheme.subx b/103grapheme.subx new file mode 100644 index 00000000..d26a0b58 --- /dev/null +++ b/103grapheme.subx @@ -0,0 +1,173 @@ +# Use the built-in font to draw a grapheme to real screen. +# +# We need to do this in machine code because Mu doesn't have global variables +# yet (for the start of video memory). +# +# There are uncomfortable assumptions baked in here about english/latin +# script. We convert the grid of pixels into a fixed-width grid of graphemes, +# which may not work well with other language families. + +== code + +# The Mu computer's screen is 1024px wide and 768px tall. +# The Mu computer's font is 8px wide and 16px tall. +# Therefore 'x' here is in [0, 128), and 'y' is in [0, 48) +# Doesn't update the cursor; where the cursor should go after printing the +# current grapheme is a higher-level concern. +draw-grapheme-on-real-screen: # g: grapheme, x: int, y: int, color: int, background-color: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + 56/push-esi + # var letter-bitmap/esi = font[g] + 8b/-> *(ebp+8) 6/r32/esi + c1 4/subop/shift-left %esi 4/imm8 + 8d/copy-address *(esi+0x8c00) 6/r32/esi # font-start + # if (letter-bitmap >= 0x9400) return # characters beyond ASCII currently not supported + 81 7/subop/compare %esi 0x9400/imm32 + 7d/jump-if->= $draw-grapheme-on-real-screen:end/disp8 + # var ycurr/edx: int = y*16 + 8b/-> *(ebp+0x10) 2/r32/edx + c1 4/subop/shift-left %edx 4/imm8 + # var ymax/ebx: int = ycurr + 16 + 8b/-> *(ebp+0x10) 3/r32/ebx + c1 4/subop/shift-left %ebx 4/imm8 + 81 0/subop/add %ebx 0x10/imm32 + { + # if (ycurr >= ymax) break + 39/compare %edx 3/r32/ebx + 7d/jump-if->= break/disp8 + # var xcurr/eax: int = x*8 + 7 + 8b/-> *(ebp+0xc) 0/r32/eax # font-width - 1 + c1 4/subop/shift-left %eax 3/imm8 + 81 0/subop/add %eax 7/imm32 + # var xmin/ecx: int = x*8 + 8b/-> *(ebp+0xc) 1/r32/ecx + c1 4/subop/shift-left %ecx 3/imm8 + # var row-bitmap/ebx: int = *letter-bitmap + 53/push-ebx + 8b/-> *esi 3/r32/ebx + { + # if (xcurr < xmin) break + 39/compare %eax 1/r32/ecx + 7c/jump-if-< break/disp8 + # shift LSB from row-bitmap into carry flag (CF) + c1 5/subop/shift-right-logical %ebx 1/imm8 + # if LSB, draw a pixel in the given color + { + 73/jump-if-not-CF break/disp8 + (pixel-on-real-screen %eax %edx *(ebp+0x14)) + eb/jump $draw-grapheme-on-real-screen:continue/disp8 + } + # otherwise use the background color + (pixel-on-real-screen %eax %edx *(ebp+0x18)) +$draw-grapheme-on-real-screen:continue: + # --x + 48/decrement-eax + # + eb/jump loop/disp8 + } + # reclaim row-bitmap + 5b/pop-to-ebx + # ++y + 42/increment-edx + # next bitmap row + 46/increment-esi + # + eb/jump loop/disp8 + } +$draw-grapheme-on-real-screen:end: + # . restore registers + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +cursor-position-on-real-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/-> *Real-screen-cursor-x 0/r32/eax + 8b/-> *Real-screen-cursor-y 1/r32/ecx +$cursor-position-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +set-cursor-position-on-real-screen: # x: int, y: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + # + 8b/-> *(ebp+8) 0/r32/eax + 89/<- *Real-screen-cursor-x 0/r32/eax + 8b/-> *(ebp+0xc) 0/r32/eax + 89/<- *Real-screen-cursor-y 0/r32/eax +$set-cursor-position-on-real-screen:end: + # . restore registers + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# Draw cursor at current location. But this is rickety: +# - does not clear previous location cursor was shown at. +# - does not preserve what was at the cursor. Caller is responsible for +# tracking what was on the screen at this position before and passing it +# in again. +# - does not stop showing the cursor at this location when the cursor moves +show-cursor-on-real-screen: # g: grapheme + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + # + (cursor-position-on-real-screen) # => eax, ecx + (draw-grapheme-on-real-screen *(ebp+8) %eax %ecx 0 7) +$show-cursor-on-real-screen:end: + # . restore registers + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +== data + +# The cursor is where certain Mu functions (usually of the form +# 'draw*cursor*') print to by default. +# +# We don't bother displaying the cursor when drawing. It only becomes visible +# on show-cursor, which is quite rickety (see above) +# +# It's up to applications to manage cursor display: +# - clean up where it used to be +# - display the cursor before waiting for a key +# - ensure its location appropriately suggests the effect keystrokes will have +# - ensure its contents (and colors) appropriately reflect the state of the +# screen +# +# There's no blinking, etc. We aren't using any hardware-supported text mode +# here. +Real-screen-cursor-x: + 0/imm32 +Real-screen-cursor-y: + 0/imm32 |