about summary refs log tree commit diff stats
path: root/103grapheme.subx
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-08-29 00:01:08 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-08-29 00:01:08 -0700
commit8e182e394e492b9ff157dc88837dee894893c1ee (patch)
tree654d31f3ff130f9d23ecf12d36500612f6402f77 /103grapheme.subx
parentbc859a7ca4713b290fa9d7dea187fde55568ab29 (diff)
downloadmu-8e182e394e492b9ff157dc88837dee894893c1ee.tar.gz
width-aware drawing primitives
No support yet for drawing wide graphemes.
Diffstat (limited to '103grapheme.subx')
-rw-r--r--103grapheme.subx103
1 files changed, 90 insertions, 13 deletions
diff --git a/103grapheme.subx b/103grapheme.subx
index fa3b17d4..67e34ca1 100644
--- a/103grapheme.subx
+++ b/103grapheme.subx
@@ -10,24 +10,23 @@
 # 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
+draw-grapheme-on-real-screen:  # g: grapheme, x: int, y: int, color: int, background-color: int -> _/eax
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
     #
-    (draw-grapheme-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0x80 0x30)
+    (draw-grapheme-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0x80 0x30)  # => eax
 $draw-grapheme-on-real-screen:end:
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
     c3/return
 
-draw-grapheme-on-screen-array:  # screen-data: (addr array byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
+draw-grapheme-on-screen-array:  # screen-data: (addr array byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
     # . save registers
-    50/push-eax
     51/push-ecx
     52/push-edx
     # if screen-width*screen-height > len(screen-data) abort
@@ -49,12 +48,11 @@ draw-grapheme-on-screen-array:  # screen-data: (addr array byte), g: grapheme, x
     8b/-> *(ebp+8) 0/r32/eax
     05/add-to-eax 4/imm32
     #
-    (draw-grapheme-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
+    (draw-grapheme-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))  # => eax
 $draw-grapheme-on-screen-array:end:
     # . restore registers
     5a/pop-to-edx
     59/pop-to-ecx
-    58/pop-to-eax
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -67,15 +65,12 @@ $draw-grapheme-on-screen-array:abort:
     (abort "draw-grapheme-on-screen-array: coordinates are off the screen. Are the screen dimensions correct?")
 
 # 'buffer' here is not a valid Mu type: a naked address without a length.
-draw-grapheme-on-screen-buffer:  # buffer: (addr byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
+# returns number of 8x16 units printed to screen (1 or 2).
+draw-grapheme-on-screen-buffer:  # buffer: (addr byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: 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
     # switch screen-width and screen-height from grapheme to pixel units
     c1 4/subop/shift-left *(ebp+20) 3/imm8/log2-font-width
@@ -88,7 +83,64 @@ draw-grapheme-on-screen-buffer:  # buffer: (addr byte), g: grapheme, x: int, y:
     # var letter-bitmap/esi = font[g]
     69/multiply %esi 0x21/imm32/glyph-size 6/r32/esi
     81 0/subop/add %esi Font/imm32
+    # dispatch based on letter-bitmap->size
+    b8/copy-to-eax 0/imm32
+    8a/byte-> *esi 0/r32/AL
     46/increment-esi  # skip size
+    3d/compare-eax-and 8/imm32
+    {
+      75/jump-if-!= break/disp8
+      (draw-narrow-grapheme-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
+      b8/copy-to-eax 1/imm32
+      eb/jump $draw-grapheme-on-screen-buffer:end/disp8
+    }
+    (draw-wide-grapheme-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
+    b8/copy-to-eax 2/imm32
+$draw-grapheme-on-screen-buffer:end:
+    # . restore registers
+    5e/pop-to-esi
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+wide-grapheme?:  # g: grapheme -> _/eax: boolean
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # eax = g
+    8b/-> *(ebp+8) 0/r32/eax
+    # if (g >= 128) return  # characters beyond ASCII currently not supported
+    3d/compare-eax-and 0x80/imm32
+    0f 8d/jump-if->= $wide-grapheme?:end/disp32
+    # var letter-bitmap/eax = font[g]
+    69/multiply %eax 0x21/imm32/glyph-size 0/r32/eax
+    05/add-to-eax Font/imm32
+    # dispatch based on letter-bitmap->size
+    8a/byte-> *eax 0/r32/AL
+    25/and-eax-with  0xff/imm32
+    3d/compare-eax-and 8/imm32
+    0f 95/set-if-!= %eax
+$wide-grapheme?:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+# buffer: naked address to raw screen RAM without a length
+# letter-bitmap: naked address to 8-pixel wide font glyph
+draw-narrow-grapheme-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
+    # . 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
+    # esi = letter-bitmap
+    8b/-> *(ebp+0xc) 6/r32/esi
     # var ycurr/edx: int = y*16
     8b/-> *(ebp+0x14) 2/r32/edx
     c1 4/subop/shift-left %edx 4/imm8
@@ -139,7 +191,32 @@ $draw-grapheme-on-screen-buffer:continue:
       #
       e9/jump loop/disp32
     }
-$draw-grapheme-on-screen-buffer:end:
+$draw-narrow-grapheme-on-screen-buffer: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
+
+# buffer: naked address to raw screen RAM without a length
+# letter-bitmap: naked address to 16-pixel wide font glyph
+draw-wide-grapheme-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
+    # . 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
+    # HERE
+$draw-wide-grapheme-on-screen-buffer:end:
     # . restore registers
     5e/pop-to-esi
     5b/pop-to-ebx
@@ -198,7 +275,7 @@ draw-cursor-on-real-screen:  # g: grapheme
     51/push-ecx
     #
     (cursor-position-on-real-screen)  # => eax, ecx
-    (draw-grapheme-on-real-screen *(ebp+8) %eax %ecx 0 7)
+    (draw-grapheme-on-real-screen *(ebp+8) %eax %ecx 0 7)  # => eax
 $draw-cursor-on-real-screen:end:
     # . restore registers
     59/pop-to-ecx