GlkTerm Library: version 1.0.5
Glk API: version 0.7.5
Designed by: Andrew Plotkin erkyrath@eblong.com
Homepage: http://eblong.com/zarf/glk/
This is source code for an implementation of the Glk library which runs in a terminal window, using the curses.h library for screen control. Curses.h (no relation to the Meldrews) should be available on all Unix systems.
This source code is not directly applicable to any other display system. Curses library calls are scattered all through the code; I haven't tried to abstract them out. If you want to create a Glk library for a different display system, you'd best start over. Use GlkTerm for a starting point for terminal-window-style display systems, and MacGlk or XGlk for graphical/windowed display systems.
This project uses CMake as the build system, providing better cross-platform support and dependency management.
- CMake 3.16 or higher
- A C compiler (GCC recommended)
- A C++ compiler (for some interpreters)
- ncurses development libraries
- SDL2 and SDL2_mixer development libraries (optional, for sound support)
- zlib development libraries (for SCARE interpreter)
- .NET runtime (optional, for FrankenDrift interpreter when enabled)
-
Create a build directory:
mkdir build cd build -
Configure with CMake:
cmake ..
-
Build the library:
make
-
Enable/disable sound support:
cmake .. -DENABLE_SOUND=OFF # Disable sound cmake .. -DENABLE_SOUND=ON # Enable sound (default)
-
Set build type:
cmake .. -DCMAKE_BUILD_TYPE=Debug # Debug build cmake .. -DCMAKE_BUILD_TYPE=Release # Release build (default)
-
Enable/disable specific interpreters:
cmake .. -DWITH_SCOTT=OFF # Disable Scott Adams interpreter cmake .. -DWITH_TADS=OFF # Disable TADS interpreter cmake .. -DWITH_FRANKENDRIFT=ON # Enable FrankenDrift (.NET) interpreter
All interpreters are enabled by default except FrankenDrift, which requires .NET.
GlkTerm includes a collection of 16 interactive fiction interpreters adapted to work with the glkterm library. These interpreters support a wide variety of adventure game formats including:
- Z-machine games (Infocom format) - bocfel
- Glulx games - git, glulxe
- Scott Adams games - scott, plus
- TADS games - tadsr
- Alan games - alan2, alan3
- Classic adventure systems - advsys, agility, hugo, jacl, level9, magnetic, scare, taylor
- .NET interpreter - frankendrift (disabled by default)
./build/terps/bocfel zork1.z5 # Play Zork I
./build/terps/git adventure.ulx # Play a Glulx game
./build/terps/scott adventure1.dat # Play Scott Adams adventure
./build/terps/tadsr game.gam # Play a TADS gameπ For detailed information about each interpreter, supported file formats, and usage examples, see terps/README.md.
GlkTerm includes a smart launcher system that automatically detects game formats and launches the appropriate interpreter. This eliminates the need to manually select interpreters for different game files.
# Automatically detect and launch any supported game
./build/glkcli mygame.z5 # Detects Z-code, launches with bocfel
./build/glkcli adventure.ulx # Detects Glulx, launches with git
./build/glkcli story.t3 # Detects TADS, launches with tadsr
# Show detected format without launching
./build/glkcli -f mygame.gblorb # Shows: "Detected format: Glulx"
# Verbose output with additional information
./build/glkcli -v adventure.z8 # Shows detection process and game info- Header-based detection: Examines file magic bytes for reliable format identification
- Extension-based fallback: Uses file extensions when header detection is inconclusive
- Blorb support: Automatically extracts and detects games embedded in Blorb containers (.gblorb, .blb)
The launcher supports all 15+ game formats and automatically finds the correct interpreter from the collection built with glkterm.
π For complete launcher documentation, usage examples, and advanced features, see launcher/README.md.
After building, you can install the library system-wide:
sudo make installThis will install:
libglkterm.ato the library directory- Header files to the include directory
Make.glktermto the include directory (for legacy Makefile compatibility)- All enabled interpreter executables to the bin directory
find_package(glkterm REQUIRED)
target_link_libraries(your_target glkterm)Include the generated Make.glkterm file in your Makefile:
include Make.glkterm
your_program: your_program.o
$(CC) -o your_program your_program.o $(GLKLIB) $(LINKLIBS)Recommended: Use the launcher system for automatic format detection:
./build/glkcli mygame.z5 # Automatically detects format and launches
./build/glkcli -f mygame.blorb # Show detected format
./build/glkcli -v adventure.ulx # Verbose outputManual: Interpreter executables are also available in the build/terps/ directory (or in your system's bin directory if installed). Each interpreter accepts game files and glkterm command-line options:
# Basic usage (manual interpreter selection)
./build/terps/bocfel story.z5 # Z-machine games
./build/terps/git game.ulx # Glulx games
./build/terps/scott adventure.dat # Scott Adams games
# With glkterm options
./build/terps/bocfel -width 132 -height 40 story.z8π See terps/README.md for detailed usage examples, file format support, and interpreter-specific options.
GlkTerm can accept command-line arguments both for itself and on behalf of the underlying program. These are the arguments the library accepts itself:
-
-width NUM,-height NUM: Set the screen width and height manually. Normally GlkTerm determines the screen size itself by asking the curses library. If this doesn't work, you can set a fixed size using these options. -
-ml BOOL: Use message line (default "yes"). Normally GlkTerm reserves the bottom line of the screen for special messages. By setting this to "no", you can free that space for game text. Note that some operations will grab the bottom line temporarily anyway. -
-revgrid BOOL: Reverse text in grid (status) windows (default "no"). Set this to "yes" to display all textgrid windows (status windows) in reverse text. -
-historylen NUM: The number of commands to keep in the command history of each window (default 20). -
-border BOOL: Force one-character borders between windows. The default is "yes", but some games switch these off. Set "yes" to force them on, or "no" to force them off, ignoring the game's request. These are lines of '-' and '|' characters. Without the borders, there's a little more room for game text, but it may be hard to distinguish windows. The-revgridoption may help. -
-precise BOOL: More precise timing for timed input (default "no"). The curses.h library only provides timed input in increments of a tenth of a second. So Glk timer events will only be checked ten times a second, even on fast machines. If this isn't good enough, you can try setting this option to "yes"; then timer events will be checked constantly. This busy-spins the CPU, probably slowing down everything else on the machine, so use it only when necessary. For that matter, it may not even work on all OSes. (If GlkTerm is compiled without support for timed input, this option will be removed.) -
-version: Display Glk library version. -
-help: Display list of command-line options.
NUM values can be any number. BOOL values can be "yes" or "no", or no value to toggle.
When you compile a Glk program and link it with GlkTerm, you must supply one more file: you must define a function called glkunix_startup_code(), and an array glkunix_arguments[]. These set up various Unix-specific options used by the Glk library. There is a sample "glkstart.c" file included in this package; you should modify it to your needs.
The glkunix_arguments[] array is a list of command-line arguments that your program can accept. The library will sort these out of the command line and pass them on to your code. The array structure looks like this:
typedef struct glkunix_argumentlist_struct {
char *name;
int argtype;
char *desc;
} glkunix_argumentlist_t;
extern glkunix_argumentlist_t glkunix_arguments[];In each entry:
nameis the option as it would appear on the command line (including the leading dash, if any)descis a description of the argument; this is used when the library is printing a list of optionsargtypeis one of the following constants:glkunix_arg_NoValue: The argument appears by itselfglkunix_arg_ValueFollows: The argument must be followed by another argument (the value)glkunix_arg_ValueCanFollow: The argument may be followed by a value, optionallyglkunix_arg_NumberValue: The argument must be followed by a numberglkunix_arg_End: The array must be terminated with an entry containing this value
glkunix_argumentlist_t glkunix_arguments[] = {
{ "", glkunix_arg_ValueFollows, "filename: The game file to load." },
{ "-hum", glkunix_arg_ValueFollows, "-hum NUM: Hum some NUM." },
{ "-bom", glkunix_arg_ValueCanFollow, "-bom [ NUM ]: Do a bom (on the NUM, if given)." },
{ "-goo", glkunix_arg_NoValue, "-goo: Find goo." },
{ "-wob", glkunix_arg_NumberValue, "-wob NUM: Wob NUM times." },
{ NULL, glkunix_arg_End, NULL }
};After the library parses the command line, it calls glkunix_startup_code():
int glkunix_startup_code(glkunix_startup_t *data);This should return TRUE if everything initializes properly. If it returns FALSE, the library will shut down without ever calling your glk_main() function.
The data structure contains:
typedef struct glkunix_startup_struct {
int argc;
char **argv;
} glkunix_startup_t;These Unix Glk library functions are available during startup:
strid_t glkunix_stream_open_pathname(char *pathname, glui32 textmode, glui32 rock);Opens an arbitrary file in read-only mode. Only available during glkunix_startup_code().
void glkunix_set_base_file(char *filename);Sets the library's idea of the "current directory" for the executing program.
The library requires ncurses. You may have to change #include <curses.h> to #include <ncurses.h> on some systems.
- SunOS: May need special include/library paths and
NO_MEMMOVEdefinition - Solaris: Compiles as-is (older versions may need
memmove()adjustments) - IRIX: Compiles as-is
- HPUX: May need to disable
OPT_TIMED_INPUTand removeKEY_END/KEY_HELPreferences - AIX: Similar to HPUX requirements
- FreeBSD: Compiles as-is
- Unixware: May need to use
ccinstead ofgcc
glk_*functions: Glk API functions declared inglk.hgli_*functions: Internal GlkTerm library implementation functions declared inglkterm.h
The code catches every error that can be caught and prints visible warnings. It should be portable to any C environment with ANSI stdio and curses.h libraries.
- Window resizing may not work properly on some Unix systems (SIGWINCH handling)
- During
glk_exit(), the "hit any key to exit" prompt doesn't do paging - Could accept more style hints (indentation, centering, bold, underline/italics)
- No visible indication of paging in windows that need to page
- Window border artifacts may remain when closing windows
- Added sound and style support
- Fixed struct initialization bug in
gli_date_to_tm() - Replaced
tmpnam()withmkstemp()
- Updated Blorb-resource functions for FORM chunks (Glk 0.7.4)
- Added autosave/autorestore hooks stub
- Added Blorb-resource functions (Glk 0.7.4)
- Updated external filename handling
- Fixed
glk_put_char_uni()output bug - Fixed file read/write positioning bug
- Fixed stream memory allocation issues
- Added improved sound function stubs (Glk 0.7.3)
- Added date-time functions (Glk 0.7.2)
- Fixed Unicode normalization and case-changing bugs
- Support for Glk 0.7.1 features: window borders, line input terminators, echo control, Unicode normalization
- Added
glkunix_stream_open_pathname_gen()
The GlkTerm, GiDispa, and GiBlorb libraries, as well as the glk.h header file, are copyright 1998-2016 by Andrew Plotkin. All are distributed under the MIT license; see the "LICENSE" file.
The CMake build system preserves all functionality of the original Makefile:
- Builds the same static library (
libglkterm.a) - Generates the same
Make.glktermfile for compatibility - Handles the same dependencies (ncurses, SDL2/SDL2_mixer)
- Uses the same compilation flags
The main improvements:
- Better dependency detection using pkg-config
- Cross-platform support
- Option to disable sound support at configure time
- Modern installation and packaging support