diff --git a/html/103glyph.subx.html b/html/103glyph.subx.html index e80298ee..ec51fccd 100644 --- a/html/103glyph.subx.html +++ b/html/103glyph.subx.html @@ -57,369 +57,408 @@ if ('onhashchange' in window) {
1 # Use the built-in font to draw glyphs to screen. 2 # https://en.wikipedia.org/wiki/Glyph#Typography - 3 # The Mu computer can currently only render glyphs corresponding to single - 4 # code points. No combining characters. - 5 # https://en.wikipedia.org/wiki/Code_point - 6 # https://en.wikipedia.org/wiki/Combining_character - 7 # - 8 # We need to do this in machine code because Mu doesn't have global variables - 9 # yet (for the start of the font). - 10 - 11 == code - 12 - 13 # The Mu computer's screen is 1024px wide and 768px tall. - 14 # The Mu computer's font is 8px wide and 16px tall. - 15 # Therefore 'x' here is in [0, 128), and 'y' is in [0, 48) - 16 # Doesn't update the cursor; where the cursor should go after printing the - 17 # current code-point is a higher-level concern. - 18 draw-code-point-on-real-screen: # c: code-point, x: int, y: int, color: int, background-color: int -> _/eax - 19 # . prologue - 20 55/push-ebp - 21 89/<- %ebp 4/r32/esp - 22 # - 23 (draw-code-point-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0x80 0x30) # => eax - 24 $draw-code-point-on-real-screen:end: - 25 # . epilogue - 26 89/<- %esp 5/r32/ebp - 27 5d/pop-to-ebp - 28 c3/return - 29 - 30 draw-code-point-on-screen-array: # screen-data: (addr array byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int - 31 # . prologue - 32 55/push-ebp - 33 89/<- %ebp 4/r32/esp - 34 # . save registers - 35 51/push-ecx - 36 52/push-edx - 37 # if screen-width*screen-height > len(screen-data) abort - 38 { - 39 # ecx = len(screen-data) - 40 8b/-> *(ebp+8) 1/r32/ecx - 41 8b/-> *ecx 1/r32/ecx - 42 # eax = screen-width*screen-height - 43 ba/copy-to-edx 0/imm32 - 44 8b/-> *(ebp+0x20) 0/r32/eax - 45 f7 4/subop/multiply-into-eax *(ebp+0x24) - 46 81 7/subop/compare %edx 0/imm32 - 47 0f 85/jump-if-!= $draw-code-point-on-screen-array:overflow/disp32 - 48 # if (eax > ecx) abort - 49 39/compare %eax 1/r32/ecx - 50 0f 8f/jump-if-> $draw-code-point-on-screen-array:abort/disp32 - 51 } - 52 # eax = screen-data+4 (skip length) - 53 8b/-> *(ebp+8) 0/r32/eax - 54 05/add-to-eax 4/imm32 - 55 # - 56 (draw-code-point-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) # => eax - 57 $draw-code-point-on-screen-array:end: - 58 # . restore registers - 59 5a/pop-to-edx - 60 59/pop-to-ecx - 61 # . epilogue - 62 89/<- %esp 5/r32/ebp - 63 5d/pop-to-ebp - 64 c3/return - 65 - 66 $draw-code-point-on-screen-array:overflow: - 67 (abort "draw-code-point-on-screen-array: screen dimensions too large") - 68 - 69 $draw-code-point-on-screen-array:abort: - 70 (abort "draw-code-point-on-screen-array: coordinates are off the screen. Are the screen dimensions correct?") - 71 - 72 # 'buffer' here is not a valid Mu type: a naked address without a length. - 73 # returns number of 8x16 units printed to screen (1 or 2). - 74 draw-code-point-on-screen-buffer: # buffer: (addr byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int - 75 # . prologue - 76 55/push-ebp - 77 89/<- %ebp 4/r32/esp - 78 # . save registers - 79 56/push-esi - 80 # switch screen-width and screen-height from code-point to pixel units - 81 c1 4/subop/shift-left *(ebp+20) 3/imm8/log2-font-width - 82 c1 4/subop/shift-left *(ebp+24) 4/imm8/log2-font-height - 83 # esi = c - 84 8b/-> *(ebp+0xc) 6/r32/esi - 85 # if (c >= 4352) return # unicode planes supported: latin, greek, cyrillic, armenian, hebrew, arabic, syriac, thaana, n'ko, indian (iscii), sinhala, thai, lao, tibetan, myanmar, georgian - 86 # next few to support: CJK, ethiopic, cherokee, ... - 87 81 7/subop/compare %esi 0x1100/imm32=4352 - 88 0f 8d/jump-if->= $draw-code-point-on-screen-buffer:end/disp32 - 89 # var letter-bitmap/esi = font[c] - 90 69/multiply %esi 0x21/imm32/glyph-size 6/r32/esi - 91 81 0/subop/add %esi 0x0010000c/imm32/Font # see boot.subx - 92 # dispatch based on letter-bitmap->size - 93 b8/copy-to-eax 0/imm32 - 94 8a/byte-> *esi 0/r32/AL - 95 46/increment-esi # skip size - 96 3d/compare-eax-and 8/imm32 - 97 { - 98 75/jump-if-!= break/disp8 - 99 (draw-narrow-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -100 b8/copy-to-eax 1/imm32 -101 eb/jump $draw-code-point-on-screen-buffer:end/disp8 -102 } -103 (draw-wide-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -104 b8/copy-to-eax 2/imm32 -105 $draw-code-point-on-screen-buffer:end: -106 # . restore registers -107 5e/pop-to-esi -108 # . epilogue -109 89/<- %esp 5/r32/ebp -110 5d/pop-to-ebp -111 c3/return -112 -113 wide-code-point?: # c: code-point -> _/eax: boolean -114 # . prologue -115 55/push-ebp -116 89/<- %ebp 4/r32/esp -117 # eax = c -118 8b/-> *(ebp+8) 0/r32/eax -119 # if (c >= 128) return # characters beyond ASCII currently not supported -120 3d/compare-eax-and 0x80/imm32 -121 0f 8d/jump-if->= $wide-code-point?:end/disp32 -122 # var letter-bitmap/eax = font[c] -123 69/multiply %eax 0x21/imm32/glyph-size 0/r32/eax -124 05/add-to-eax 0x0010000c/imm32/Font # see boot.subx -125 # dispatch based on letter-bitmap->size -126 8a/byte-> *eax 0/r32/AL -127 25/and-eax-with 0xff/imm32 -128 3d/compare-eax-and 8/imm32 -129 0f 95/set-if-!= %eax -130 $wide-code-point?:end: -131 # . epilogue -132 89/<- %esp 5/r32/ebp -133 5d/pop-to-ebp -134 c3/return -135 -136 # buffer: naked address to raw screen RAM without a length -137 # letter-bitmap: naked address to 8-pixel wide font glyph -138 draw-narrow-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -139 # . prologue -140 55/push-ebp -141 89/<- %ebp 4/r32/esp -142 # . save registers -143 52/push-edx -144 53/push-ebx -145 56/push-esi -146 57/push-edi -147 # esi = letter-bitmap -148 8b/-> *(ebp+0xc) 6/r32/esi -149 # var ycurr/edx: int = y*16 -150 8b/-> *(ebp+0x14) 2/r32/edx -151 c1 4/subop/shift-left %edx 4/imm8 -152 # var ymax/edi: int = ycurr + 16 -153 8b/-> *(ebp+0x14) 7/r32/edi -154 c1 4/subop/shift-left %edi 4/imm8 -155 81 0/subop/add %edi 0x10/imm32 -156 { -157 # if (ycurr >= ymax) break -158 39/compare %edx 7/r32/edi -159 0f 8d/jump-if->= break/disp32 -160 # var row-bitmap/ebx: byte = *letter-bitmap -161 bb/copy-to-ebx 0/imm32 -162 8a/byte-> *esi 3/r32/BL -163 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx *(ebp+0x10) %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -164 # ++y -165 42/increment-edx -166 # next bitmap row -167 46/increment-esi -168 # -169 e9/jump loop/disp32 -170 } -171 $draw-narrow-code-point-on-screen-buffer:end: -172 # . restore registers -173 5f/pop-to-edi -174 5e/pop-to-esi -175 5b/pop-to-ebx -176 5a/pop-to-edx -177 # . epilogue -178 89/<- %esp 5/r32/ebp -179 5d/pop-to-ebp -180 c3/return -181 -182 # buffer: naked address to raw screen RAM without a length -183 # letter-bitmap: naked address to 16-pixel wide font glyph -184 draw-wide-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -185 # . prologue -186 55/push-ebp -187 89/<- %ebp 4/r32/esp -188 # . save registers -189 50/push-eax -190 51/push-ecx -191 52/push-edx -192 53/push-ebx -193 56/push-esi -194 57/push-edi -195 # esi = letter-bitmap -196 8b/-> *(ebp+0xc) 6/r32/esi -197 # -198 bb/copy-to-ebx 0/imm32 -199 # var ycurr/edx: int = y*16 -200 8b/-> *(ebp+0x14) 2/r32/edx -201 c1 4/subop/shift-left %edx 4/imm8 -202 # var ymax/edi: int = ycurr + 16 -203 8b/-> *(ebp+0x14) 7/r32/edi -204 c1 4/subop/shift-left %edi 4/imm8 -205 81 0/subop/add %edi 0x10/imm32 -206 { -207 # if (ycurr >= ymax) break -208 39/compare %edx 7/r32/edi -209 0f 8d/jump-if->= break/disp32 -210 # var row-bitmap/ebx: byte = *letter-bitmap -211 8a/byte-> *esi 3/r32/BL -212 # ecx = x -213 8b/-> *(ebp+0x10) 1/r32/ecx -214 # first half-row -215 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx %ecx %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -216 # second half-row -217 8a/byte-> *(esi+1) 3/r32/BL -218 41/increment-ecx -219 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx %ecx %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -220 # ++y -221 42/increment-edx -222 # next bitmap row -223 81 0/subop/add %esi 2/imm32 -224 # -225 e9/jump loop/disp32 -226 } -227 $draw-wide-code-point-on-screen-buffer:end: -228 # . restore registers -229 5f/pop-to-edi -230 5e/pop-to-esi -231 5b/pop-to-ebx -232 5a/pop-to-edx -233 59/pop-to-ecx -234 58/pop-to-eax -235 # . epilogue -236 89/<- %esp 5/r32/ebp -237 5d/pop-to-ebp -238 c3/return -239 -240 # draw 8 pixels from a single glyph byte in a font bitmap -241 draw-run-of-pixels-from-glyph: # buffer: (addr byte), glyph-byte: byte, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -242 # . prologue -243 55/push-ebp -244 89/<- %ebp 4/r32/esp -245 # . save registers -246 50/push-eax -247 51/push-ecx -248 56/push-esi -249 # esi = glyph-byte -250 8b/-> *(ebp+0xc) 6/r32/esi -251 # var xcurr/eax: int = x*8 + 7 -252 8b/-> *(ebp+0x10) 0/r32/eax -253 c1 4/subop/shift-left %eax 3/imm8 -254 05/add-to-eax 7/imm32 -255 # var xmin/ecx: int = x*8 -256 8b/-> *(ebp+0x10) 1/r32/ecx -257 c1 4/subop/shift-left %ecx 3/imm8 -258 { -259 # if (xcurr < xmin) break -260 39/compare %eax 1/r32/ecx -261 7c/jump-if-< break/disp8 -262 # shift LSB from row-bitmap into carry flag (CF) -263 c1 5/subop/shift-right-logical %esi 1/imm8 -264 # if LSB, draw a pixel in the given color -265 { -266 73/jump-if-not-CF break/disp8 -267 (pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18) *(ebp+0x20) *(ebp+0x24)) -268 eb/jump $draw-code-point-on-screen-buffer:continue/disp8 -269 } -270 # otherwise use the background color -271 (pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) -272 $draw-code-point-on-screen-buffer:continue: -273 # --x -274 48/decrement-eax -275 # -276 eb/jump loop/disp8 -277 } -278 $draw-run-of-pixels-from-glyph:end: -279 # . restore registers -280 5e/pop-to-esi -281 59/pop-to-ecx -282 58/pop-to-eax -283 # . epilogue -284 89/<- %esp 5/r32/ebp -285 5d/pop-to-ebp -286 c3/return -287 -288 cursor-position-on-real-screen: # -> _/eax: int, _/ecx: int -289 # . prologue -290 55/push-ebp -291 89/<- %ebp 4/r32/esp -292 # TODO: support fake screen; we currently assume 'screen' is always 0 (real) -293 8b/-> *Real-screen-cursor-x 0/r32/eax -294 8b/-> *Real-screen-cursor-y 1/r32/ecx -295 $cursor-position-on-real-screen:end: -296 # . epilogue -297 89/<- %esp 5/r32/ebp -298 5d/pop-to-ebp -299 c3/return -300 -301 set-cursor-position-on-real-screen: # x: int, y: int -302 # . prologue -303 55/push-ebp -304 89/<- %ebp 4/r32/esp -305 # . save registers -306 50/push-eax -307 # -308 8b/-> *(ebp+8) 0/r32/eax -309 89/<- *Real-screen-cursor-x 0/r32/eax -310 8b/-> *(ebp+0xc) 0/r32/eax -311 89/<- *Real-screen-cursor-y 0/r32/eax -312 $set-cursor-position-on-real-screen:end: -313 # . restore registers -314 58/pop-to-eax -315 # . epilogue -316 89/<- %esp 5/r32/ebp -317 5d/pop-to-ebp -318 c3/return -319 -320 # Not a real `show-cursor` primitive: -321 # - does not clear previous location cursor was shown at. -322 # - does not preserve what was at the cursor. Caller is responsible for -323 # tracking what was on the screen at this position before and passing it -324 # in again. -325 # - does not stop showing the cursor at this location when the cursor moves -326 draw-cursor-on-real-screen: # c: code-point -327 # . prologue -328 55/push-ebp -329 89/<- %ebp 4/r32/esp -330 # . save registers -331 50/push-eax -332 51/push-ecx -333 # -334 (cursor-position-on-real-screen) # => eax, ecx -335 (draw-code-point-on-real-screen *(ebp+8) %eax %ecx 0 7) # => eax -336 $draw-cursor-on-real-screen:end: -337 # . restore registers -338 59/pop-to-ecx -339 58/pop-to-eax -340 # . epilogue -341 89/<- %esp 5/r32/ebp -342 5d/pop-to-ebp -343 c3/return -344 -345 == data -346 -347 # The cursor is where certain Mu functions (usually of the form -348 # 'draw*cursor*') print to by default. -349 # -350 # We don't bother displaying the cursor when drawing. It only becomes visible -351 # on draw-cursor, which is quite rickety (see above) -352 # -353 # It's up to applications to manage cursor display: -354 # - clean up where it used to be -355 # - display the cursor before waiting for a key -356 # - ensure its location appropriately suggests the effect keystrokes will have -357 # - ensure its contents (and colors) appropriately reflect the state of the -358 # screen -359 # -360 # There's no blinking, etc. We aren't using any hardware-supported text mode -361 # here. -362 Real-screen-cursor-x: -363 0/imm32 -364 Real-screen-cursor-y: -365 0/imm32 + 3 # Extremely hacky support for combining characters. + 4 # https://en.wikipedia.org/wiki/Code_point + 5 # https://en.wikipedia.org/wiki/Combining_character + 6 # All we support is drawing combining characters atop the same screen cell as + 7 # a single base code point. See the overlay? arguments below. + 8 # + 9 # We need to do this in machine code because Mu doesn't have global variables + 10 # yet (for the start of the font). + 11 + 12 == code + 13 + 14 # The Mu computer's screen is 1024px wide and 768px tall. + 15 # The Mu computer's font is 8px wide and 16px tall. + 16 # Therefore 'x' here is in [0, 128), and 'y' is in [0, 48) + 17 # Doesn't update the cursor; where the cursor should go after printing the + 18 # current code-point is a higher-level concern. + 19 draw-code-point-on-real-screen: # c: code-point, x: int, y: int, color: int, background-color: int -> _/eax + 20 # . prologue + 21 55/push-ebp + 22 89/<- %ebp 4/r32/esp + 23 # + 24 (draw-code-point-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0 0x80 0x30) # 0/no-overlay => eax + 25 $draw-code-point-on-real-screen:end: + 26 # . epilogue + 27 89/<- %esp 5/r32/ebp + 28 5d/pop-to-ebp + 29 c3/return + 30 + 31 overlay-code-point-on-real-screen: # c: code-point, x: int, y: int, color: int, background-color: int -> _/eax + 32 # . prologue + 33 55/push-ebp + 34 89/<- %ebp 4/r32/esp + 35 # + 36 (draw-code-point-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 1 0x80 0x30) # 1/overlay => eax + 37 $overlay-code-point-on-real-screen:end: + 38 # . epilogue + 39 89/<- %esp 5/r32/ebp + 40 5d/pop-to-ebp + 41 c3/return + 42 + 43 draw-code-point-on-screen-array: # screen-data: (addr array byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int + 44 # . prologue + 45 55/push-ebp + 46 89/<- %ebp 4/r32/esp + 47 # . save registers + 48 51/push-ecx + 49 52/push-edx + 50 # if screen-width*screen-height > len(screen-data) abort + 51 { + 52 # ecx = len(screen-data) + 53 8b/-> *(ebp+8) 1/r32/ecx + 54 8b/-> *ecx 1/r32/ecx + 55 # eax = screen-width*screen-height + 56 ba/copy-to-edx 0/imm32 + 57 8b/-> *(ebp+0x20) 0/r32/eax + 58 f7 4/subop/multiply-into-eax *(ebp+0x24) + 59 81 7/subop/compare %edx 0/imm32 + 60 0f 85/jump-if-!= $draw-code-point-on-screen-array:overflow/disp32 + 61 # if (eax > ecx) abort + 62 39/compare %eax 1/r32/ecx + 63 0f 8f/jump-if-> $draw-code-point-on-screen-array:abort/disp32 + 64 } + 65 # eax = screen-data+4 (skip length) + 66 8b/-> *(ebp+8) 0/r32/eax + 67 05/add-to-eax 4/imm32 + 68 # + 69 (draw-code-point-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) # => eax + 70 $draw-code-point-on-screen-array:end: + 71 # . restore registers + 72 5a/pop-to-edx + 73 59/pop-to-ecx + 74 # . epilogue + 75 89/<- %esp 5/r32/ebp + 76 5d/pop-to-ebp + 77 c3/return + 78 + 79 $draw-code-point-on-screen-array:overflow: + 80 (abort "draw-code-point-on-screen-array: screen dimensions too large") + 81 + 82 $draw-code-point-on-screen-array:abort: + 83 (abort "draw-code-point-on-screen-array: coordinates are off the screen. Are the screen dimensions correct?") + 84 + 85 # 'buffer' here is not a valid Mu type: a naked address without a length. + 86 # returns number of 8x16 units printed to screen (1 or 2). + 87 draw-code-point-on-screen-buffer: # buffer: (addr byte), c: code-point, x: int, y: int, color: int, background-color: int, overlay?: boolean, screen-width: int, screen-height: int -> _/eax: int + 88 # . prologue + 89 55/push-ebp + 90 89/<- %ebp 4/r32/esp + 91 # . save registers + 92 56/push-esi + 93 # switch screen-width and screen-height from code-point to pixel units + 94 c1 4/subop/shift-left *(ebp+24) 3/imm8/log2-font-width + 95 c1 4/subop/shift-left *(ebp+28) 4/imm8/log2-font-height + 96 # esi = c + 97 8b/-> *(ebp+0xc) 6/r32/esi + 98 # if (c >= 4352) return # unicode planes supported: latin, greek, cyrillic, armenian, hebrew, arabic, syriac, thaana, n'ko, indian (iscii), sinhala, thai, lao, tibetan, myanmar, georgian + 99 # next few to support: CJK, ethiopic, cherokee, ... +100 81 7/subop/compare %esi 0x1100/imm32/4352 +101 0f 8d/jump-if->= $draw-code-point-on-screen-buffer:end/disp32 +102 # var letter-bitmap/esi = font[c] +103 69/multiply %esi 0x22/imm32/glyph-size 6/r32/esi +104 81 0/subop/add %esi 0x0010000c/imm32/Font # see boot.subx +105 # dispatch based on letter-bitmap->size +106 b8/copy-to-eax 0/imm32 +107 8a/byte-> *esi 0/r32/AL +108 46/increment-esi # skip size +109 46/increment-esi # skip size +110 3d/compare-eax-and 8/imm32 +111 { +112 75/jump-if-!= break/disp8 +113 (draw-narrow-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24) *(ebp+0x28)) +114 b8/copy-to-eax 1/imm32 +115 eb/jump $draw-code-point-on-screen-buffer:end/disp8 +116 } +117 (draw-wide-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24) *(ebp+0x28)) +118 b8/copy-to-eax 2/imm32 +119 $draw-code-point-on-screen-buffer:end: +120 # . restore registers +121 5e/pop-to-esi +122 # . epilogue +123 89/<- %esp 5/r32/ebp +124 5d/pop-to-ebp +125 c3/return +126 +127 wide-code-point?: # c: code-point -> _/eax: boolean +128 # . prologue +129 55/push-ebp +130 89/<- %ebp 4/r32/esp +131 # eax = c +132 8b/-> *(ebp+8) 0/r32/eax +133 # if (c >= 128) return # characters beyond ASCII currently not supported +134 3d/compare-eax-and 0x80/imm32 +135 0f 8d/jump-if->= $wide-code-point?:end/disp32 +136 # var letter-bitmap/eax = font[c] +137 69/multiply %eax 0x22/imm32/glyph-size 0/r32/eax +138 05/add-to-eax 0x0010000c/imm32/Font # see boot.subx +139 # dispatch based on letter-bitmap->size +140 8a/byte-> *eax 0/r32/AL +141 25/and-eax-with 0xff/imm32 +142 3d/compare-eax-and 8/imm32 +143 0f 95/set-if-!= %eax +144 $wide-code-point?:end: +145 # . epilogue +146 89/<- %esp 5/r32/ebp +147 5d/pop-to-ebp +148 c3/return +149 +150 combining-code-point?: # c: code-point -> _/eax: boolean +151 # . prologue +152 55/push-ebp +153 89/<- %ebp 4/r32/esp +154 # eax = c +155 8b/-> *(ebp+8) 0/r32/eax +156 # if (c >= 128) return # characters beyond ASCII currently not supported +157 3d/compare-eax-and 0x80/imm32 +158 0f 8d/jump-if->= $combining-code-point?:end/disp32 +159 # var letter-bitmap/eax = font[c] +160 69/multiply %eax 0x22/imm32/glyph-size 0/r32/eax +161 05/add-to-eax 0x0010000c/imm32/Font # see boot.subx +162 # dispatch based on letter-bitmap->is-combine? +163 8a/byte-> *(eax+1) 0/r32/AL +164 25/and-eax-with 0xff/imm32 +165 $combining-code-point?:end: +166 # . epilogue +167 89/<- %esp 5/r32/ebp +168 5d/pop-to-ebp +169 c3/return +170 +171 # buffer: naked address to raw screen RAM without a length +172 # letter-bitmap: naked address to 8-pixel wide font glyph +173 draw-narrow-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, overlay?: boolean, screen-width: int, screen-height: int +174 # . prologue +175 55/push-ebp +176 89/<- %ebp 4/r32/esp +177 # . save registers +178 52/push-edx +179 53/push-ebx +180 56/push-esi +181 57/push-edi +182 # esi = letter-bitmap +183 8b/-> *(ebp+0xc) 6/r32/esi +184 # var ycurr/edx: int = y*16 +185 8b/-> *(ebp+0x14) 2/r32/edx +186 c1 4/subop/shift-left %edx 4/imm8 +187 # var ymax/edi: int = ycurr + 16 +188 8b/-> *(ebp+0x14) 7/r32/edi +189 c1 4/subop/shift-left %edi 4/imm8 +190 81 0/subop/add %edi 0x10/imm32 +191 { +192 # if (ycurr >= ymax) break +193 39/compare %edx 7/r32/edi +194 0f 8d/jump-if->= break/disp32 +195 # var row-bitmap/ebx: byte = *letter-bitmap +196 bb/copy-to-ebx 0/imm32 +197 8a/byte-> *esi 3/r32/BL +198 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx *(ebp+0x10) %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24) *(ebp+0x28)) +199 # ++y +200 42/increment-edx +201 # next bitmap row +202 46/increment-esi +203 # +204 e9/jump loop/disp32 +205 } +206 $draw-narrow-code-point-on-screen-buffer:end: +207 # . restore registers +208 5f/pop-to-edi +209 5e/pop-to-esi +210 5b/pop-to-ebx +211 5a/pop-to-edx +212 # . epilogue +213 89/<- %esp 5/r32/ebp +214 5d/pop-to-ebp +215 c3/return +216 +217 # buffer: naked address to raw screen RAM without a length +218 # letter-bitmap: naked address to 16-pixel wide font glyph +219 draw-wide-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, overlay?: boolean, screen-width: int, screen-height: int +220 # . prologue +221 55/push-ebp +222 89/<- %ebp 4/r32/esp +223 # . save registers +224 50/push-eax +225 51/push-ecx +226 52/push-edx +227 53/push-ebx +228 56/push-esi +229 57/push-edi +230 # esi = letter-bitmap +231 8b/-> *(ebp+0xc) 6/r32/esi +232 # +233 bb/copy-to-ebx 0/imm32 +234 # var ycurr/edx: int = y*16 +235 8b/-> *(ebp+0x14) 2/r32/edx +236 c1 4/subop/shift-left %edx 4/imm8 +237 # var ymax/edi: int = ycurr + 16 +238 8b/-> *(ebp+0x14) 7/r32/edi +239 c1 4/subop/shift-left %edi 4/imm8 +240 81 0/subop/add %edi 0x10/imm32 +241 { +242 # if (ycurr >= ymax) break +243 39/compare %edx 7/r32/edi +244 0f 8d/jump-if->= break/disp32 +245 # var row-bitmap/ebx: byte = *letter-bitmap +246 8a/byte-> *esi 3/r32/BL +247 # ecx = x +248 8b/-> *(ebp+0x10) 1/r32/ecx +249 # first half-row +250 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx %ecx %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24) *(ebp+0x28)) +251 # second half-row +252 8a/byte-> *(esi+1) 3/r32/BL +253 41/increment-ecx +254 (draw-run-of-pixels-from-glyph *(ebp+8) %ebx %ecx %edx *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24) *(ebp+0x28)) +255 # ++y +256 42/increment-edx +257 # next bitmap row +258 81 0/subop/add %esi 2/imm32 +259 # +260 e9/jump loop/disp32 +261 } +262 $draw-wide-code-point-on-screen-buffer:end: +263 # . restore registers +264 5f/pop-to-edi +265 5e/pop-to-esi +266 5b/pop-to-ebx +267 5a/pop-to-edx +268 59/pop-to-ecx +269 58/pop-to-eax +270 # . epilogue +271 89/<- %esp 5/r32/ebp +272 5d/pop-to-ebp +273 c3/return +274 +275 # draw 8 pixels from a single glyph byte in a font bitmap +276 draw-run-of-pixels-from-glyph: # buffer: (addr byte), glyph-byte: byte, x: int, y: int, color: int, background-color: int, overlay?: boolean, screen-width: int, screen-height: int +277 # . prologue +278 55/push-ebp +279 89/<- %ebp 4/r32/esp +280 # . save registers +281 50/push-eax +282 51/push-ecx +283 56/push-esi +284 # esi = glyph-byte +285 8b/-> *(ebp+0xc) 6/r32/esi +286 # var xcurr/eax: int = x*8 + 7 +287 8b/-> *(ebp+0x10) 0/r32/eax +288 c1 4/subop/shift-left %eax 3/imm8 +289 05/add-to-eax 7/imm32 +290 # var xmin/ecx: int = x*8 +291 8b/-> *(ebp+0x10) 1/r32/ecx +292 c1 4/subop/shift-left %ecx 3/imm8 +293 { +294 # if (xcurr < xmin) break +295 39/compare %eax 1/r32/ecx +296 7c/jump-if-< break/disp8 +297 # shift LSB from row-bitmap into carry flag (CF) +298 c1 5/subop/shift-right-logical %esi 1/imm8 +299 # if LSB, draw a pixel in the given color +300 { +301 73/jump-if-not-CF break/disp8 +302 (pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18) *(ebp+0x24) *(ebp+0x28)) +303 eb/jump $draw-code-point-on-screen-buffer:continue/disp8 +304 } +305 # otherwise use the background color (except when overlay?) +306 { +307 81 7/subop/compare *(ebp+0x20) 0/imm32/false +308 75/jump-if-!= break/disp8 +309 (pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x1c) *(ebp+0x24) *(ebp+0x28)) +310 } +311 $draw-code-point-on-screen-buffer:continue: +312 # --x +313 48/decrement-eax +314 # +315 eb/jump loop/disp8 +316 } +317 $draw-run-of-pixels-from-glyph:end: +318 # . restore registers +319 5e/pop-to-esi +320 59/pop-to-ecx +321 58/pop-to-eax +322 # . epilogue +323 89/<- %esp 5/r32/ebp +324 5d/pop-to-ebp +325 c3/return +326 +327 cursor-position-on-real-screen: # -> _/eax: int, _/ecx: int +328 # . prologue +329 55/push-ebp +330 89/<- %ebp 4/r32/esp +331 # TODO: support fake screen; we currently assume 'screen' is always 0 (real) +332 8b/-> *Real-screen-cursor-x 0/r32/eax +333 8b/-> *Real-screen-cursor-y 1/r32/ecx +334 $cursor-position-on-real-screen:end: +335 # . epilogue +336 89/<- %esp 5/r32/ebp +337 5d/pop-to-ebp +338 c3/return +339 +340 set-cursor-position-on-real-screen: # x: int, y: int +341 # . prologue +342 55/push-ebp +343 89/<- %ebp 4/r32/esp +344 # . save registers +345 50/push-eax +346 # +347 8b/-> *(ebp+8) 0/r32/eax +348 89/<- *Real-screen-cursor-x 0/r32/eax +349 8b/-> *(ebp+0xc) 0/r32/eax +350 89/<- *Real-screen-cursor-y 0/r32/eax +351 $set-cursor-position-on-real-screen:end: +352 # . restore registers +353 58/pop-to-eax +354 # . epilogue +355 89/<- %esp 5/r32/ebp +356 5d/pop-to-ebp +357 c3/return +358 +359 # Not a real `show-cursor` primitive: +360 # - does not clear previous location cursor was shown at. +361 # - does not preserve what was at the cursor. Caller is responsible for +362 # tracking what was on the screen at this position before and passing it +363 # in again. +364 # - does not stop showing the cursor at this location when the cursor moves +365 draw-cursor-on-real-screen: # c: code-point +366 # . prologue +367 55/push-ebp +368 89/<- %ebp 4/r32/esp +369 # . save registers +370 50/push-eax +371 51/push-ecx +372 # +373 (cursor-position-on-real-screen) # => eax, ecx +374 (draw-code-point-on-real-screen *(ebp+8) %eax %ecx 0 7) # => eax +375 $draw-cursor-on-real-screen:end: +376 # . restore registers +377 59/pop-to-ecx +378 58/pop-to-eax +379 # . epilogue +380 89/<- %esp 5/r32/ebp +381 5d/pop-to-ebp +382 c3/return +383 +384 == data +385 +386 # The cursor is where certain Mu functions (usually of the form +387 # 'draw*cursor*') print to by default. +388 # +389 # We don't bother displaying the cursor when drawing. It only becomes visible +390 # on draw-cursor, which is quite rickety (see above) +391 # +392 # It's up to applications to manage cursor display: +393 # - clean up where it used to be +394 # - display the cursor before waiting for a key +395 # - ensure its location appropriately suggests the effect keystrokes will have +396 # - ensure its contents (and colors) appropriately reflect the state of the +397 # screen +398 # +399 # There's no blinking, etc. We aren't using any hardware-supported text mode +400 # here. +401 Real-screen-cursor-x: +402 0/imm32 +403 Real-screen-cursor-y: +404 0/imm32