From f0931316ea2ce968b7c4117da6782bd3c2b13b18 Mon Sep 17 00:00:00 2001 From: d_m Date: Fri, 10 Nov 2023 11:44:37 -0500 Subject: [PATCH] Initial import --- .gitignore | 11 + README.md | 19 + cp437.tal | 259 +++++++++ determ.terminfo | 23 + term.c | 57 ++ term.py | 69 +++ term.tal | 1328 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1766 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cp437.tal create mode 100644 determ.terminfo create mode 100644 term.c create mode 100755 term.py create mode 100644 term.tal diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d446045 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# use glob syntax. +syntax: glob +*.pyc +*.pyo +*~ +TAGS +*.rom +.theme +.snarf +*.sym +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..0d9b9d9 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# determ + +terminal emulator for the uxn system. + +(TODO: improve this readme) + +## quick start + +``` +uxnasm term.tal term.rom +python.py term.py term.rom +``` + +or alternately: + +``` +gcc term.c -c term +./term term.rom +``` diff --git a/cp437.tal b/cp437.tal new file mode 100644 index 0000000..0d4998d --- /dev/null +++ b/cp437.tal @@ -0,0 +1,259 @@ +&nul ( null ) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 7e c3 81 a5 81 bd 99 c3 7e 00 00 00 00 00 00 + 00 7e ff ff db ff c3 e7 ff 7e 00 00 00 00 00 00 + 00 00 44 ee fe fe fe 7c 38 10 00 00 00 00 00 00 + 00 10 38 7c fe fe 7c 38 10 00 00 00 00 00 00 00 + 00 18 3c 3c ff e7 e7 18 18 7e 00 00 00 00 00 00 + 00 18 3c 7e ff ff 7e 18 18 7e 00 00 00 00 00 00 + 00 00 00 00 3c 7e 7e 3c 00 00 00 00 00 00 00 00 + ff ff ff ff c3 81 81 c3 ff ff ff ff 00 00 00 00 + 00 00 3c 7e 66 42 42 66 7e 3c 00 00 00 00 00 00 + ff ff c3 81 99 bd bd 99 81 c3 ff ff 00 00 00 00 + 00 3e 0e 3a 72 f8 cc cc cc 78 00 00 00 00 00 00 + 00 3c 66 66 66 3c 18 7e 18 18 00 00 00 00 00 00 + 00 1f 19 19 1f 18 18 78 f8 70 00 00 00 00 00 00 + 00 7f 63 7f 63 63 63 67 e7 e6 c0 00 00 00 00 00 + 00 00 18 db 7e e7 e7 7e db 18 00 00 00 00 00 00 + 00 80 c0 e0 f8 fe f8 e0 c0 80 00 00 00 00 00 00 + 00 02 06 0e 3e fe 3e 0e 06 02 00 00 00 00 00 00 + 00 18 3c 7e 18 18 18 7e 3c 18 00 00 00 00 00 00 + 00 66 66 66 66 66 00 00 66 66 00 00 00 00 00 00 + 00 7f db db db 7b 1b 1b 1b 1b 00 00 00 00 00 00 + 00 7e 63 30 3c 66 66 3c 0c c6 7e 00 00 00 00 00 + 00 00 00 00 00 00 00 fe fe fe 00 00 00 00 00 00 + 00 18 3c 7e 18 18 18 7e 3c 18 7e 00 00 00 00 00 + 00 18 3c 7e 18 18 18 18 18 18 00 00 00 00 00 00 + 00 18 18 18 18 18 18 7e 3c 18 00 00 00 00 00 00 + 00 00 00 18 0c fe 0c 18 00 00 00 00 00 00 00 00 + 00 00 00 30 60 fe 60 30 00 00 00 00 00 00 00 00 + 00 00 00 00 c0 c0 c0 fe 00 00 00 00 00 00 00 00 + 00 00 00 24 66 ff 66 24 00 00 00 00 00 00 00 00 +&rs ( record separator ) + 00 00 10 10 38 38 7c 7c fe fe 00 00 00 00 00 00 + 00 00 fe fe 7c 7c 38 38 10 10 00 00 00 00 00 00 +&space ( space ) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 30 78 78 78 30 30 00 30 30 00 00 00 00 00 00 + 00 66 66 66 24 00 00 00 00 00 00 00 00 00 00 00 + 00 6c 6c fe 6c 6c 6c fe 6c 6c 00 00 00 00 00 00 + 30 30 7c c0 c0 78 0c 0c f8 30 30 00 00 00 00 00 + 00 00 00 c4 cc 18 30 60 cc 8c 00 00 00 00 00 00 + 00 70 d8 d8 70 fa de cc dc 76 00 00 00 00 00 00 + 00 30 30 30 60 00 00 00 00 00 00 00 00 00 00 00 + 00 0c 18 30 60 60 60 30 18 0c 00 00 00 00 00 00 + 00 60 30 18 0c 0c 0c 18 30 60 00 00 00 00 00 00 + 00 00 00 66 3c ff 3c 66 00 00 00 00 00 00 00 00 + 00 00 00 18 18 7e 18 18 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 38 38 60 00 00 00 00 00 + 00 00 00 00 00 fe 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 38 38 00 00 00 00 00 00 + 00 00 02 06 0c 18 30 60 c0 80 00 00 00 00 00 00 + 00 7c c6 ce de d6 f6 e6 c6 7c 00 00 00 00 00 00 + 00 10 30 f0 30 30 30 30 30 fc 00 00 00 00 00 00 + 00 78 cc cc 0c 18 30 60 cc fc 00 00 00 00 00 00 + 00 78 cc 0c 0c 38 0c 0c cc 78 00 00 00 00 00 00 + 00 0c 1c 3c 6c cc fe 0c 0c 1e 00 00 00 00 00 00 + 00 fc c0 c0 c0 f8 0c 0c cc 78 00 00 00 00 00 00 + 00 38 60 c0 c0 f8 cc cc cc 78 00 00 00 00 00 00 + 00 fe c6 c6 06 0c 18 30 30 30 00 00 00 00 00 00 + 00 78 cc cc cc 78 cc cc cc 78 00 00 00 00 00 00 + 00 78 cc cc cc 7c 18 18 30 70 00 00 00 00 00 00 + 00 00 00 38 38 00 00 38 38 00 00 00 00 00 00 00 + 00 00 00 38 38 00 00 38 38 18 30 00 00 00 00 00 + 00 0c 18 30 60 c0 60 30 18 0c 00 00 00 00 00 00 + 00 00 00 00 7e 00 7e 00 00 00 00 00 00 00 00 00 + 00 60 30 18 0c 06 0c 18 30 60 00 00 00 00 00 00 + 00 78 cc 0c 18 30 30 00 30 30 00 00 00 00 00 00 + 00 7c c6 c6 de de de c0 c0 7c 00 00 00 00 00 00 + 00 30 78 cc cc cc fc cc cc cc 00 00 00 00 00 00 + 00 fc 66 66 66 7c 66 66 66 fc 00 00 00 00 00 00 + 00 3c 66 c6 c0 c0 c0 c6 66 3c 00 00 00 00 00 00 + 00 f8 6c 66 66 66 66 66 6c f8 00 00 00 00 00 00 + 00 fe 62 60 64 7c 64 60 62 fe 00 00 00 00 00 00 + 00 fe 66 62 64 7c 64 60 60 f0 00 00 00 00 00 00 + 00 3c 66 c6 c0 c0 ce c6 66 3e 00 00 00 00 00 00 + 00 cc cc cc cc fc cc cc cc cc 00 00 00 00 00 00 + 00 78 30 30 30 30 30 30 30 78 00 00 00 00 00 00 + 00 1e 0c 0c 0c 0c cc cc cc 78 00 00 00 00 00 00 + 00 e6 66 6c 6c 78 6c 6c 66 e6 00 00 00 00 00 00 + 00 f0 60 60 60 60 62 66 66 fe 00 00 00 00 00 00 + 00 c6 ee fe fe d6 c6 c6 c6 c6 00 00 00 00 00 00 + 00 c6 c6 e6 f6 fe de ce c6 c6 00 00 00 00 00 00 + 00 38 6c c6 c6 c6 c6 c6 6c 38 00 00 00 00 00 00 + 00 fc 66 66 66 7c 60 60 60 f0 00 00 00 00 00 00 + 00 38 6c c6 c6 c6 ce de 7c 0c 1e 00 00 00 00 00 + 00 fc 66 66 66 7c 6c 66 66 e6 00 00 00 00 00 00 + 00 78 cc cc c0 70 18 cc cc 78 00 00 00 00 00 00 + 00 fc b4 30 30 30 30 30 30 78 00 00 00 00 00 00 + 00 cc cc cc cc cc cc cc cc 78 00 00 00 00 00 00 + 00 cc cc cc cc cc cc cc 78 30 00 00 00 00 00 00 + 00 c6 c6 c6 c6 d6 d6 6c 6c 6c 00 00 00 00 00 00 + 00 cc cc cc 78 30 78 cc cc cc 00 00 00 00 00 00 + 00 cc cc cc cc 78 30 30 30 78 00 00 00 00 00 00 + 00 fe ce 98 18 30 60 62 c6 fe 00 00 00 00 00 00 + 00 3c 30 30 30 30 30 30 30 3c 00 00 00 00 00 00 + 00 00 80 c0 60 30 18 0c 06 02 00 00 00 00 00 00 + 00 3c 0c 0c 0c 0c 0c 0c 0c 3c 00 00 00 00 00 00 + 10 38 6c c6 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00 00 + 30 30 18 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + 00 e0 60 60 7c 66 66 66 66 dc 00 00 00 00 00 00 + 00 00 00 00 78 cc c0 c0 cc 78 00 00 00 00 00 00 + 00 1c 0c 0c 7c cc cc cc cc 76 00 00 00 00 00 00 + 00 00 00 00 78 cc fc c0 cc 78 00 00 00 00 00 00 + 00 38 6c 60 60 f8 60 60 60 f0 00 00 00 00 00 00 + 00 00 00 00 76 cc cc cc 7c 0c cc 78 00 00 00 00 + 00 e0 60 60 6c 76 66 66 66 e6 00 00 00 00 00 00 + 00 18 18 00 78 18 18 18 18 7e 00 00 00 00 00 00 + 00 0c 0c 00 3c 0c 0c 0c 0c cc cc 78 00 00 00 00 + 00 e0 60 60 66 6c 78 6c 66 e6 00 00 00 00 00 00 + 00 78 18 18 18 18 18 18 18 7e 00 00 00 00 00 00 + 00 00 00 00 fc d6 d6 d6 d6 c6 00 00 00 00 00 00 + 00 00 00 00 f8 cc cc cc cc cc 00 00 00 00 00 00 + 00 00 00 00 78 cc cc cc cc 78 00 00 00 00 00 00 + 00 00 00 00 dc 66 66 66 66 7c 60 f0 00 00 00 00 + 00 00 00 00 76 cc cc cc cc 7c 0c 1e 00 00 00 00 + 00 00 00 00 ec 6e 76 60 60 f0 00 00 00 00 00 00 + 00 00 00 00 78 cc 60 18 cc 78 00 00 00 00 00 00 + 00 00 20 60 fc 60 60 60 6c 38 00 00 00 00 00 00 + 00 00 00 00 cc cc cc cc cc 76 00 00 00 00 00 00 + 00 00 00 00 cc cc cc cc 78 30 00 00 00 00 00 00 + 00 00 00 00 c6 c6 d6 d6 6c 6c 00 00 00 00 00 00 + 00 00 00 00 c6 6c 38 38 6c c6 00 00 00 00 00 00 + 00 00 00 00 66 66 66 66 3c 0c 18 f0 00 00 00 00 + 00 00 00 00 fc 8c 18 60 c4 fc 00 00 00 00 00 00 + 00 1c 30 30 60 c0 60 30 30 1c 00 00 00 00 00 00 + 00 18 18 18 18 00 18 18 18 18 00 00 00 00 00 00 + 00 e0 30 30 18 0c 18 30 30 e0 00 00 00 00 00 00 + 00 73 da ce 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 10 38 6c c6 c6 fe 00 00 00 00 00 00 00 + 00 78 cc cc c0 c0 c0 cc cc 78 30 60 00 00 00 00 + 00 cc cc 00 cc cc cc cc cc 76 00 00 00 00 00 00 + 0c 18 30 00 78 cc fc c0 cc 78 00 00 00 00 00 00 + 30 78 cc 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + 00 cc cc 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + c0 60 30 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + 38 6c 6c 38 f8 0c 7c cc cc 76 00 00 00 00 00 00 + 00 00 00 00 78 cc c0 c0 cc 78 30 60 00 00 00 00 + 30 78 cc 00 78 cc fc c0 c0 7c 00 00 00 00 00 00 + 00 cc cc 00 78 cc fc c0 c0 7c 00 00 00 00 00 00 + c0 60 30 00 78 cc fc c0 c0 7c 00 00 00 00 00 00 + 00 6c 6c 00 78 18 18 18 18 7e 00 00 00 00 00 00 + 10 38 6c 00 78 18 18 18 18 7e 00 00 00 00 00 00 + 60 30 18 00 78 18 18 18 18 7e 00 00 00 00 00 00 + 00 cc 00 30 78 cc cc fc cc cc 00 00 00 00 00 00 + 78 cc cc 78 78 cc cc fc cc cc 00 00 00 00 00 00 + 0c 18 00 fc c4 c0 f8 c0 c4 fc 00 00 00 00 00 00 + 00 00 00 00 fe 1b 7f d8 d8 ef 00 00 00 00 00 00 + 00 3e 78 d8 d8 fe d8 d8 d8 de 00 00 00 00 00 00 + 30 78 cc 00 78 cc cc cc cc 78 00 00 00 00 00 00 + 00 cc cc 00 78 cc cc cc cc 78 00 00 00 00 00 00 + c0 60 30 00 78 cc cc cc cc 78 00 00 00 00 00 00 + 30 78 cc 00 cc cc cc cc cc 76 00 00 00 00 00 00 + c0 60 30 00 cc cc cc cc cc 76 00 00 00 00 00 00 + 00 66 66 00 66 66 66 66 3c 0c 18 f0 00 00 00 00 + 00 cc 00 78 cc cc cc cc cc 78 00 00 00 00 00 00 + cc 00 cc cc cc cc cc cc cc 78 00 00 00 00 00 00 + 00 00 00 00 78 cc dc ec cc 78 00 00 00 00 00 00 + 3c 66 60 60 60 fc 60 60 c0 fe 00 00 00 00 00 00 + 00 3a 6c ce d6 d6 d6 e6 6c b8 00 00 00 00 00 00 + 00 00 00 00 00 c6 6c 38 6c c6 00 00 00 00 00 00 + 0e 1b 18 18 7e 18 18 18 d8 70 00 00 00 00 00 00 + 0c 18 30 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + 0c 18 30 00 78 18 18 18 18 7e 00 00 00 00 00 00 + 0c 18 30 00 78 cc cc cc cc 78 00 00 00 00 00 00 + 0c 18 30 00 cc cc cc cc cc 76 00 00 00 00 00 00 + 00 76 dc 00 f8 cc cc cc cc cc 00 00 00 00 00 00 + 76 dc 00 c6 e6 f6 de ce c6 c6 00 00 00 00 00 00 + 00 78 cc cc 7e 00 fe 00 00 00 00 00 00 00 00 00 + 00 78 cc cc 78 00 fe 00 00 00 00 00 00 00 00 00 + 00 30 30 00 30 60 c0 c0 cc 78 00 00 00 00 00 00 + 00 38 44 ba aa ba b2 aa 44 38 00 00 00 00 00 00 + 00 00 00 00 00 fc 0c 0c 0c 00 00 00 00 00 00 00 + 00 62 e6 6c 78 30 6e c3 86 0c 1f 00 00 00 00 00 + 00 63 e6 6c 78 37 6f db b3 3f 03 00 00 00 00 00 + 00 30 30 00 30 30 78 78 78 30 00 00 00 00 00 00 + 00 00 00 00 33 66 cc cc 66 33 00 00 00 00 00 00 + 00 00 00 00 cc 66 33 33 66 cc 00 00 00 00 00 00 + 24 92 49 24 92 49 24 92 49 24 92 49 00 00 00 00 + 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 00 00 00 00 + 6d db b6 6d db b6 6d db b6 6d db b6 00 00 00 00 + 18 18 18 18 18 18 18 18 18 18 18 18 00 00 00 00 + 18 18 18 18 18 f8 18 18 18 18 18 18 00 00 00 00 + 0c 18 00 30 78 cc cc fc cc cc 00 00 00 00 00 00 + 78 cc 00 30 78 cc cc fc cc cc 00 00 00 00 00 00 + 60 30 00 30 78 cc cc fc cc cc 00 00 00 00 00 00 + 00 38 44 ba a2 a2 a2 ba 44 38 00 00 00 00 00 00 + 66 66 66 66 e6 06 06 e6 66 66 66 66 00 00 00 00 + 66 66 66 66 66 66 66 66 66 66 66 66 00 00 00 00 + 00 00 00 00 fe 06 06 e6 66 66 66 66 00 00 00 00 + 66 66 66 66 e6 06 06 fe 00 00 00 00 00 00 00 00 + 00 30 30 78 cc c0 c0 cc 78 30 30 00 00 00 00 00 + cc cc cc cc 78 fc 30 fc 30 30 00 00 00 00 00 00 + 00 00 00 00 00 f8 18 18 18 18 18 18 00 00 00 00 + 18 18 18 18 18 1f 00 00 00 00 00 00 00 00 00 00 + 18 18 18 18 18 ff 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 ff 18 18 18 18 18 18 00 00 00 00 + 18 18 18 18 18 1f 18 18 18 18 18 18 00 00 00 00 + 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00 00 + 18 18 18 18 18 ff 18 18 18 18 18 18 00 00 00 00 + 00 76 dc 00 78 0c 7c cc cc 76 00 00 00 00 00 00 + 76 dc 00 30 78 cc cc fc cc cc 00 00 00 00 00 00 + 66 66 66 66 67 60 60 7f 00 00 00 00 00 00 00 00 + 00 00 00 00 7f 60 60 67 66 66 66 66 00 00 00 00 + 66 66 66 66 e7 00 00 ff 00 00 00 00 00 00 00 00 + 00 00 00 00 ff 00 00 e7 66 66 66 66 00 00 00 00 + 66 66 66 66 67 60 60 67 66 66 66 66 00 00 00 00 + 00 00 00 00 ff 00 00 ff 00 00 00 00 00 00 00 00 + 66 66 66 66 e7 00 00 e7 66 66 66 66 00 00 00 00 + 00 00 00 00 00 c6 7c 6c 7c c6 00 00 00 00 00 00 + cc 30 d8 0c 06 7e c6 c6 c6 7c 00 00 00 00 00 00 + 00 f8 6c 66 66 f6 66 66 6c f8 00 00 00 00 00 00 + 78 cc 00 fc c4 c0 f8 c0 c4 fc 00 00 00 00 00 00 + 00 cc 00 fc c4 c0 f8 c0 c4 fc 00 00 00 00 00 00 + 60 30 00 fc c4 c0 f8 c0 c4 fc 00 00 00 00 00 00 + 00 f0 30 30 30 fc 00 00 00 00 00 00 00 00 00 00 + 18 30 00 78 30 30 30 30 30 78 00 00 00 00 00 00 + 78 cc 00 78 30 30 30 30 30 78 00 00 00 00 00 00 + 00 cc 00 78 30 30 30 30 30 78 00 00 00 00 00 00 + 18 18 18 18 18 f8 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 1f 18 18 18 18 18 18 00 00 00 00 + ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 + 00 00 00 00 00 00 ff ff ff ff ff ff 00 00 00 00 + 00 18 18 18 18 00 18 18 18 18 00 00 00 00 00 00 + 60 30 00 78 30 30 30 30 30 78 00 00 00 00 00 00 + ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 + 18 30 00 78 cc cc cc cc cc 78 00 00 00 00 00 00 + 00 78 cc cc d8 cc cc cc f8 c0 60 00 00 00 00 00 + 78 cc 00 78 cc cc cc cc cc 78 00 00 00 00 00 00 + 60 30 00 78 cc cc cc cc cc 78 00 00 00 00 00 00 + 00 76 dc 00 78 cc cc cc cc 78 00 00 00 00 00 00 + 76 dc 00 78 cc cc cc cc cc 78 00 00 00 00 00 00 + 00 00 00 00 66 66 66 66 66 7b 60 c0 00 00 00 00 + 00 00 e0 60 7c 66 66 7c 60 f0 00 00 00 00 00 00 + 00 f0 60 7c 66 66 66 7c 60 f0 00 00 00 00 00 00 + 18 30 00 cc cc cc cc cc cc 78 00 00 00 00 00 00 + 78 cc 00 cc cc cc cc cc cc 78 00 00 00 00 00 00 + 60 30 00 cc cc cc cc cc cc 78 00 00 00 00 00 00 + 06 0c 18 00 66 66 66 66 3c 0c 18 f0 00 00 00 00 + 18 30 00 cc cc cc 78 30 30 78 00 00 00 00 00 00 + 00 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0c 18 30 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 fc 00 00 00 00 00 00 00 00 00 00 + 00 00 30 30 fc 30 30 00 fc 00 00 00 00 00 00 00 + 00 00 00 00 00 f8 00 00 f8 00 00 00 00 00 00 00 + e0 33 66 3c f8 37 6f db b3 3f 03 00 00 00 00 00 + 00 7f db db db 7b 1b 1b 1b 1b 00 00 00 00 00 00 + 00 7e 63 30 3c 66 66 3c 0c c6 7e 00 00 00 00 00 + 00 00 30 30 00 fc 00 30 30 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 30 70 00 00 00 00 + 00 3c 66 66 66 3c 00 00 00 00 00 00 00 00 00 00 + 00 cc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 18 00 00 00 00 00 00 00 00 00 00 + 00 30 70 30 30 78 00 00 00 00 00 00 00 00 00 00 + 00 78 0c 38 0c 78 00 00 00 00 00 00 00 00 00 00 + 00 78 0c 18 30 7c 00 00 00 00 00 00 00 00 00 00 + 00 00 00 fc fc fc fc fc fc 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/determ.terminfo b/determ.terminfo new file mode 100644 index 0000000..58fbad2 --- /dev/null +++ b/determ.terminfo @@ -0,0 +1,23 @@ +# based on ansi +determ|quasi-ansi terminal without color, + am, mc5i, mir, msgr, xenl, + cols#80, it#8, lines#24, + acsc=+\020\,\021-\030.^Y0\333`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376, + bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J, + cr=\r, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, + cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, + cuu=\E[%p1%dA, cuu1=\E[A, dch=\E[%p1%dP, dch1=\E[P, + dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K, + el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG, ht=\E[I, hts=\EH, + ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, ind=\n, + indn=\E[%p1%dS, invis=\E[8m, kbs=^H, kcbt=\E[Z, kcub1=\E[D, + kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A, khome=\E[H, kich1=\E[L, + mc4=\E[4i, mc5=\E[5i, nel=\r\E[S, op=\E[39;49m, + rep=%p1%c\E[%p2%{1}%-%db, rev=\E[7m, rin=\E[%p1%dT, + rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m, + s0ds=\E(B, s1ds=\E)B, s2ds=\E*B, s3ds=\E+B, + setab=\E[4%p1%dm, setaf=\E[3%p1%dm, + sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m, + sgr0=\E[0;10m, smacs=\E[11m, smpch=\E[11m, smso=\E[7m, + smul=\E[4m, tbc=\E[3g, u6=\E[%i%d;%dR, u7=\E[6n, + u8=\E[?%[;0123456789]c, u9=\E[c, vpa=\E[%i%p1%dd, diff --git a/term.c b/term.c new file mode 100644 index 0000000..2c7c06e --- /dev/null +++ b/term.c @@ -0,0 +1,57 @@ +#include +#ifdef __APPLE__ +#include +#include +#else +#include +#endif +#include +#include +#include + +// compile with gcc term.c -lutil +int main(int argc, char **argv) { + if (argc < 2) { + printf("usage: %s ROM [LOGIN]\n", argv[0]); + return 1; + } + char *rom = argv[1]; // find term.rom + int login = argc > 2; // any extra arg signals login shell + + // detect the user's shell + char *shell = getenv("SHELL"); + if (shell == NULL) { + struct passwd *passwd = getpwuid(getuid()); + if (passwd != NULL) { + shell = passwd->pw_shell; + } + } + if (shell == NULL) { + shell = "/bin/sh"; + } + + // allocate a pty, fork, inititialize file descriptor + int fdm = -1; // allocate file descriptor + pid_t pid = forkpty(&fdm, NULL, NULL, NULL); + + if (pid < 0) { // failure + perror("fork failed"); + return 1; + } else if (pid == 0) { // child + setenv("TERM", "ansi", 1); + // execute shell + if (login) { + execlp(shell, shell, "-l", "-i", NULL); + } else { + execlp(shell, shell, NULL); + } + perror("exec bash failed"); + } else { // parent + struct winsize ws = {23, 80, 8, 12}; // rows, cols, xps, ypx + ioctl(fdm, TIOCSWINSZ, &ws); // set term window size + dup2(fdm, 0); // use fdm for stdin + dup2(fdm, 1); // use fdm for stdout + execlp("uxnemu", "uxnemu", rom, NULL); // exec uxnemu + perror("exec uxnemu failed"); + } +} diff --git a/term.py b/term.py new file mode 100755 index 0000000..0eea4b0 --- /dev/null +++ b/term.py @@ -0,0 +1,69 @@ +#/usr/bin/env python + +import fcntl +import os +import pty +import sys +import struct +import termios + +# return dimensions (cols x rows) +def load_dimensions(): + # default to 80x24 + dims = 80, 24 + + if not os.path.exists('.theme'): + return dims + + try: + with open('.theme', 'rb') as f: + data = f.read(8) + if len(data) < 8: + return dims + vals = struct.unpack('HHHBB', data) + x, y = int(vals[3]), int(vals[4]) + if x < 80 or y < 24 or x > 200 or y > 100: + print('invalid width/height: %d/%d' % (x, y)) + sys.exit(1) + dims = x, y + except Exception(e): + print('error in .theme file: %s' % e) + sys.exit(1) + return dims + +def main(): + + # check usage + args = sys.argv[1:] + if len(args) < 1: + print('usage: %s ROM') + print('') + print(' ROM: the rom file to launch') + sys.exit(1) + + # either detect dimensions from theme or use 80x24 + cols, rows = load_dimensions() + + # path to rom to run + rom = args[0] + + # fork with a new pty + pid, fd = pty.fork() + + if pid == 0: + # set TERM to something we can (mostly) handle + env = dict(os.environ) + env['TERM'] = 'ansi' + os.execvpe('bash', ['bash'], env) + else: + # set the terminal size + size = struct.pack("HHHH", rows, cols, 8, 12) + fcntl.ioctl(fd, termios.TIOCSWINSZ, size) + + # use fd for the terminals stdin/stdout + os.dup2(fd, sys.stdin.fileno()) + os.dup2(os.dup(fd), sys.stdout.fileno()) + os.execvp('uxnemu', ['uxnemu', rom] + args[1:]) + +if __name__ == "__main__": + main() diff --git a/term.tal b/term.tal new file mode 100644 index 0000000..d0289cf --- /dev/null +++ b/term.tal @@ -0,0 +1,1328 @@ +( term.tal ) + +( TODO: ) +( 3. need to implement scrolling regions ) +( 5. need draw-line word, and need to use it more ) +( a. on delete, CSI-P ) +( b. on insert ) +( c. etc. ) +( 6. add more ansi control seqs ) +( 9. support shift+arrow and alt+arrow ) +( 10. crawl has screen-clearing issues ) +( 11. cursor hiding for cmatrix ) +( 12. clean up super ugly selection code ) +( 15. blinking text? ) +( 16. status line in femto, etc. is weird *** major bug ) +( 17. determ.terminfo ) + +( ANSI sequences ) +( ) +( set attributes: ESC [ x ; ... m -> 0:reset 1:bright 2:dim 7:reverse ) +( get cursor position: ESC [ 6 n -> ESC [ $row ; $col R ) +( set insert: ESC [ 4 h ) +( set replace (def): ESC [ 4 l ) +( enable line wrap: ESC [ 7 h ) +( disable line wrap: ESC [ 7 l ) +( ) +( move cursor home: ESC [ H ) +( move cursor: ESC [ $row ; $col H ) +( move to column: ESC [ $n G ) +( move to row: ESC [ $n d ) +( move up: ESC [ $n A ) +( move down: ESC [ $n B ) +( move forward: ESC [ $n C ) +( move back: ESC [ $n D ) +( move forward n tabs ESC [ $n I ) +( ) +( erase from cursor to end of line: ESC [ K ) +( erase from start of line to cursor: ESC [ 1 K ) +( erase line: ESC [ 2 K ) +( erase from current line to bottom: ESC [ J ) +( erase from current line to top: ESC [ 1 J ) +( erase screen: ESC [ 2 J ) +( ) +( insert lines: ESC [ $n L ) +( delete n characters: ESC [ $n P ) +( insert n blank characters: ESC [ $n @ ) +( ) +( show cursor: ESC [ ? 25 h ) +( hide cursor: ESC [ ? 25 l ) +( set bracketed paste mode: ESC [ ? 2004 h ) +( unset bracketed paste mode: ESC [ ? 2004 l ) +( ) +( SEMI-SUPPORTED ) +( select G0 charset ($c) ESC lpar $c ) +( save cursor ESC 7 ) +( restore cursor ESC 8 ) +( ) +( NOT SUPPORTED YET: ) +( end alt charset ESC [ 10 m ) +( end alt charset ESC [ 11 m ) + +( ESC [ $top $bot r -> set scrolling region [$top;$bot] ) +( ESC [ 7 h/l -> set/unset auto-wrap mode ) +( ESC [ 1 h/l -> set/unset application cursor keys [up: CSI A vs SS3 A] ) +( ESC = -> application keypad [use SS3 sequences] ) +( ESC M -> set ANSI conformance level 2 ) +( ESC > -> normal keypad [normal sequences] ) + +( ESC [ ? 1000 h/l -> send mouse X & Y on button press and release (X11 xterm mouse protocol) ) +( ESC [ ? 1002 h/l -> use cell motion mouse tracking, xterm ) +( ESC [ ? 1006 h/l -> SGR mouse mode, xterm ) +( ESC [ ? 1005 h/l -> UTF-8 mouse mode, xterm ) +( ESC [ ? 1015 h/l -> urxvt Mouse mode ) +( ESC [ ? 1051 l -> unset sun function key mode ) +( ESC [ ? 1052 l -> unset hp function key mode ) +( ESC [ ? 1060 l -> unset legacy keyboard emulation ) +( ESC [ ? 1061 h -> set VT220 keyboard emulation ) + +|00 @System [ &vect $2 &expansion $2 &title $2 &metadata $2 &r $2 &g $2 &b $2 ] +|10 @Console [ &vect $2 &r $1 &exec $2 &mode $1 &dead $1 &exit $1 &w $1 ] +|20 @Screen [ &vect $2 &w $2 &h $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &px $1 &sprite $1 ] +|80 @Controller [ &vect $2 &button $1 &key $1 &fn $1 ] +|90 @Mouse [ &vect $2 &x $2 &y $2 &state $1 &pad $3 &scrollx $2 &scrolly $2 ] +|a0 @File1 [ &vect $2 &ok $2 &stat $2 &del $1 &append $1 &name $2 &len $2 &r $2 &w $2 ] +|b0 @File2 [ &vect $2 &ok $2 &stat $2 &del $1 &append $1 &name $2 &len $2 &r $2 &w $2 ] + +|0000 + @tint $1 ( draw mode. 01=regular, 04=inverted ) + @attr $1 ( 5 bits: RxxxBBFF ) + @dirty $1 ( screen needs redraw? ) + @lastkey $1 ( last button press ) + @rows $2 ( height in characters ) + @cols $2 ( width in characters ) + @cur-x $2 ( cursor x: 0 <= cur-x < cols ) + @cur-y $2 ( cursor y: 0 <= cur-y < rows ) + @cur-wrap $1 ( did cursor just wrap? ) + @max-x $2 ( cols-1 ) + @max-y $2 ( rows-1 ) + @saved-x $2 ( saved x coordinate ) + @saved-y $2 ( saved y coordinate ) + @col-bytes $2 ( 2*cols ) + @lastmouse-x $2 ( last mouse x ) + @lastmouse-y $2 ( last mouse y ) + @lastmouse-st $1 ( last mouse press ) + @is-lit $1 ( are we selecting an area? ) + @is-lit-flip $1 ( is the selection flipped? i.e. drawing left/up ) + @lit-click-x $2 ( x coord of starting selection click ) + @lit-click-y $2 ( y coord of starting selection click ) + @lit-drag-x $2 ( x coord of selection drag ) + @lit-drag-y $2 ( y coord of selection drag ) + @flash $1 ( visual bell flash timer ) + @pointer-ttl $1 ( visible cursor timer ) + + ( terminal settings ) + @ignored $1 ( ignored ) + @irm $1 ( 01: insert and move right, 00: replace and overwrite ) + @awm $1 ( 01: wrap chars at margin, 00: overwrite at margin ) + @tcem $1 ( 01: cursor is visible, 00: cursor is invisible ) + @paste $1 ( 01: bracketed paste is on, 00: is off ) + + ( user configuration ) + @debug $1 ( use debug log? ) + @show-banner $1 ( show banner on startup? ) + @visual-bell $1 ( flash visual bell? otherwise do nothing ) + @border-pad $2 ( use border? should be 0000 or 0010 ) + +|0100 + ( metadata ) + ;meta .System/metadata DEO2 + ;meta/name .System/title DEO2 + + ( user configuration defaults ) + #01 .debug STZ + #01 .show-banner STZ +( #0010 .border-pad STZ2 ) + #0000 .border-pad STZ2 + #01 .visual-bell STZ + + ( 80 cols x 24 rows by default ) + #0018 .rows STZ2 + #0050 .cols STZ2 + + ( start cursor at origin - including border ) + .border-pad LDZ2 .Screen/x DEO2 + .border-pad LDZ2 .Screen/y DEO2 + + ( set colors ) + #07bf .System/r DEO2 + #07bf .System/g DEO2 + #07bf .System/b DEO2 + + load-theme ( optional theme sets colors/dimensions ) + + ;on-redraw .Screen/vect DEO2 ( set up screen callback ) + ;on-key .Controller/vect DEO2 ( set up keyboard callback ) + ;on-mouse .Mouse/vect DEO2 ( set up mouse callback ) + ;on-read .Console/vect DEO2 ( set up stdin callback ) + + setup-subprocess ( set up experimental subprocess support ) + reset-terminal ( initialize terminal state and settings ) + setup-debugging ( set up debugging if requested ) + draw-banner ( draw banner if requested ) + + BRK + +( these only work with a patched uxnemu ) +( on other emulators they should be no-ops ) +@setup-subprocess ( -> ) + ;shell .Console/exec DEO2 ( set up bash subprocess ) + #80 .Console/mode DEO ( start bash subprocess ) + JMP2r + +@setup-debugging ( -> ) + .debug LDZ ?&continue JMP2r &continue +( #99 #010e DEO ) ( put 99 in wst so #010e DEO reliably logs ) + ;debug-log .File1/name DEO2 + #01 .File1/append DEO + JMP2r + +@draw-banner ( -> ) + redraw ;banner-ascii + &loop LDAk DUP ?&ok POP POP2 JMP2r + &ok read INC2 !&loop + +@reset-terminal ( -> ) + ( set initial cursor ) + #0000 .cur-x STZ2 + #0000 .cur-y STZ2 + + ( confirm no buttons pressed yet ) + #00 .lastkey STZ + + ( calculate derived dimensions from cols/rows ) + update-dimensions + + ( set starting tint: reverse=0, bg=0, fg=2 ) + #02 .attr STZ + update-tint + + ( set initial modes ) + #00 .irm STZ ( insert and move right ) + #01 .awm STZ ( wrap at margin ) + #01 .tcem STZ ( show cursor ) + #00 .paste STZ ( bracketed paste is off ) + + ( prepare for initial draw ) + init-screen + + ( draw border ) + .border-pad LDZ2 ORA ?draw-border + JMP2r + +@update-dimensions ( -> ) + ( set col-bytes, frequently needed ) + .cols LDZ2 DUP2 ADD2 .col-bytes STZ2 + + ( set max row/col ) + .rows LDZ2 #0001 SUB2 .max-y STZ2 + .cols LDZ2 #0001 SUB2 .max-x STZ2 + + ( set screen height/width based on rows/cols + border padding ) + .border-pad LDZ2 DUP2 ADD2 DUP2 + .cols LDZ2 #30 SFT2 ADD2 .Screen/w DEO2 + .rows LDZ2 #000c MUL2 ADD2 .Screen/h DEO2 + JMP2r + +@shell "bash 00 "-i 00 00 + +@load-theme ( -> ) + ;&path .File1/name DEO2 + #0006 .File1/len DEO2 + ;&r .File1/r DEO2 + .File1/ok DEI2 ORA #01 [ JCN JMP2r ] + ,&r LDR2 .System/r DEO2 + ,&g LDR2 .System/g DEO2 + ,&b LDR2 .System/b DEO2 + #0002 .File1/len DEO2 + ;&x .File1/r DEO2 + .File1/ok DEI2 ORA #01 [ JCN JMP2r ] + #00 ,&x LDR .cols STZ2 + #00 ,&y LDR .rows STZ2 + JMP2r [ &path ".theme $1 &r $2 &g $2 &b $2 &x $1 &y $1 ] + +@first-addr ( -> ) + ;cells JMP2r + +@bol-addr ( -> addr* ) + .col-bytes LDZ2 .cur-y LDZ2 MUL2 ;cells ADD2 JMP2r + +@cur-addr ( -> addr* ) + .col-bytes LDZ2 .cur-y LDZ2 MUL2 .cur-x LDZ2 DUP2 ADD2 ADD2 ;cells ADD2 JMP2r + +@eol-addr ( -> addr* ) + .col-bytes LDZ2 .cur-y LDZ2 INC2 MUL2 ;cells ADD2 JMP2r + +@limit-addr ( -> ) + .col-bytes LDZ2 .rows LDZ2 MUL2 ;cells ADD2 JMP2r + +@min ( x* y* -> min* ) + LTH2k [ JMP SWP2 ] POP2 JMP2r + +@max ( x* y* -> max* ) + LTH2k [ JMP SWP2 ] NIP2 JMP2r + +( signed max ) +( #8000 < #8001 < ... < #ffff < #0000 < #0001 < ... < #7fff ) +@smax ( x* y* -> min* ) + EOR2k POP #80 AND ?min !max + +( initialize screen cells and prepare for first draw ) +@init-screen ( -> ) + first-addr limit-addr #0200 ( fall-through ) +@init ( start* limit* cell* -> ) + STH2 EQU2k ?&skip ( start* limit* [cell*] ) + #01 .dirty STZ OVR2 ( start* limit* start* [cell*] ) + #01 SFT2 SWP2 #01 SFT2 SUB2 ( start* -count* [cell*] ) + STH2 SWP2r STH2r SWP2 ( cell* start* [-count*] ) + &loop ( cell* addr* [-i*] ) + STA2k INC2 INC2 INC2r ( cell* addr+2* [-i+1*] ) + ORAkr STHr ?&loop ( cell* addr+2* [-i+1*] ) + &skip POP2 POP2 POP2r JMP2r ( ) + +( uses the existing .Screen/x and .Screen/y ) +( returns them to their starting values when finished ) +@erase-fg-cell ( -> ) + #40 .Screen/sprite DEO ( ; s/s<-40 ) + .Screen/y DEI2k STH2k ( zp^ y* [y*] ) + #0004 ADD2 ROT DEO2 ( [y*] ; s/y<-y+4 ) + #40 .Screen/sprite DEO STH2r ( y* ; s/s<-40 ) + .Screen/y DEO2 JMP2r ( ; s/y<-y ) + +@draw-border ( -> ) + ;cp437/space .Screen/addr DEO2 + #04 .Screen/sprite + #0000 draw-border/row + #0008 draw-border/row + .rows LDZ2 #000c MUL2 #0010 ADD2 draw-border/row + .Screen/y DEI2 #0008 ADD2 draw-border/row + #0000 draw-border/col + #0008 draw-border/col + .cols LDZ2 #30 SFT2 #0010 ADD2 draw-border/col + .Screen/x DEI2 #0008 ADD2 draw-border/col + #00 .Screen/auto DEO POP2 !screen-to-cursor + + &row ( y* -> ) + .Screen/y DEO2 + #0000 .Screen/x DEO2 + #01 .Screen/auto DEO + #0000 .cols LDZ2 #0004 ADD2 SUB2 STH2 + !&loop + + &col ( x* -> ) + .Screen/x DEO2 + #0000 .Screen/y DEO2 + #02 .Screen/auto DEO + #0000 .rows LDZ2 #0003 MUL2 INC2 #01 SFT2 #0004 ADD2 SUB2 STH2 + !&loop + + &loop ( 04 sprite^ [-count] ) + DEOk INC2r STH2kr ORA ?&loop POP2r JMP2r + +@on-redraw ( -> ) + redraw BRK + +@redraw ( -> ) + .pointer-ttl LDZ #00 EQU ?&pointer-ok ( ) + .pointer-ttl LDZk INC DUP ROT STZ ?&pointer-ok + #01 .dirty STZ ( redraw without pointer ) + &pointer-ok + .dirty LDZ #00 EQU ?&done + LIT2r =cells ( [addr*] ) + .rows LDZ2 #0000 DUP2 .border-pad LDZ2 ADD2 .Screen/y DEO2 + &yloop + .cols LDZ2 #0000 DUP2 .border-pad LDZ2 ADD2 .Screen/x DEO2 + &xloop + STH2kr LDA2 draw-cell erase-fg-cell + .Screen/x DEI2k #0008 ( width ) ADD2 ROT DEO2 + INC2 INC2r INC2r GTH2k ?&xloop + POP2 POP2 + .Screen/y DEI2k #000c ( height ) ADD2 ROT DEO2 + INC2 GTH2k ?&yloop + POP2 POP2 POP2r + .is-lit LDZ #00 EQU ?&flashing redraw-selection !&finally + &flashing .flash LDZ #00 EQU ?&pointer flash-bell !draw-cursor + &pointer draw-pointer + &finally draw-cursor #00 .dirty STZ + &done JMP2r + +@flash-bell ( -> ) + .flash LDZk #01 SUB SWP STZ ( ; flash<-flash-1 ) + #0000 DUP2 .lit-click-x STZ2 .lit-click-y STZ2 + .max-x LDZ2 .lit-drag-x STZ2 .max-y LDZ2 .lit-drag-y STZ2 + redraw-selection !clear-selection + +@screen-to-cell ( row* col* -> ) + #30 SFT2 ( width ) .border-pad LDZ2 ADD2 .Screen/x DEO2 + #000c MUL2 ( height ) .border-pad LDZ2 ADD2 .Screen/y DEO2 + JMP2r + +@screen-to-cursor ( -> ) + .cur-y LDZ2 .cur-x LDZ2 !screen-to-cell + +@clear-cursor ( -> ) + screen-to-cursor cur-addr LDA2 !draw-cell + +@draw-cursor ( -> ) + screen-to-cursor cur-addr LDA2 + .tcem LDZ #00 EQU ?&skip SWP reverse-tint SWP + &skip !draw-cell + +@on-button ( -> BRK ) + .lastkey LDZ ( last^ ) + .Controller/button DEI ( last^ button^ ) + STHk EOR ( last-xor-button^ [button^] ) + STHr AND ( last-xor-button&button^ ) + DUP #10 AND #00 EQU ?&no-n LIT "A arrow + &no-n DUP #20 AND #00 EQU ?&no-s LIT "B arrow + &no-s DUP #40 AND #00 EQU ?&no-w LIT "D arrow + &no-w DUP #80 AND #00 EQU ?&no-e LIT "C arrow + &no-e POP .Controller/button DEI .lastkey STZ BRK + +( send ESC [ $c ) +@arrow ( c^ -> ) + .Console/w STH + #1b STHkr DEO LIT "[ STHkr DEO STHr DEO + JMP2r + +@paste-from-buf ( size* -> ) + ;paste-buf SWP2 OVR2 ADD2 SWP2 ( limit* start* ) + &loop ( limit* pos* ) + LDAk .Console/w DEO INC2 ( limit* pos+1* ) + GTH2k ?&loop POP2 POP2 JMP2r + +@bracket-paste ( c^ -> ) + .Console/w STH + #1b STHkr DEO + LIT "[ STHkr DEO + LIT "2 STHkr DEO + LIT "0 STHkr DEO + ( c ) STHkr DEO + LIT "~ STHr DEO + JMP2r + +@paste-snarf ( -> ) + .paste LDZ #00 EQU ?&start LIT "0 bracket-paste &start + ;snarf .File2/name DEO2 ( ) + #0780 .File2/len DEO2 ( ) + &loop ( ) + ;paste-buf .File2/r DEO2 ( ) + .File2/ok DEI2 ( size* ) + DUP2 #0000 EQU2 ?&failed ( size* ) + DUP2 paste-from-buf ( size* ) + #0780 LTH2 ?&done ( ) + !&loop ( ) + &failed POP2 + &done + .paste LDZ #00 EQU ?&end LIT "1 bracket-paste &end + JMP2r + +@lit-first-y + .is-lit-flip LDZ ?&flip .lit-click-y LDZ2 JMP2r &flip .lit-drag-y LDZ2 JMP2r +@lit-first-x + .is-lit-flip LDZ ?&flip .lit-click-x LDZ2 JMP2r &flip .lit-drag-x LDZ2 JMP2r +@lit-last-y + .is-lit-flip LDZ ?&flip .lit-drag-y LDZ2 JMP2r &flip .lit-click-y LDZ2 JMP2r +@lit-last-x + .is-lit-flip LDZ ?&flip .lit-drag-x LDZ2 JMP2r &flip .lit-click-x LDZ2 JMP2r + +@redraw-selection ( -> ) + lit-first-y .cols LDZ2 MUL2 ( y0*cols* ) + lit-first-x ADD2 DUP2 ADD2 ( 2(y0*cols+x0)* ) + ;cells ADD2 STH2 ( [addr*] ) + lit-last-y INC2 lit-first-y ( yn* y0* [addr*] ) + DUP2 lit-first-x STH2k ( yn* y0* x0* [addr* x0*] ) + screen-to-cell ( yn* y0* [addr* x0*] ) + &yloop ( yn* y* [addr* x*] ) + OVR2 OVR2 INC2 GTH2 STH .cols LDZ2 ( yn* y* cols* [addr* x* last^] ) + lit-last-x INC2 ( yn* y* cols* xn* [addr* x* last^] ) + STHr [ JMP SWP2 ] POP2 STH2r ( yn* y* xlim* x* [addr*] ) + &xloop ( yn* y* xlim* x* [addr*] ) + STH2kr LDA2 highlight-cell ( yn* y* xlim* x* [addr*] ) + .Screen/x DEI2k #0008 ADD2 ROT DEO2 ( yn* y* xlim* x* [addr*] ) + INC2 INC2r INC2r ( yn* y* xlim* x+1* [addr+2*] ) + GTH2k ?&xloop ( yn* y* xlim* x+1* [addr+2*] ) + POP2 POP2 ( yn* y* [addr+2*] ) + .Screen/y DEI2k #000c ADD2 ROT DEO2 ( yn* y* [addr+2*] ) + .border-pad LDZ2 .Screen/x DEO2 ( yn* y* [addr+2*] ) + LIT2r 0000 INC2 GTH2k ?&yloop ( yn* y+1* [addr+2* 0*] ) + POP2 POP2 POP2r POP2r ( ) + JMP2r ( ) + +@y-point-to-row ( y* -> row* ) + .border-pad LDZ2 LTH2k ?&y0 SUB2 #000c DIV2 .max-y LDZ2 !min &y0 POP2 POP2 #0000 JMP2r + +@x-point-to-col ( x* -> col* ) + #0004 ADD2 .border-pad LDZ2 LTH2k ?&x0 SUB2 #03 SFT2 .max-x LDZ2 !min &x0 POP2 POP2 #0000 JMP2r + +@point-to-coord ( x* y* -> row* col* ) + y-point-to-row SWP2 !x-point-to-col + +@unset-wrap ( -> ) + #00 .cur-wrap STZ JMP2r + +@start-selection ( -> ) + #01 .is-lit STZ ( ) + .Mouse/x DEI2 .Mouse/y DEI2 ( x* y* ) + #00 .is-lit-flip STZ ( x* y* ) + point-to-coord ( row* col* ) + DUP2 .lit-click-x STZ2 .lit-drag-x STZ2 ( row* ) + DUP2 .lit-click-y STZ2 .lit-drag-y STZ2 ( ) + redraw-selection !draw-cursor ( ) + +@selection-is-empty ( -> bool^ ) + .lit-click-y LDZ2 .lit-drag-y LDZ2 EQU2 + .lit-click-x LDZ2 .lit-drag-x LDZ2 EQU2 AND JMP2r + +@find-natural-end ( y* -> xend* ) + DUP2 .cols LDZ2 MUL2 ( y* y*cols* ) + DUP2 ADD2 ;cells ADD2 INC2 ( y* edge* ) + DUP2 .max-x LDZ2 DUP2 ADD2 ADD2 ( y* edge* start=edge+2cols* ) + &loop ( y* edge* addr* ) + LDAk ?&done ( y* edge* addr* ) + #0002 SUB2 LTH2k ?&loop ( y* edge* addr-2* ) + &done ( y* edge* addr* ) + SWP2 SUB2 #01 SFT2 ( y* x* ) + NIP2 JMP2r ( x* ) + +@copy-line ( y* x1* x0* -> y* ) + STH2 STH2 DUP2 find-natural-end ( y* xend* [x0* x1*] ) + STH2r min ( y* xlim=min(xend,x1)* [x0*] ) + DUP2 STH2kr GTH2 ?&ok ( y* xlim* [x0*] ) + POP2 POP2r JMP2r ( y* ; return if line is empty ) + &ok OVR2 .cols LDZ2 MUL2 ( y* xlim* y*cols* [x0*] ) + STH2kr ADD2 DUP2 ADD2 ;cells ADD2 ( y* xlim* addr* [x0*] ) + INC2 STH2 SWP2r STH2r ( y* xlim* x0* [addr+1*] ) + SUB2 INC2 #0000 SWP2 SUB2 ( y* -count* [addr+1*] ) + &loop ( y* -i* [pos*] ) + LDAkr STHr copy-char ( y* -i* [pos*] ) + INC2 INC2r INC2r ORAk ?&loop ( y* -i+1* [pos+2*] ) + POP2 POP2r JMP2r ( y* ; done ) + +@copy-char ( c^ -> ) + DUP ?&ok POP #20 ( replace \0 with space ) + &ok STH ;paste-pos LDA2k ( pos* addr* [c^] ) + STH2k STAr INC2 SWP2 STA2 JMP2r ( ) + +@copy-selection ( -> ) + ;paste-buf ;paste-pos STA2 + lit-last-y INC2 lit-first-y ( ylim* y0* ) + DUP2 lit-first-x STH2k screen-to-cell ( yn* y0* [x0*] ) + &yloop ( yn* y* [x*] ) + OVR2 OVR2 INC2 GTH2 STH .max-x LDZ2 ( yn* y* maxx* [x* last^] ) + lit-last-x ( yn* y* maxx* xlast* [x* last^] ) + STHr [ JMP SWP2 ] POP2 STH2r ( yn* y* x1* x* ) + copy-line ( yn* y* ) + LIT2r 0000 INC2 GTH2k ?&next !&done ( yn* y+1* [0*] ) + &next ( ) + #0a copy-char !&yloop ( ) + &done ( ) + POP2 POP2 POP2r ( ) + ;snarf .File2/name DEO2 ( ) + ;paste-pos LDA2 ;paste-buf SUB2 ( len* ) + .File2/len DEO2 ( ) + ;paste-buf .File2/w DEO2 ( ) + JMP2r ( ) + +@handle-selection ( -> ) + selection-is-empty ?&skip copy-selection + &skip ( fall through to clear-selection ) +@clear-selection ( -> ) + #00 .is-lit STZ + #00 .is-lit-flip STZ + #01 .dirty STZ + #0000 DUP2 .lit-click-y STZ2 + DUP2 .lit-click-x STZ2 + DUP2 .lit-drag-y STZ2 + .lit-drag-x STZ2 JMP2r + +@update-selection ( -> ) + .Mouse/x DEI2 .Mouse/y DEI2 point-to-coord ( row* col* ) + OVR2 .lit-drag-y STZ2 DUP2 .lit-drag-x STZ2 ( row* col* ) + OVR2 .lit-click-y LDZ2 LTH2 ?&earlier ( row* col* ) + DUP2 .lit-click-x LDZ2 LTH2 ?&earlier ( row* col* ) + #00 !&done &earlier #01 ( row* col* ) + &done .is-lit-flip STZ POP2 POP2 JMP2r ( ) + +@end-selection ( -> ) + update-selection draw-cursor !handle-selection ( ) + +@on-click-down ( click^ -> ) + DUP #01 AND ?&left-click + DUP #02 AND ?&middle-click + !&done + &left-click POP !start-selection + &middle-click POP !paste-snarf + &done POP JMP2r + +@on-click-up ( unclick^ -> ) + #01 AND ?&left-click !&done + &left-click !end-selection + &done JMP2r + +@draw-at ( x* y* addr* -> ) + STH2k .Screen/addr DEO2 ( x* y* [addr*] ) + STH2k .Screen/y DEO2 ( x [addr* y*] ) + .Screen/x DEO2 ( [addr* y* x*] ) + #43 .Screen/sprite DEOk ( 43 sprite^ [addr* y* x*] ) + STH2r #0008 ADD2 .Screen/y DEO2 ( 43 sprite^ [addr*] ) + STH2r #0008 ADD2 .Screen/addr DEO2 ( 43 sprite^ ) + DEO JMP2r ( ) + +@draw-pointer ( -> ) + .lastmouse-x LDZ2 .lastmouse-y LDZ2 ( x* y* ) + .pointer-ttl LDZ ?&visible ;cp437/nul !draw-at + &visible ;cp437/rs !draw-at + +@on-move ( -> ) + #c4 .pointer-ttl STZ ( pointer visible for ~1 second ) + .Mouse/x DEI2 .lastmouse-x LDZ2 NEQ2 ?&redraw ( ) + .Mouse/y DEI2 .lastmouse-y LDZ2 NEQ2 ?&redraw ( ) + JMP2r ( ) + &redraw ( ) + .lastmouse-x LDZ2 .lastmouse-y LDZ2 ( lx* ly* ) + ;cp437/space draw-at ( ) + .is-lit LDZ #00 EQU ?&next ( ) + update-selection #01 .dirty STZ ( ) + &next ( ) + .Mouse/x DEI2 .Mouse/y DEI2 ( x* y* ) + .lastmouse-y STZ2 .lastmouse-x STZ2 ( ) + draw-pointer !screen-to-cursor ( ) + +@on-mouse ( -> BRK ) + .lastmouse-st LDZ ( last ) + .Mouse/state DEI ( last st ) + STHk OVR EOR STHkr AND ( last (last^st)&st [st] ) + on-click-down ( last [st] ) + DUP STHkr EOR AND ( last&(last^st) [st] ) + on-click-up ( [st] ) + STHr .lastmouse-st STZ ( ) + on-move BRK ( ) + +@on-key ( -> BRK ) + #00 .pointer-ttl STZ #01 .dirty STZ ( hide pointer ) + .Controller/key DEI ?&ok !on-button + &ok alt ?on-alt-key + ctrl ?on-ctrl-key + .Controller/key DEI + DUP #08 NEQ ?&done + POP #7f ( send DEL instead of BS ) + &done .Console/w DEO BRK + +@ctrl ( -> is-down? ) .Controller/button DEI #01 AND JMP2r +@alt ( -> is-down? ) .Controller/button DEI #02 AND JMP2r + +( alt-XYZ emits ESC and then emits XYZ ) +@on-alt-key ( -> BRK ) + #1b .Console/w DEO + ctrl ?on-ctrl-key + .Controller/key DEI .Console/w DEO BRK + +( control seqs: ) +( ctrl-sp -> 00 ) +( ctrl-@ -> 00 ) +( ctrl-a -> 01 ) +( ... ) +( ctrl-y -> 19 ) +( ctrl-z -> 1a ) +( ctrl-[ -> 1b ) +( esc -> 1b ) +( ctrl-\ -> 1c ) +( ctrl-] -> 1d ) +( ctrl-^ -> 1e ) +( ctrl-/ -> 1f ) +( ctrl-_ -> 1f ) + +( ctrl-$n emits: ) +( 0 <= $n < @ -> $n ) +( @ <= $n < ` -> $n #40 SUB ) +( ` <= $n <= #ff -> $n #60 SUB ) +@on-ctrl-key ( -> BRK ) + .Controller/key DEI + DUP #20 EQU ?&nul ( space ) + DUP #2d EQU ?&us ( '-' i.e. '_' ) + DUP #2f EQU ?&nul ( '/' ) + DUP #32 EQU ?&nul ( '2' i.e. '@' ) + DUP #36 EQU ?&rs ( '6' i.e. '^' ) + DUP LIT "@ LTH ?&done + DUP LIT "` LTH ?&c1 + LIT "` SUB !&done + &nul #00 !&done + &rs #1e !&done + &us #1f !&done + &c1 LIT "@ SUB + &done .Console/w DEO BRK + +@on-read-priv ( -> BRK ) + .Console/r DEI + DUP LIT "; EQU ?next-arg + DUP LIT "0 LTH ?end-arg-priv + DUP LIT "9 GTH ?end-arg-priv + !add-to-arg + +@start-priv ( -> BRK ) + POP ;on-read-priv .Console/vect DEO2 BRK + +@on-read-csi ( -> BRK ) + .Console/r DEI + DUP LIT "? EQU ?start-priv + DUP LIT "; EQU ?next-arg + DUP LIT "0 LTH ?end-arg + DUP LIT "9 GTH ?end-arg + !add-to-arg + +@on-read-osc ( -> BRK ) + .Console/r DEI + DUP #07 ( bell ) EQU ?&end-osc + #9c ( esc-\ ) EQU ?&end-osc BRK + &end-osc ;on-read .Console/vect DEO2 BRK + ( TODO: support 7-bit 1b 5c sequence? ) + +@debug-arg ( n* -> ) + &short SWP debug-arg/byte + &byte DUP #04 SFT debug-arg/char + &char #0f AND DUP #09 GTH #27 MUL ADD #30 ADD !scratch-write + +@debug-args ( -> ) + ;args/pos LDA2 ;args + &loop + #20 scratch-write + LDA2k debug-arg/short INC2 INC2 + LTH2k ?&done !&loop + &done POP2 POP2 JMP2r + +@debug-priv ( c^ -> ) + .debug LDZ ?&continue POP JMP2r &continue + reset-scratch + LIT2r =scratch-write + LIT "1 STH2kr JSR2 + LIT "b STH2kr JSR2 + #20 STH2kr JSR2 + LIT "[ STH2kr JSR2 + #20 STH2kr JSR2 + LIT "? STH2kr JSR2 + debug-args + #20 STH2kr JSR2 + STH2kr JSR2 + #0a STH2r JSR2 + scratch-len .File1/len DEO2 + ;scratch .File1/w DEO2 + JMP2r + +@end-arg-priv ( c^ -> BRK ) + ;on-read .Console/vect DEO2 + DUP LIT "h EQU ?exec-priv-set-or-unset + DUP LIT "l EQU ?exec-priv-set-or-unset + DUP debug-priv + ( TODO: handle these ) + POP BRK + +@exec-priv-set-or-unset ( c^ -> BRK ) + #0001 read-arg-1 ( c^ n* ) + DUP2 #0019 NEQ2 ?&!25 POP2 .tcem !&change + &!25 DUP2 #07d4 NEQ2 ?&!2004 POP2 .paste !&change + &!2004 POP2 debug-priv BRK + &change SWP LIT "h EQU SWP STZ BRK ( h is set, l is unset ) + +@debug-read ( c^ -> ) + .debug LDZ ?&continue POP JMP2r &continue + reset-scratch + debug-arg/byte + #0a scratch-write + scratch-len .File1/len DEO2 + ;scratch .File1/w DEO2 + JMP2r + +@debug-csi ( c^ -> ) + .debug LDZ ?&continue POP JMP2r &continue + reset-scratch + LIT2r =scratch-write + LIT "1 STH2kr JSR2 + LIT "b STH2kr JSR2 + #20 STH2kr JSR2 + LIT "[ STH2kr JSR2 + debug-args + #20 STH2kr JSR2 + STH2kr JSR2 + #0a STH2r JSR2 + scratch-len .File1/len DEO2 + ;scratch .File1/w DEO2 + JMP2r + +@end-arg ( c^ -> BRK ) + ;on-read .Console/vect DEO2 + DUP debug-csi + DUP LIT "@ EQU ?exec-ich ( insert blank characters ) + DUP LIT "A EQU ?exec-cuu ( up ) + DUP LIT "B EQU ?exec-cud ( down ) + DUP LIT "C EQU ?exec-cuf ( forward ) + DUP LIT "D EQU ?exec-cub ( back ) + DUP LIT "E EQU ?exec-cnl ( next line $n times ) + DUP LIT "F EQU ?exec-cpl ( prev line $n times ) + DUP LIT "G EQU ?exec-cha ( move cursor to col ) + DUP LIT "H EQU ?exec-cup ( move cursor ) + DUP LIT "I EQU ?exec-cht ( forward by tab stops ) + DUP LIT "J EQU ?exec-ed ( erase screen ) + DUP LIT "K EQU ?exec-el ( erase line ) + DUP LIT "L EQU ?exec-il ( insert blank lines ) + DUP LIT "M EQU ?exec-dl ( delete n lines ) + DUP LIT "P EQU ?exec-dch ( delete n chars ) + DUP LIT "S EQU ?exec-su ( scroll up ) + DUP LIT "T EQU ?exec-sd ( scroll down ) + DUP LIT "X EQU ?exec-ech ( erase $n characters ) + DUP LIT "Z EQU ?exec-cbt ( backward by tab stops ) + DUP LIT "` EQU ?exec-hpa ( char pos abs col=$n ) + DUP LIT "a EQU ?exec-hpr ( char pos rel col=$n ) + DUP LIT "d EQU ?exec-vpa ( move cursor to row ) + DUP LIT "e EQU ?exec-vpr ( line pos rel row+=$n ) + DUP LIT "g EQU ?exec-tbc ( clear tab stops ) + DUP LIT "h EQU ?exec-sm ( set mode ) + DUP LIT "l EQU ?exec-rm ( reset mode ) + DUP LIT "m EQU ?exec-sgr ( set graphical rendering ) + DUP LIT "n EQU ?exec-dsr ( device status reports ) + DUP LIT "r EQU ?exec-set-scrolling-region + DUP LIT "s EQU ?exec-scosc ( saved current cursor position ) + DUP LIT "u EQU ?exec-scorc ( restore saved cursor position ) + ( = 0 C - normal cursor ) + ( = 1 C - bold cursor ) + debug-csi BRK + +@exec-set-scrolling-region ( c^ -> BRK ) POP BRK + +@exec-tbc ( c^ -> BRK ) POP BRK + +@exec-scosc ( c^ -> BRK ) + POP .cur-x LDZ2 .saved-x STZ2 .cur-y LDZ2 .saved-y STZ2 BRK + +@exec-scorc ( c^ -> BRK ) + POP clear-cursor + .saved-x LDZ2 .cur-x STZ2 .saved-y LDZ2 .cur-y STZ2 + draw-cursor BRK + +@mode-addr ( n* -> zp^ ) + DUP2 #0004 NEQ2 ?¬-irm POP2 .irm JMP2r + ¬-irm DUP2 #0007 NEQ2 ?¬-awm POP2 .awm JMP2r + ¬-awm POP2 .ignored JMP2r + +@sm ( n* -> ) mode-addr #01 SWP STZ JMP2r +@rm ( n* -> ) mode-addr #00 SWP STZ JMP2r + +( other attributes: ) +( 10 - primary font ) +( 39 - default fg ) +( 49 - default bg ) +@read-attr ( attr* -> ) + DUP2 #0031 GTH2 ?&skip ( attr* ; skip > 49 ) + DUP2 ;sgr-fg ADD2 LDA ( attr* code^ ) + DUP #40 EQU ?&reset ( attr* code^ ) + DUP #80 EQU ?&invert ( attr* code^ ) + DUP #ff EQU ?&done ( attr* code^ ) + ROT ROT #0027 GTH2 ?&bg + .attr LDZ #fc !&update + &bg #20 SFT .attr LDZ #f3 + &update AND ORA .attr STZ !update-tint + + &reset #02 .attr STZ !&done + &invert .attr LDZ #80 ORA .attr STZ + &done update-tint POP &skip POP2 JMP2r + +@sgr-fg ( 0 1 2 3 4 5 6 7 8 9 a b c d e f ) + ( 00 ) 40 03 01 ff ff ff ff 80 ff ff ff ff ff ff ff ff + ( 10 ) ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 02 + ( 20 ) 02 02 02 02 02 03 ff 02 00 01 01 01 01 01 01 03 + ( 30 ) ff 00 + +@exec-sgr ( c^ -> BRK ) + POP + ;args/pos LDA2 ;args + &loop + LDA2k read-attr + INC2 INC2 + LTH2k ?&done !&loop + &done + POP2 POP2 BRK + +@exec0 ( addr* -> BRK ) STH2 #0000 read-arg-1 STH2r JSR2 BRK +@exec1 ( addr* -> BRK ) STH2 #0001 read-arg-1 STH2r JSR2 BRK + +@exec-cuu POP ;cuu !exec1 +@exec-cud POP ;cud !exec1 +@exec-cuf POP ;cuf !exec1 +@exec-cub POP ;cub !exec1 +@exec-ich POP ;ich !exec1 +@exec-dl POP ;dl !exec1 +@exec-dch POP ;dch !exec1 +@exec-il POP ;il !exec1 +@exec-cht POP ;cht !exec1 +@exec-cbt POP ;cbt !exec1 +@exec-cnl POP ;cnl !exec1 +@exec-cpl POP ;cpl !exec1 +@exec-su POP ;su !exec1 +@exec-ech POP ;ech !exec1 +@exec-hpa POP ;hpa !exec1 +@exec-hpr POP ;hpr !exec1 +@exec-vpr POP ;vpr !exec1 +@exec-sd POP BRK ( TODO ) +@exec-vpa POP ;vpa !exec1 +@exec-cha POP ;cha !exec1 +@exec-el POP ;el !exec0 +@exec-ed POP ;ed_ !exec0 +@exec-sm POP ;sm !exec1 +@exec-rm POP ;rm !exec1 +@exec-dsr POP ;dsr !exec1 + +@dsr ( n* -> ) + #0006 NEQ2 ?&done + #1b .Console/w DEO + LIT "[ .Console/w DEO + .cur-y LDZ2 INC2 emit-dec2 + LIT "; .Console/w DEO + .cur-x LDZ2 INC2 emit-dec2 + LIT "R .Console/w DEO + &done BRK + +@cnl ( n* -> ) clear-cursor #0000 .cur-x STZ2 !down-n +@cpl ( n* -> ) clear-cursor #0000 .cur-x STZ2 !up-n +@cub ( n* -> ) clear-cursor !back-n +@cud ( n* -> ) clear-cursor !down-n +@cuf ( n* -> ) clear-cursor !forward-n +@cuu ( n* -> ) clear-cursor !up-n +@hpa ( n* -> ) unset-wrap clear-cursor dec-floor .max-x LDZ2 min .cur-x STZ2 !draw-cursor +@hpr ( n* -> ) clear-cursor !forward-n +@vpr ( n* -> ) clear-cursor !down-n +@vpa ( n* -> ) dec-floor .cur-x LDZ2 !goto +@cha ( n* -> ) dec-floor .cur-y LDZ2 SWP !goto + +@su ( n* -> ) + #0000 SWP2 SUB2 STH2 clear-cursor ( [-count*] ) + &loop scroll INC2r ORAkr STHr ?&loop ( [-i+1*] ) + POP2r JMP2r ( ) + +@ech ( n* -> ) + #0000 SWP2 SUB2 STH2 ( [-count*] ) + #0200 cur-addr ( 0200 addr* [-count*] ) + &loop ( 0200 pos* [-i*] ) + STA2k INC2 INC2 ( 0200 pos+2* [-i*] ; pos<-0200 ) + INC2r ORAkr STHr ?&loop ( pos+2* [-i+1*] ) + POP2 POP2 POP2r ( ) + #01 .dirty STZ JMP2r ( ) + +@el ( n* -> ) + DUP2 #0000 EQU2 ?&erase-to-end + DUP2 #0001 EQU2 ?&erase-from-start + DUP2 #0002 EQU2 ?&erase-full + POP2 JMP2r + &erase-full POP2 bol-addr eol-addr !erase + &erase-to-end POP2 cur-addr eol-addr !erase + &erase-from-start POP2 bol-addr cur-addr !erase + +@ed_ ( n* -> ) + DUP2 #0000 EQU2 ?&erase-to-end + DUP2 #0001 EQU2 ?&erase-from-start + DUP2 #0002 EQU2 ?&erase-full + POP2 JMP2r + &erase-full POP2 first-addr limit-addr !erase + &erase-to-end POP2 bol-addr limit-addr !erase + &erase-from-start POP2 first-addr eol-addr ( fall-through ) +@erase ( start* end* -> ) #0200 !init + +@exec-cup ( c^ -> BRK ) + POP ( ) + #0001 read-arg-1 dec-floor ( row ) + #0001 read-arg-2 dec-floor ( col ) + goto BRK ( ) + +@dec-floor ( x* -> x==0 ? 0* : x-1* ) + #0001 SUB2 #0000 !smax + +@debug-esc ( c^ -> ) + .debug LDZ ?&continue POP JMP2r &continue + LIT2r =scratch + LIT "1 STH2kr STA INC2r + LIT "b STH2kr STA INC2r + #20 STH2kr STA INC2r + STH2kr STA INC2r + #0a STH2r STA + #0005 .File1/len DEO2 + ;scratch .File1/w DEO2 + JMP2r + +@on-read-esc ( -> BRK ) + .Console/r DEI + DUP debug-esc + DUP LIT "D EQU ?exec-ind + DUP LIT "E EQU ?exec-nel + DUP LIT "H EQU ?exec-hts + DUP LIT "M EQU ?exec-ri + DUP LIT "P EQU ?exec-dcs + DUP LIT "[ EQU ?start-csi + DUP LIT "] EQU ?start-osc + DUP LIT "c EQU ?exec-ris + DUP LIT "( EQU ?start-charset + DUP LIT ") EQU ?start-charset + DUP LIT "7 EQU ?&skip ( save cursor ) + DUP LIT "8 EQU ?&skip ( restore cursor ) + debug-esc + ;on-read .Console/vect DEO2 + !on-read + &skip POP ;on-read .Console/vect DEO2 BRK + +@exec-ind ( c^ -> ) POP clear-cursor down-or-scroll BRK +@exec-nel ( c^ -> ) POP cr BRK +@exec-hts ( c^ -> ) POP BRK ( TODO ) +@exec-ri ( c^ -> ) POP clear-cursor #0001 up-n BRK +@exec-dcs ( c^ -> ) POP BRK ( TODO ) + +@exec-ris ( c^ -> ) + POP first-addr limit-addr erase + reset-terminal BRK + +@on-read-skip ( -> BRK ) + ;on-read .Console/vect DEO2 + BRK + +( '(' = designate G0 charset ) +( ')' = designate G1 charset ) +( '*' = designate G2 charset ) +( '+' = designate G3 charset ) +@start-charset ( c^ -> BRK ) + POP ;on-read-skip .Console/vect DEO2 BRK + +@start-csi ( c^ -> BRK ) + POP reset-args ;on-read-csi .Console/vect DEO2 BRK + +@start-osc ( c^ -> BRK ) + POP reset-args ;on-read-osc .Console/vect DEO2 BRK + +@on-read ( -> BRK ) + .Console/r DEI read BRK + +@read ( c^ -> ) + DUP debug-read + DUP ?&ok POP JMP2r + &ok + DUP #20 LTH ?read-ctrl + DUP #7f EQU ?read-del + ( fall through to draw ) + +@draw ( c^ -> ) + .tint LDZ SWP DUP2 insert-cell draw-cell + .cur-x LDZ2 .max-x LDZ2 EQU2 .cur-wrap STZ + clear-cursor !forward + +@read-ctrl ( c^ -> ) + DUP #07 EQU ?read-bel + DUP #08 EQU ?read-bs + DUP #09 EQU ?read-tab + DUP #0a EQU ?read-lf + DUP #0b EQU ?read-lf + DUP #0c EQU ?read-lf + DUP #0d EQU ?read-cr + DUP #1b EQU ?read-esc + POP JMP2r + +@read-bel ( 07 -> ) + POP .visual-bell LDZ #00 EQU ?&done + #06 .flash STZ #01 .dirty STZ + &done JMP2r + +@read-bs ( 08 -> ) + POP clear-cursor #0001 !back-n + +@read-esc ( 1b -> ) + POP ;on-read-esc .Console/vect DEO2 JMP2r + +@read-del ( 7f -> ) + POP JMP2r + +@read-tab ( 09 -> ) + POP + .cur-x LDZ2 ( x* ) + NIP #07 AND #08 SUB ( i=(xlo&7)-8^ ) + &loop ( i^ ) + .tint LDZ #20 DUP2 ( i^ cell* cell* ) + cur-addr STA2 ( i^ cell* ; addr<-cell ) + draw-cell ( i^ ) + clear-cursor ( i^ ) + forward ( i^ ) + INC DUP ?&loop ( i+1^ ) + POP JMP2r ( ) + +@cr ( -> ) + clear-cursor #0000 .cur-x STZ2 !draw-cursor + +@read-cr ( 0d -> ) + POP .cur-wrap LDZ ?&skip cr &skip JMP2r + +@at-max-x ( -> true? ) .cur-x LDZ2 .max-x LDZ2 EQU2 JMP2r +@at-max-y ( -> true? ) .cur-y LDZ2 .max-y LDZ2 EQU2 JMP2r + +@read-lf ( 0a -> ) + POP !lf + +@lf ( -> ) + .cur-wrap LDZ ?&skip clear-cursor down-or-scroll &skip JMP2r + +@goto ( y* x* -> ) + unset-wrap + clear-cursor + .max-x LDZ2 min .cur-x STZ2 + .max-y LDZ2 min .cur-y STZ2 + !draw-cursor + +@forward-n ( n* -> ) + .cur-x LDZ2 ADD2 .max-x LDZ2 min .cur-x STZ2 !draw-cursor + +@back-n ( n* -> ) + unset-wrap + .cur-x LDZ2 SWP2 SUB2 #0000 smax .cur-x STZ2 !draw-cursor + +@up-n ( n* -> ) + .cur-y LDZ2 SWP2 SUB2 #0000 smax .cur-y STZ2 !draw-cursor + +@down-n ( n* -> ) + .cur-y LDZ2 ADD2 .max-y LDZ2 min .cur-y STZ2 !draw-cursor + +@forward ( -> ) #0001 !forward-n +@down ( -> ) #0001 !down-n + +@down-or-scroll ( -> ) at-max-y ?&s !down &s !scroll + +@maybe-autowrap ( -> ) + .cur-wrap LDZ #00 EQU ?&skip + #00 .cur-wrap STZ + clear-cursor + #0000 .cur-x STZ2 + at-max-y ?&scrolling + .cur-y LDZ2k INC2 ROT STZ2 + screen-to-cursor + &skip JMP2r + &scrolling !scroll + +@insert-cell ( cell* -> ) + maybe-autowrap ( cell* ) + .irm LDZ #00 EQU ?&replace ( cell* ) + cur-addr ( cell* lim* ) + eol-addr #0002 SUB2 ( cell* lim* last=eol-2* ) + &loop ( cell* lim* pos* ) + STH2k #0002 SUB2 LDA2k ( cell* lim* pos-2* cell* [pos*] ) + STH2r STA2 LTH2k ?&loop ( cell* lim* pos-2* ) + POP2 POP2 ( cell* ) + &replace ( cell* ) + cur-addr STA2 JMP2r ( ) + +@cht ( n* -> ) + clear-cursor + dec-floor #30 SFT2 ( i=(n-1)8* ) + #0008 .cur-x LDZ2 #0007 AND2 SUB2 ( i* 8-cur%8* ) + ADD2 !forward-n ( ) + +@cbt ( n* -> ) + unset-wrap + clear-cursor + dec-floor #30 SFT2 ( i=(n-1)8* ) + .cur-x LDZ2 #0007 AND2 ( i* cur%8* ) + ADD2 !back-n ( ) + +@il ( n* -> ) + .col-bytes LDZ2 MUL2 STH2 ( [i*] ) + bol-addr ( bound* [i*] ) + limit-addr STH2kr ( bound* limit* i* [i*] ) + INC2 INC2 SUB2 ( bound* start=limit-i-2* [i*] ) + &loop ( bound* pos* [i*] ) + LDA2k OVR2 STH2kr ADD2 ( bound* pos* x* pos+i* [i*] ) + STA2 ( bound* pos* [i*] ; pos+i<-x ) + #0200 OVR2 STA2 ( bound* pos* [i*] ; pos<-0200 ) + #0002 SUB2 ( bound* pos-2* [i*] ) + GTH2k #00 EQU ?&loop ( bound* pos-2* [i*] ) + POP2 POP2 POP2r ( ) + #01 .dirty STZ JMP2r ( ) + +@ich ( n* -> ) + STH2 ( [n*] ) + eol-addr #0001 SUB2 ( last* [n*] ) + STH2kr DUP2 ADD2 SUB2 ( start=last-2n* [n*] ) + cur-addr SWP2 ( end* start* [n*] ) + DUP2kr ADD2r ( end* start* [n* 2n*] ) + &loop ( end* pos* [n* 2n*] ) + LDA2k OVR2 STH2kr ADD2 ( end* pos* x* pos+2n* ) + STA2 #0002 SUB2 ( end* pos-2* [n* 2n*] ) + GTH2k #00 EQU ?&loop ( end* pos-2* [n* 2n*] ) + POP2 POP2 POP2r ( [n*] ) + LIT2r 0000 SWP2r SUB2r ( [-n*] ) + #0200 cur-addr ( 0200 cur* [-n*] ) + &loop2 ( 0200 pos* [-i*] ) + STA2k INC2 INC2 INC2r ( 0200 pos+2* [-i+1*] ) + ORAkr STHr ?&loop2 ( 0200 pos+2* [-i+1*] ) + POP2 POP2 POP2r ( ) + #01 .dirty STZ JMP2r ( ) + +( starts with cursor pos ) +@dch ( n* -> ) + DUP2 ADD2 STH2 ( [i=2n*] ) + eol-addr STH2kr SUB2 ( limit=eol-i* [i*] ) + cur-addr ( limit* start* [i*] ) + &loop ( limit* pos* [n*] ) + DUP2 STH2kr ADD2 LDA2k ( limit* pos* pos+i* x* [i*] ) + #0200 ROT2 STA2 ( limit* pos* x* [i*] ; pos+i<-0200 ) + OVR2 STA2 INC2 INC2 ( limit* pos+2* [i*] ; pos<-x ) + GTH2k ?&loop ( limit* pos+2* [i*] ) + POP2 POP2 POP2r ( ) + #01 .dirty STZ JMP2r ( ) + +( starts below current line ) +@dl ( n* -> ) + .col-bytes LDZ2 MUL2 STH2 ( [n*] ) + limit-addr STH2kr SUB2 ( limit* [n*] ) + eol-addr ( limit* start* [n*] ) + !dch/loop + +@scroll ( -> ) + limit-addr STH2 ( [lim*] ) + ;cells .col-bytes LDZ2 ADD2 STH2 ( [lim* addr*] ) + &loop ( [lim* pos*] ) + STH2kr LDA2 #0200 STH2kr STA2 ( cell* [lim* pos* cell*] ; pos<-0200 ) + STH2kr .col-bytes LDZ2 SUB2 STA2 ( [lim* pos*] ; pos-cb<-cell ) + INC2r INC2r GTH2kr STHr ?&loop ( [lim* pos+2*] ) + POP2r POP2r ( ) + #01 .dirty STZ ( ) + !draw-cursor ( ) + +( bits: Rx xx FF BB ) +( - R: reversed [0=normal, 1=reversed] ) +( - F: foreground [0:black, 1:dim, 2:normal, 3:bright] ) +( - B: background [0:black, 1:dim, 2:normal, 3:bright] ) +@update-tint ( -> ) + .attr LDZ + DUP #80 LTH ?&ok + #80 EOR DUP #02 SFT SWP #20 SFT #0c AND ORA + &ok .tint STZ JMP2r + +@reverse-tint ( tint^ -> tint^ ) + #0f AND ( x=tint&0f ) + DUP #02 SFT SWP ( x>>2 x ) + #03 AND #20 SFT ( x>>2 (x&3)<<2 ) + ORA ( res=40|x>>2|(x&3)<<2 ) + JMP2r ( res^ ) + +( to draw a 12 pixel high character we first draw the top ) +( 8 pixels and then we draw the bottom 8 pixels; there is ) +( an overlap of 4 pixels. we do this to avoid drawing too ) +( low which might overwrite characters on the next line. ) + +( cell* = tint^ c^ ) +@draw-cell ( cell* -> ) + SWP STH ( c^ [tint^] ) + #00 SWP #40 SFT2 ;cp437 ADD2 ( addr* [tint^] ) + .Screen/addr DEO2k ( addr* s^ [tint^] ) + STHkr .Screen/sprite DEO ( addr* s^ [tint^] ) + .Screen/y DEI2k #0004 ADD2 ROT DEO2 ( addr* s^ [tint^] ) + STH #0004 ADD2 STHr DEO2 ( [tint^] ) + STHr .Screen/sprite DEO ( ) + .Screen/y DEI2k #0004 SUB2 ROT DEO2 ( ) + JMP2r ( ) + +@highlight-cell ( cell* -> ) + NIP LITr 47 ( c^ [tint^] ) + #00 SWP #40 SFT2 ;cp437 ADD2 ( addr* [tint^] ) + .Screen/addr DEO2k ( addr* s^ [tint^] ) + STHkr .Screen/sprite DEO ( addr* s^ [tint^] ) + .Screen/y DEI2k #0004 ADD2 ROT DEO2 ( addr* s^ [tint^] ) + STH #0004 ADD2 STHr DEO2 ( [tint^] ) + STHr .Screen/sprite DEO ( ) + .Screen/y DEI2k #0004 SUB2 ROT DEO2 ( ) + JMP2r ( ) + +@next-arg ( c^ -> BRK ) + POP + ( TODO: check if we already have max args ) + ;args/pos LDA2k INC2 INC2 SWP2 STA2 BRK + +@add-to-arg ( c^ -> BRK ) + LIT "0 SUB LITr 00 STH ( [digit*] ) + ;args/pos LDA2 LDA2k ( addr* value* [digit*] ) + #000a MUL2 STH2r ADD2 ( addr* value*10+digit ) + SWP2 STA2 BRK + +@read-arg-1 ( default* -> n* ) ;args/arg1 LDA2 !max +@read-arg-2 ( default* -> n* ) ;args/arg2 ( INC2 INC2 ) LDA2 !max + +@reset-args ( -> ) + ;args ;args/pos STA2 + #0000 ;args LITr f8 + &loop STA2k INC2 INC2 + INCr STHkr ?&loop + POPr POP2 POP2 JMP2r + +( emit a signed short as a decimal ) +@emit-sdec2 ( n* -> ) + DUP2k #1f SFT2 EQUk ?&s LIT2 "- 18 DEO + &s MUL2 SUB2 ( fall-through to emit-dec2 ) + +( emit an unsigned short as a decimal ) +@emit-dec2 ( n* -> ) + LITr ff00 &read #000a DIV2k STH2k MUL2 SUB2 STH2r INCr ORAk ?&read + POP2 &write NIP #30 ADD #18 DEO OVRr ADDr STHkr ?&write + POP2r JMP2r + +@debug-log "debug_term.log 00 +@scratch $40 &pos $2 + +@scratch-write ( c^ -> ) + ;scratch/pos LDA2 STA + ;scratch/pos LDA2k INC2 SWP2 STA2 JMP2r +@scratch-len ( -> n* ) + ;scratch/pos LDA2 ;scratch SUB2 JMP2r +@reset-scratch + ;scratch ;scratch/pos STA2 JMP2r + +( store up to 8 arguments for control sequences ) +( @args $10 &pos $2 ) +@args [ &arg1 $2 &arg2 $2 &rest $c &pos $2 ] + +( 256 chars x 2 tiles/char x 8 bytes/tile = 4096 bytes ) +( second tile only uses top 50% ) +@cp437 + ~cp437.tal + +@snarf ".snarf 00 + +@meta 00 &body + &name "determ 0a + &details "ansi 20 "terminal 20 "emulator 0a + &author "by 20 "d_m 0a + &date "3 20 "jan 20 2023 00 + 02 + ( device mask ) 41 0d07 + ( 24x24 icon ) 83 =icon-2-bit + +@banner-ascii + 0d 0a + 20 20 c9 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd bb 0d 0a + 20 20 ba 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ba 0d 0a + 20 20 ba 20 20 "d "e "t "e "r "m 20 20 "v "1 "0 20 20 ba 0d 0a + 20 20 ba 20 20 20 20 "b "y 20 "d "_ "m 20 20 20 20 20 ba 0d 0a + 20 20 ba 20 20 "1 "8 20 "m "a "r 20 "2 "0 "2 "3 20 20 ba 0d 0a + 20 20 ba 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ba 0d 0a + 20 20 c8 cd cd cb cd cd cd cd cd cd cd cd cd cb cd cd bc 0d 0a + 20 20 c9 cb cb ce cb cb cb cb cb cb cb cb cb ce cb cb bb 0d 0a + 20 20 c8 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca bc 0d 0a + 0d 0a 00 + +@icon-2-bit + 00 00 00 1f 3f 38 32 34 00 00 00 00 00 07 0f 0f + 00 00 00 ff ff 00 00 00 00 00 00 00 00 ff ff ff + 00 00 00 f8 fc 1c 4c 2c 00 00 00 00 00 e0 f0 f0 + 34 30 30 30 30 30 30 30 0f 0f 0f 0f 0f 0f 0f 0f + 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff + 2c 0c 0c 0c 0c 0c 0c 0c f0 f0 f0 f0 f0 f0 f0 f0 + 34 34 32 38 3f 1e 07 00 0f 0f 0f 07 00 03 00 00 + 00 00 00 00 ff a0 ff 00 ff ff ff ff 00 ff 00 00 + 2c 2c 4c 1c fc 38 e0 00 f0 f0 f0 e0 00 c0 00 00 + +( paste buffer ) +@paste-buf $0780 ( max 80 x 24 characters ) +@paste-pos $2 + +( store tint+char for each screen position ) +@cells ( width x height x 2 bytes )