VT100 Animations
This is a fun exercise in retro-computing.
There is a cool website called textfiles.com, which has almost every "viral" text file archived from the 80s onward. Browsing this website is a great way to spend an afternoon relaxing and geeking out.
Of course, there is an entire subsection dedicated to VT100 animations. These are text files that contain special escape sequences that "smart" terminals (such as the VT100 and derivatives) recognize. These escape sequences can manipulate the cursor position and change font properties.
The animation "text" files were designed to be printed directly to a VT100 terminal. Unfortunately, I don't own a hardware VT100 terminal. (Although if you have a working unit that you wish to sell/donate, please let me know.)
However, all desktop Linux distributions come with a program that
emulates VT100 terminals: xterm
.
There is one problem though. xterm
runs extremely fast, and the
animation only takes a fraction of a second to run. We need to slow
down terminal emulation somehow.
Perl comes to the rescue! The following quick-and-dirty script inserts two artificial delays while printing a text file.
- Line delay: At most one line is printed every 60 seconds. This is supposed to (crudely) emulate the refresh rate of a "glass" terminal.
- Character delay: Very small delays are inserted between characters. This emulates the slow speed of a serial line. There are a few animations that are just one line long. For these, we need this extra character delay.
Both parameters can be customized using flags.
#!/usr/bin/env perl # # scat # # sleepy-cat - like cat, except delay a little bit to emulate the # behavior of an old terminal # # By default a delay is inserted after every line feed (to emulate # screen refresh), and a smaller delay is inserted between every # character (to emulate slow baud rate). # # -nXX sets the newline output rate in frames per second (default is 60) # -cXX sets the character output rate in frames per second (default 12800) # (set either option to 0 to disable) # # There are no spaces between the letter option and its number value # (i.e. "-c15" is valid, but "-c 15" is not) use strict; use warnings; use Time::HiRes qw(time usleep); use List::Util qw(max); my $linewait = 1e6 / 60; my $charwait = 1e6 / 12800; # Parse parameters while (defined($ARGV[0]) && $ARGV[0] =~ /^-/) { $_ = shift @ARGV; if (/^-n(\d+)/) {$linewait = $1 == 0? 0: 1e6 / $1;} elsif (/^-c(\d+)/) {$charwait = $1 == 0 ? 0 : 1e6 / $1;} elsif (/^-$/) {unshift @ARGV, $_; last} elsif (/^--$/) {last;} else {die "Unknown parameter $_";} } if ($charwait > 0) { $| = 1; while (<>) { my $t0 = time(); foreach (split //, $_) { print; usleep($charwait); } my $elapsed = (time() - $t0) * 1e6; usleep(max(0, $linewait - $elapsed)); } } # If charwait is disabled, we can skip many extra steps. else { while (<>) { print; usleep($linewait); } }
The results are amazing, and watching these animations is another great way to spend a geeky afternoon.
Source files
- scat.pl (or grab it from my dotfiles repo)
- bambi.vt - Bambi vs. Godzilla
- VT100 Art and Animations - more cool animations
Suggestions? Comments?
Please contact me.