Termlib demo
What is this?
TL;DR: An MVP of a terminal-inspired text rendering library for XO-CHIP.
See the GitHub repo for quickstart instructions and source code.
As of Octojam 10, it supports notions of foreground and background:
: message_string text "^B3^F2" text "PLANE 3 BG PLANE 2 TXT\n" text "^D" # Reset the colors text "PLANE 0 BG PLANE 3 TXT\n" text "^B2" # Set BG plane to 3 text "PLANE 2 BG PLANE 3 TXT\" text "\0" # \0 ends the message. :main show-msg 0 0 message_string v0 := key # wait for input before the rest of the program
Please provide feedback on the syntax & future features proposed below!
Why build this?
I wanted:
- A quickstart tool for rendering text in Octo projects
- A configurable renderer to help restart work on Fontknife, another project of mine
- To learn about text formatting and rendering on low-resource and retro platforms
How does it work?
TL;DR: It reads certain character combinations as formatting control instead of drawing them as sprites.
Let's use the title screen from the demo above as an example. With the library, drawing the formatted text on it consists of the following:
- Declare the following label:
: msg_title text "\n\n" text "^F3^B0 COLOR LIB DEMO \n" text " ^F3^B2 PRESS ANY KEY ^D\n" text " ^F1^B3 ALL TEXT DYNAMIC!\0"
- Call the drawing routine:
show-msg 0 0 msg_title # Wait for input to allow observing the text v0 := key
Every ^
starts an escape sequence which changes the drawing planes
instead of rendering as text. Some set non-default colors, while others restore
defaults.
The result:
The second screen shows off the full range of color combinations by using the following syntax:
: msg_all text "^F0^B0 0^F1^B0 1^F2^B0 2^F3^B0 3\n" text "^F0^B1 4^F1^B1 5^F2^B1 6^F3^B1 7\n" text "^F0^B2 8^F1^B2 9^F2^B210^F3^B211\n" text "^F0^B312^F1^B313^F2^B314^F3^B315\0"
The result:
Is it fast?
TL;DR: Yes-ish.
For maximum performance, you should follow Internet Janitor's advice on performance.
Otherwise, this library will probably be ok for getting started. The demo embedded on this page runs at 100 instructions / cycle. It will run smoothly down to 30 instructions / cycle. After that point, pauses from string parsing will grow more noticeable.
Since there is a lot of room for optimization, it is unclear what the minimum instruction / cycle will be.
Syntax Details
TL;DR: "What if Bash color escapes were better?"
The ^
character enters escape mode. To save CPU cycles
and memory, there is no closing tag and no stack. Instead, effects are
applied immediately. You can restore defaults by either binding them
to a string to draw, or use the dedicated shortcut:
Name | Escape code | Action(s) |
---|---|---|
Defaults | ^D |
Restore the following defaults:
|
Background | ^BN |
Set the draw plane(s) for the flat character used to color the background layer. |
Foreground | ^FN |
Set the draw plane(s) for the foreground layer. |
As Regex
TL;DR: There are interactive regex playgrounds linked below.
Regex Flavor | Regex101 Link | Rough expression |
---|---|---|
ECMAScript/JavaScript | Try it | const fmt = /(\^(?<action>[A-Z])(?<num>\d?)+)/ |
Python | Try it | fmt = re.compile(r'\^(?P<action>[A-Z])(?P<num>\d)?') |
Current Limitations
TL;DR: There are a lot of brittle assumptions and no way to keep vF
results.
The drawing layers imitate the concepts of other systems by
using double length sprites compatible with plane 3
.
Font data is expected to match this standard. This is how the
second screen generates all its color combinations: XO-CHIP's
XOR-based allows effects like stenciling shapes out of single-color
surfaces.
Despite its potential, the current implementation is currently incomplete in ways which limit its use for more demanding tasks. Some of the most important examples are outlined below.
Current Implementation | Limitation |
---|---|
No form of error handling in any shape | Bad input can break non-debugger status displays. |
One message position stored at time without caching | Library best used for predictable state such as JRPG text boxes |
Assumes monospace fonts | Unexpected character sizes will not render highlighting correctly. |
Layer draw calls skip if their plane is 0 |
Inconsistent timing if plane values change |
Storing vF from successive draw calls is unimplemented |
Can't detect XOR collisions while batch drawing text |
See the following to learn more:
- The Inspiration heading below
- The XO-Chip documentation
Planned Additions
Tentative Example | Meaning | Intended Purpose |
---|---|---|
text "^R5^C5example" |
Jump drawing cursor to row 5, column 5 | Replacing or deleting specific characters |
text "^X51^Y23example" |
Move the drawing cursor to:
|
Kerning tweaks / experimentation. |
text "^E3" |
XOR entire screen with pixels using plane 3 |
Change colors for already-printed text. |
Future features could also include:
- Caching of rendered glyphs to speed up XOR-erasing specific parts
- Limited UI / widget features
Design goals
TL;DR: Imitate some old terminal behaviors but with quality of life improvements.
The CHIP-8 instruction set was originally designed for 1970s kit computers. This hardware was extremely limited, even when compared to the era's terminals and more some recent household appliances. For example, these kit computers:
- ran at less than 2 MHz
- came with less than 2 KB of RAM
Systems from this era made the most of their limited resources by reserving control characters for communication and markup, as well as using escape characters to indicate changes in encoding.
Since control characters are often represented with
caret notation, this library re-uses it as a convenient default
escape character. However, the final value is not converted to a byte
literal but left as an ASCII ^
.
It has numerous advantages:
- It works with the limitations of Octo's
:stringmode
macros without sacrificing any clarity - Combining styles is far more legible:
- It's easier to implement in Octo
- It renders cleanly in Octo's debugger unlike unprintable byte literals
- The resulting escapes are easier to distinguish than hex codes
- It's easier to enter than hex codes
Aside from wasting bytes, there seem to be few downsides, especially if you
are still prototyping. The ^
character seems to generally be
unused in Octo projects due to poor legibility in pixel fonts, especially at
the supported screen resolutions.
Inspiration
- rich, a Python terminal formatting library
- Control & drawing behaviors from specific systems:
Status | Prototype |
Category | Tool |
Platforms | HTML5 |
Author | pushfoo |
Tags | demo, library, octo, Text based |
Average session | A few seconds |
Inputs | Keyboard |
Links | Source code |
Leave a comment
Log in with itch.io to leave a comment.