1 # Primitives for screen control.
2 # Require Linux and a modern terminal.
6 enable-screen-grid-mode:
13 # switch to second screen buffer
18 $enable-screen-grid-mode:end:
24 enable-screen-type-mode:
28 # switch to first screen buffer
31 $enable-screen-type-mode:end:
37 real-screen-size: # -> nrows/eax: int, ncols/ecx: int
47 (_maybe-open-terminal)
48 # var window-size-info/esi: (addr winsize)
49 # winsize is a type from the Linux kernel. We don't care how large it is.
50 81 5/subop/subtract %esp 0x40/imm32
52 # ioctl(*Terminal-file-descriptor, TIOCGWINSZ, window-size-info)
54 b9/copy-to-ecx 0x5413/imm32/TIOCGWINSZ
55 8b/-> *Terminal-file-descriptor 3/r32/ebx
56 e8/call syscall_ioctl/disp32
57 # some bitworking to extract 2 16-bit shorts
59 25/and-eax-with 0xffff/imm32
61 c1/shift 5/subop/logical-right %ecx 0x10/imm8
62 $real-screen-size:end:
64 81 0/subop/add %esp 0x40/imm32
84 $clear-real-screen:end:
90 # row and col count from the top-left as (1, 1)
91 move-cursor-on-real-screen: # row: int, column: int
97 # var buf/ecx: (stream byte 32)
98 81 5/subop/subtract %esp 0x20/imm32
99 68/push 0x20/imm32/size
101 68/push 0/imm32/write
103 # construct directive in buf
106 (write-int32-decimal %ecx *(ebp+8))
108 (write-int32-decimal %ecx *(ebp+0xc))
111 (write-stream 2 %ecx)
112 $move-cursor-on-real-screen:end:
114 81 0/subop/add %esp 0x2c/imm32
115 # . restore registers
122 print-string-to-real-screen: # s: (addr array byte)
128 $print-string-to-real-screen:end:
134 print-slice-to-real-screen: # s: (addr slice)
139 (write-slice-buffered Stdout *(ebp+8))
141 $print-slice-to-real-screen:end:
147 print-stream-to-real-screen: # s: (addr stream byte)
152 (write-stream-data Stdout *(ebp+8))
154 $print-stream-to-real-screen:end:
160 # print a grapheme in utf-8 (only up to 4 bytes so far)
161 print-grapheme-to-real-screen: # c: grapheme
167 # var curr/eax: byte = 0
168 b8/copy-to-eax 0/imm32
170 8a/byte-> *(ebp+8) 0/r32/al
171 # if (curr == 0) return
172 3d/compare-eax-and 0/imm32
173 74/jump-if-= $print-grapheme-to-real-screen:end/disp8
175 (print-byte-to-real-screen %eax)
177 8a/byte-> *(ebp+9) 0/r32/al
178 # if (curr == 0) return
179 3d/compare-eax-and 0/imm32
180 74/jump-if-= $print-grapheme-to-real-screen:end/disp8
182 (print-byte-to-real-screen %eax)
184 8a/byte-> *(ebp+0xa) 0/r32/al
185 # if (curr == 0) return
186 3d/compare-eax-and 0/imm32
187 74/jump-if-= $print-grapheme-to-real-screen:end/disp8
189 (print-byte-to-real-screen %eax)
191 8a/byte-> *(ebp+0xb) 0/r32/al
192 # if (curr == 0) return
193 3d/compare-eax-and 0/imm32
194 74/jump-if-= $print-grapheme-to-real-screen:end/disp8
196 (print-byte-to-real-screen %eax)
197 $print-grapheme-to-real-screen:end:
198 # . restore registers
205 print-byte-to-real-screen: # c: byte
211 # var s/ecx: (addr array byte)
212 ff 6/subop/push *(ebp+8)
216 $print-byte-to-real-screen:end:
218 81 0/subop/add %esp 8/imm32
219 # . restore registers
226 print-int32-hex-to-real-screen: # n: int
231 (write-int32-hex-buffered Stdout *(ebp+8))
233 $print-int32-hex-to-real-screen:end:
239 print-int32-hex-bits-to-real-screen: # n: int, bits: int
244 (write-int32-hex-bits-buffered Stdout *(ebp+8) *(ebp+0xc) *(ebp+0x10))
246 $print-int32-hex-bits-to-real-screen:end:
252 print-int32-decimal-to-real-screen: # n: int
257 (write-int32-decimal-buffered Stdout *(ebp+8))
259 $print-int32-decimal-to-real-screen:end:
265 write-int32-decimal-buffered: # f: (addr buffered-file), n: int
271 # var ecx: (stream byte 16)
272 81 5/subop/subtract %esp 0x10/imm32
273 68/push 0x10/imm32/size
275 68/push 0/imm32/write
277 (write-int32-decimal %ecx *(ebp+0xc))
278 (write-stream-data *(ebp+8) %ecx)
279 $write-int32-decimal-buffered:end:
281 81 0/subop/add %esp 0x1c/imm32
282 # . restore registers
289 reset-formatting-on-real-screen:
298 $reset-formatting-on-real-screen:end:
304 start-color-on-real-screen: # fg: int, bg: int
310 # var buf/ecx: (stream byte 32)
311 81 5/subop/subtract %esp 0x20/imm32
312 68/push 0x20/imm32/size
314 68/push 0/imm32/write
316 # construct directive in buf
319 (write %ecx "[38;5;")
320 (write-int32-decimal %ecx *(ebp+8))
324 (write %ecx "[48;5;")
325 (write-int32-decimal %ecx *(ebp+0xc))
328 (write-stream 2 %ecx)
329 $start-color-on-real-screen:end:
331 81 0/subop/add %esp 0x2c/imm32
332 # . restore registers
339 start-bold-on-real-screen:
346 $start-bold-on-real-screen:end:
352 start-underline-on-real-screen:
359 $start-underline-on-real-screen:end:
365 start-reverse-video-on-real-screen:
372 $start-reverse-video-on-real-screen:end:
378 # might require enabling blinking in your terminal program
379 start-blinking-on-real-screen:
386 $start-blinking-on-real-screen:end:
392 hide-cursor-on-real-screen:
399 $hide-cursor-on-real-screen:end:
405 show-cursor-on-real-screen:
414 $show-cursor-on-real-screen:end:
420 # This is a low-level detail; I don't think everything should be a file.
422 # Open "/dev/tty" if necessary and cache its file descriptor in Terminal-file-descriptor
423 # where later primitives can use it.
424 _maybe-open-terminal:
425 81 7/subop/compare *Terminal-file-descriptor -1/imm32
426 75/jump-if-!= $_maybe-open-terminal:epilogue/disp8
431 # open("/dev/tty", O_RDWR)
432 bb/copy-to-ebx Terminal-filename/imm32
433 b9/copy-to-ecx 2/imm32/O_RDWR
434 e8/call syscall_open/disp32
435 89/<- *Terminal-file-descriptor 0/r32/eax
436 $_maybe-open-terminal:end:
437 # . restore registers
441 $_maybe-open-terminal:epilogue:
446 Terminal-file-descriptor: # (addr int)
449 Esc: # (addr array byte)
455 Terminal-filename: # (addr kernel-string)
457 2f/slash 64/d 65/e 76/v 2f/slash 74/t 74/t 79/y 0/nul
460 #? 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