# 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 the font). # # 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 81 0/subop/add %esi Font/imm32 # 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 05/add-to-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 # Not a real `show-cursor` primitive: # - 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 draw-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) $draw-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 draw-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