e996502f01
Minor tweaks to get Mu shell running nicely on a Linux console atop Qemu. We also need to switch a few 256-color codes to 8-color mode. I'm not sure whether/how to patch the repo for those.
461 lines
10 KiB
Plaintext
461 lines
10 KiB
Plaintext
# 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
|