Ttyrec
A ttyrec is a recording of a terminal. For example, you can play a game of NetHack in a text-mode terminal, and record everything that NetHack shows. nethack.alt.org and hardfought.org record all games.
ttyrec files can be played back with several programs:
Name | Can rewind | Can play compressed (e.g. .gz) | Supports logarithmic time compression | Notes |
---|---|---|---|---|
IPBT | Yes (including frame by frame control) | No | Yes | May have issues emitting ncurses output, and is very slow to read ttyrecs |
playttyrec.c (also see https://www.stack.nl/~jilles/games/) | No | No | No | Supports "fake" timing, where ttyrecs don't contain time information |
ttyplay and ttyrec | No | No | No | Part of the original ttyrec package. |
termplay | Yes (time based control, not frame by frame) | Yes | No | Note that the bundled termcat package may mangle timing |
Jettyplay | Yes (full timing and frame by frame control) | Yes | Yes | Uses a GUI, but has significantly more features including a timeline and online URL loading. |
A game may be split into many ttyrec files. There are multiple approaches for merging them into a single game:
Name | Notes |
---|---|
cat *.ttyrec > path/to/out.ttyrec | Just by using built in Unix commands. Note that large time differences are maintained, so a player with logarithmic compression may be required. |
termcat | Timing may be mangled. See details. |
ttytie | Playback may break after the first concatenated file. |
ttyrec format
A ttyrec consists of many frames. Each frame is made up of a twelve-byte header and an arbitrarily long data block. The twelve-byte header contains two pieces of information: how much data is in this frame and a timestamp. The timestamp is very precise; it has microsecond precision. The header bytes are aligned like so:
1 2 3 4 5 6 7 8 9 A B C \-----/ \-----/ \-----/ sec usec len
The bytes are in little-endian order (meaning least significant bytes first). You can portably read and process frames like this, in C:
while (fread(header, 1, 12, stdin) == 12) { sec = (((((header[ 3] << 8) | header[ 2]) << 8) | header[1]) << 8) | header[0]; usec = (((((header[ 7] << 8) | header[ 6]) << 8) | header[5]) << 8) | header[4]; len = (((((header[11] << 8) | header[10]) << 8) | header[9]) << 8) | header[8]; received = fread(data, 1, len, stdin) if (len != received) break; /* process data */ } /* either the ttyrec is done or we had an error */
- This page is a stub. Should you wish to do so, you can contribute by expanding this page.