diff options
Diffstat (limited to 'linux/304screen.subx')
-rw-r--r-- | linux/304screen.subx | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/linux/304screen.subx b/linux/304screen.subx new file mode 100644 index 00000000..8a8df8f9 --- /dev/null +++ b/linux/304screen.subx @@ -0,0 +1,460 @@ +# Primitives for screen control. +# Require Linux and a modern terminal. + +== code + +enable-screen-grid-mode: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (flush Stdout) + (flush Stderr) + # switch to second screen buffer + (write 1 Esc) + (write 1 "[?1049h") + # + (clear-real-screen) +$enable-screen-grid-mode:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +enable-screen-type-mode: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # switch to first screen buffer + (write 1 Esc) + (write 1 "[?1049l") +$enable-screen-type-mode:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +real-screen-size: # -> nrows/eax: int, ncols/ecx: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 52/push-edx + 53/push-ebx + 56/push-esi + 57/push-edi + # + (_maybe-open-terminal) + # var window-size-info/esi: (addr winsize) + # winsize is a type from the Linux kernel. We don't care how large it is. + 81 5/subop/subtract %esp 0x40/imm32 + 89/<- %esi 4/r32/esp + # ioctl(*Terminal-file-descriptor, TIOCGWINSZ, window-size-info) + 89/<- %edx 6/r32/esi + b9/copy-to-ecx 0x5413/imm32/TIOCGWINSZ + 8b/-> *Terminal-file-descriptor 3/r32/ebx + e8/call syscall_ioctl/disp32 + # some bitworking to extract 2 16-bit shorts + 8b/-> *esi 0/r32/eax + 81 4/subop/and %eax 0xffff/imm32 + 8b/-> *esi 1/r32/ecx + c1/shift 5/subop/logical-right %ecx 0x10/imm8 +$real-screen-size:end: + # . reclaim locals + 81 0/subop/add %esp 0x40/imm32 + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +clear-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[H") + (write 1 Esc) + (write 1 "[2J") +$clear-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# row and col count from the top-left as (1, 1) +move-cursor-on-real-screen: # row: int, column: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var buf/ecx: (stream byte 32) + 81 5/subop/subtract %esp 0x20/imm32 + 68/push 0x20/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/<- %ecx 4/r32/esp + # construct directive in buf + (write %ecx Esc) + (write %ecx "[") + (write-int32-decimal %ecx *(ebp+8)) + (write %ecx ";") + (write-int32-decimal %ecx *(ebp+0xc)) + (write %ecx "H") + # flush + (write-stream 2 %ecx) +$move-cursor-on-real-screen:end: + # . reclaim locals + 81 0/subop/add %esp 0x2c/imm32 + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-string-to-real-screen: # s: (addr array byte) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 *(ebp+8)) +$print-string-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-slice-to-real-screen: # s: (addr slice) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write-slice-buffered Stdout *(ebp+8)) + (flush Stdout) +$print-slice-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-stream-to-real-screen: # s: (addr stream byte) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write-stream-data Stdout *(ebp+8)) + (flush Stdout) +$print-stream-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# print a grapheme in utf-8 (only up to 4 bytes so far) +print-grapheme-to-real-screen: # c: grapheme + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + # var curr/eax: byte = 0 + b8/copy-to-eax 0/imm32 + # curr = *(ebp+8) + 8a/byte-> *(ebp+8) 0/r32/al + # if (curr == 0) return + 3d/compare-eax-and 0/imm32 + 74/jump-if-= $print-grapheme-to-real-screen:end/disp8 + # + (print-byte-to-real-screen %eax) + # curr = *(ebp+9) + 8a/byte-> *(ebp+9) 0/r32/al + # if (curr == 0) return + 3d/compare-eax-and 0/imm32 + 74/jump-if-= $print-grapheme-to-real-screen:end/disp8 + # + (print-byte-to-real-screen %eax) + # curr = *(ebp+10) + 8a/byte-> *(ebp+0xa) 0/r32/al + # if (curr == 0) return + 3d/compare-eax-and 0/imm32 + 74/jump-if-= $print-grapheme-to-real-screen:end/disp8 + # + (print-byte-to-real-screen %eax) + # curr = *(ebp+11) + 8a/byte-> *(ebp+0xb) 0/r32/al + # if (curr == 0) return + 3d/compare-eax-and 0/imm32 + 74/jump-if-= $print-grapheme-to-real-screen:end/disp8 + # + (print-byte-to-real-screen %eax) +$print-grapheme-to-real-screen:end: + # . restore registers + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-byte-to-real-screen: # c: byte + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var s/ecx: (addr array byte) + ff 6/subop/push *(ebp+8) + 68/push 1/imm32/size + 89/<- %ecx 4/r32/esp + (write 1 %ecx) +$print-byte-to-real-screen:end: + # . reclaim locals + 81 0/subop/add %esp 8/imm32 + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-int32-hex-to-real-screen: # n: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write-int32-hex-buffered Stdout *(ebp+8)) + (flush Stdout) +$print-int32-hex-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-int32-hex-bits-to-real-screen: # n: int, bits: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write-int32-hex-bits-buffered Stdout *(ebp+8) *(ebp+0xc) *(ebp+0x10)) + (flush Stdout) +$print-int32-hex-bits-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +print-int32-decimal-to-real-screen: # n: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write-int32-decimal-buffered Stdout *(ebp+8)) + (flush Stdout) +$print-int32-decimal-to-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +write-int32-decimal-buffered: # f: (addr buffered-file), n: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var ecx: (stream byte 16) + 81 5/subop/subtract %esp 0x10/imm32 + 68/push 0x10/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/<- %ecx 4/r32/esp + (write-int32-decimal %ecx *(ebp+0xc)) + (write-stream-data *(ebp+8) %ecx) +$write-int32-decimal-buffered:end: + # . reclaim locals + 81 0/subop/add %esp 0x1c/imm32 + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +reset-formatting-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "(B") + (write 1 Esc) + (write 1 "[m") +$reset-formatting-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +start-color-on-real-screen: # fg: int, bg: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var buf/ecx: (stream byte 32) + 81 5/subop/subtract %esp 0x20/imm32 + 68/push 0x20/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/<- %ecx 4/r32/esp + # construct directive in buf + # . set fg + (write %ecx Esc) + (write %ecx "[38;5;") + (write-int32-decimal %ecx *(ebp+8)) + (write %ecx "m") + # . set bg + (write %ecx Esc) + (write %ecx "[48;5;") + (write-int32-decimal %ecx *(ebp+0xc)) + (write %ecx "m") + # flush + (write-stream 2 %ecx) +$start-color-on-real-screen:end: + # . reclaim locals + 81 0/subop/add %esp 0x2c/imm32 + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +start-bold-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[1m") +$start-bold-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +start-underline-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[4m") +$start-underline-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +start-reverse-video-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[7m") +$start-reverse-video-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# might require enabling blinking in your terminal program +start-blinking-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[5m") +$start-blinking-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +hide-cursor-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[?25l") +$hide-cursor-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +show-cursor-on-real-screen: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (write 1 Esc) + (write 1 "[?12l") + (write 1 Esc) + (write 1 "[?25h") +$show-cursor-on-real-screen:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# This is a low-level detail; I don't think everything should be a file. +# +# Open "/dev/tty" if necessary and cache its file descriptor in Terminal-file-descriptor +# where later primitives can use it. +_maybe-open-terminal: + 81 7/subop/compare *Terminal-file-descriptor -1/imm32 + 75/jump-if-!= $_maybe-open-terminal:epilogue/disp8 + # . save registers + 50/push-eax + 51/push-ecx + 53/push-ebx + # open("/dev/tty", O_RDWR) + bb/copy-to-ebx Terminal-filename/imm32 + b9/copy-to-ecx 2/imm32/O_RDWR + e8/call syscall_open/disp32 + 89/<- *Terminal-file-descriptor 0/r32/eax +$_maybe-open-terminal:end: + # . restore registers + 5b/pop-to-ebx + 59/pop-to-ecx + 58/pop-to-eax +$_maybe-open-terminal:epilogue: + c3/return + +== data + +Terminal-file-descriptor: # (addr int) + -1/imm32 + +Esc: # (addr array byte) + # size + 1/imm32 + # data + 0x1b + +Terminal-filename: # (addr kernel-string) + # "/dev/tty" + 2f/slash 64/d 65/e 76/v 2f/slash 74/t 74/t 79/y 0/nul + # on Linux console +#? # "/dev/console" +#? 2f/slash 64/d 65/e 76/v 2f/slash 63/c 6f/o 6e/n 73/s 6f/o 6c/l 65/e 0/nul |