A curses-style TUI library for the TI-84 Plus CE. Panels, widgets, scenes, dialogs, colors and text styles for CE C programs.
You need:
bin/ on PATH. It provides make, cedev-config and
cemu-autotester.pacman -S mingw-w64-ucrt-x86_64-gcc.
Put C:\msys64\ucrt64\bin above C:\Program Files\Git\mingw64\bin in
your PATH. Git ships older copies of DLLs that gcc loads, and if Git’s
folder comes first, gcc fails without printing an error. Git Bash always puts
its own folder first, so run the unit tests from PowerShell or cmd.PATH
(on Windows: winget install DimitriVanHeesch.Doxygen) and
Node.js, which runs moxygen through npx.| Path | Contents |
|---|---|
src/ |
The library. titrm.h is the whole public API |
src/FONT.md |
Character code → glyph → purpose table (generated) |
examples/hello/ |
The smallest useful program |
examples/demo/ |
A mock Wi-Fi manager using every feature: scenes, an overlay dialog with buttons, a log |
docs/ |
API reference (generated) |
Doxyfile |
Doxygen settings for the API docs |
tools/gen_font.py |
Converts tools/petabyt-font/font.h into src/titrm_font.c, src/titrm_chars.h and src/FONT.md |
tests/ |
Host unit tests and their stand-in CE headers (tests/stubs/) |
tests/hw/ |
Hardware tests for CEmu’s autotester, and their runner run.py |
project.mk |
CEdev build rules for one example or hardware test program |
bin/, obj/ |
Build output |
make # build every example into bin/<example>/
make demo # or one of them
make hw-build # build the hardware test programs
make clean # remove all build output
The library is compiled straight into each program (see project.mk). Keep
every source file inside the repository root: on Windows, CEdev can’t build
sources reached through ...
Don’t edit src/titrm_font.c, src/titrm_chars.h or src/FONT.md by hand.
Change tools/gen_font.py and regenerate:
python tools/gen_font.py
Commit the script and the regenerated files together. CI fails if they don’t match.
docs/ is generated from the doc comments in src/titrm.h.
Doxygen reads the header into XML, and
moxygen turns the XML into one Markdown
page per group, plus the index docs/api.md.
GitHub Pages publishes the repository root from main as
https://gavinhsmith.github.io/titrmlib/, with README.md as the front page and
the API reference under docs/. Site settings are in _config.yml.
In the header:
/** @brief ... */ comment, or /**< ... */ after a field or enum value.@defgroup of its section, between @{ and
@}. Each group becomes one page.Edit the header, not docs/, then regenerate:
make docs # Doxygen on PATH
make docs DOXYGEN="/c/Program Files/doxygen/bin/doxygen" # or point at it
Doxygen fails the build if anything public is undocumented. Commit the header and the regenerated docs together; CI regenerates them with the same versions (Doxygen 1.18.0, moxygen 2.1.19) and fails if they differ.
make -C tests # build and run with cc
make -C tests CC=clang # any C99 compiler
make -C tests CC=gcc SANITIZE= # without ASan/UBSan, e.g. MinGW gcc on Windows
The unit tests don’t need CEdev or a calculator. They compile the library with
the host compiler against the headers in tests/stubs/. Drawing goes to an
in-memory 320×240 framebuffer and a stand-in keypad presses a scripted list of
keys, so layout, clipping, focus, widgets, key handling and the run loop are
tested through the public API.
tests/hw/ holds small CE programs that run in
CEmu’s cemu-autotester. For each
test, the autotester launches the program, presses keys, and compares CRCs of
video memory with the recorded screens. These tests cover what the unit tests
can’t: the real eZ80 compiler (24-bit int), graphx, the keypad and the clock.
cemu-autotester, found on PATH (CEdev ships it) or set in
CEMU_AUTOTESTER.AUTOTESTER_ROM: a TI-84 Plus CE ROM image with the
CE C libraries
(clibs.8xg) installed. It must be one of:
Asm(prgmNAME).AsmHook2 app installed. Each test first runs AsmHook2 from the
Apps menu, then runs the program from the PRGM menu.The runner picks the launch method from the ROM: arTIfiCE if AsmHook2 is on it,
Asm( otherwise. Set HW_LAUNCH=asm or HW_LAUNCH=artifice (or pass
--launch) to choose. On an arTIfiCE ROM, the program is picked by the first
letter of its name, so the ROM mustn’t hold another program that starts with the
same letter and sorts before it.
export AUTOTESTER_ROM=/path/to/ti84ce.rom
make hw-test # build and run all of them
make hw-test HW_ARGS="layout widgets" # or some of them
make hw-record # re-record the CRCs of failing screens
python tests/hw/run.py --help # all options
| Test | Checks |
|---|---|
canary |
Only the setup: a graphx program launches and exits. If it fails, check the ROM first |
glyphs |
Every character code, reverse video, box-drawing joins, word wrap |
styles |
Bold, italic, underline and strikethrough alone and combined, in color and reversed, over box drawing (unchanged), inline in a text widget, as a list’s focus highlight; tab stops in panels, text and list items |
layout |
Fixed, percent and weighted-fill sizes, nesting, clipping, hide/show reflow, destroying a subtree |
colors |
Every TERM_COLOR_*, and a colored bordered box with a list, checkbox and button inheriting its colors, and focus moving between them with [vars] and the arrows |
controls |
Checkboxes, a custom widget built with a key handler, and buttons: toggling, custom change events, focus markers, submitting, moving focus with [vars] and the arrows |
widgets |
List, input and a text log driven by key presses: wrap-around, [enter], focus moved by the app on [vars], alpha and alpha lock, [del], scrollback |
ticks |
term_set_tick with the real clock(): 20 ticks of 100 ms arrive on time |
scenes |
Switching between two scenes: each keeps its content and list selection, a scene’s handler refocuses on entry, and a hidden scene can be printed into |
overlays |
A centered dialog over a list: focus moved into it, typing, submitting and cancelling, focus given back, and the screen underneath restored exactly |
perf |
Update times when nothing changes, when one row changes and when the whole screen changes (in white on black and in color) stay within budget (the one-row budget is the 50 ms goal); a miss shows the measured time |
selfcheck |
Checks that run on the calculator and read pixels back from the screen: layout, 24-bit printf, clipping, the log ring, focus, panel limits |
Every test ends by pressing [clear] and checking for a cleared home screen.
When a screen doesn’t match, the runner saves it as a PNG in
tests/hw/build/<test>/, next to the autotester’s log.
After an intended change to what’s on screen, run make hw-record. It writes
the new CRCs into each test’s autotest.json. Open the PNGs and check them
before committing, because a recording accepts whatever was on screen.
vram_8_size) have exactly one
correct CRC, so recording replaces it.vram_16_size) differ between OS versions,
so recording adds the new one to the list.tests/hw/<name>/main.c. Keep the final screen the same on every
run: no clock values or counters, unless they only show on failure.HW_NAME_<name> = <PROGRAM> to project.mk.tests/hw/<name>/autotest.json with that program as target. Start
the sequence with action|launch, use hashWait for each screen to check,
and end with key|clear and the home-screen hash (copy it from another
test). Use "00000000" as the CRC of new screens.make hw-record HW_ARGS=<name>, check the PNGs, then run
make hw-test HW_ARGS=<name> to confirm that it passes..github/workflows/ci.yml runs on every branch push and pull request, and
before every release:
tools/gen_font.py and make docs and fails if src/ or docs/ changeThe hardware tests themselves don’t run in CI because they need a ROM. Run them locally when you change rendering, input or timing.
Set TITRM_VERSION in src/titrm.h to the new version (without the v),
run make docs, and commit. Then push a version tag to that commit:
git tag v1.0.0
git push origin v1.0.0
.github/workflows/release.yml fails if TITRM_VERSION doesn’t match the tag.
Otherwise it runs CI, then creates a draft release named
after the tag. It attaches titrmlib-<tag>.zip, which holds src/*.c,
src/*.h and the licenses, and a short “how to use” description. Add the
changes to the description on GitHub, then publish the draft.
Bugs: include
cedev-config --version) and the
calculator OS versiontests/hw/build/ if a hardware test failedFeature requests: describe the screen or interaction you’re trying to build, and what’s missing from the current API. Check ROADMAP.md first.
[dev] ..., [test] ....README.md and regenerate docs/ for public API changes, and ROADMAP.md when you finish
or add a planned item.