joeylib2/docs/GettingStarted.adoc
2026-10-19 15:46:47 -05:00

714 lines
26 KiB
Text

== Getting Started
=== Setting Up the Toolchains
JoeyLib cross-compiles for five machines and for DVX, a DOS desktop whose
programs run in windows (see <<_dvx_programs>>), builds native programs for
the machine you work on through SDL3 (see <<_sdl3_programs>>), builds web
pages through Emscripten (see <<_web_programs>>), builds Mac apps through
zig and Apple's SDK (see <<_macos_programs>>), and builds PSP homebrew
through pspdev (see <<_psp_programs>>). It builds on Linux x86-64,
and on Windows inside WSL2. One script installs every cross toolchain, pinned
to a known-good version and checked against a published checksum, into
`toolchains/` in the repository. The only things it installs anywhere else
are ordinary packages from your distribution (apt on Debian and Ubuntu, dnf
on Fedora), and only when you ask it to.
Two commands set up a new machine:
[source,console]
----
$ ./install.sh deps toolchains --install
$ ./install.sh install toolchains
----
The first installs the distribution packages the toolchains need; it runs
`sudo` once. The second downloads or builds every cross toolchain. The first
run takes about an hour, almost all of it compiling the Apple IIgs and Amiga
compilers. To start working sooner, install only the ports you need:
[source,console]
----
$ ./install.sh install toolchain:dos toolchain:atarist
----
Running `install` again is cheap. Components that are already current are
skipped, and a component is rebuilt only when its pinned version changes.
No environment setup is needed afterwards. `make` reads the tool paths the
installer records in `toolchains/config.mk`, and the scripts in
`scripts/` load the same settings themselves. To use a cross compiler by hand
in a shell, `source toolchains/env.sh` sets the same variables.
If a port's toolchain is missing, its build stops at once and says what to
install:
[source,console]
----
$ make amiga
make/amiga.mk:13: *** toolchain:amiga is not installed; run: ./install.sh install toolchain:amiga. Stop.
----
Check what the build can see:
[source,console]
----
$ make status
Toolchain availability:
iigs: yes
amiga: yes
atarist: yes
dos: yes
x68000: yes
dvx: yes
----
==== Installer reference
`+./install.sh [options] COMMAND [TARGETS...]+`, run from the top of the
repository.
[cols="1,3"]
|===
| Command | What it does
| `list`
| Every component, the groups it belongs to, and whether it is current,
outdated, or missing.
| `install TARGETS`
| Installs or updates the targets and everything they depend on, and
smoke-tests each one it installs. A failure does not stop the rest; the
failures are listed at the end.
| `deps TARGETS`
| Lists the distribution packages the targets need and which are missing.
With `--install`, installs the missing ones.
| `doctor`
| Checks the host, then smoke-tests every installed component (each cross
compiler compiles a file, and every prebuilt program must find its shared
libraries, for example). It reports anything out of date, any component
whose files have gone, and any part of a port you installed only partly,
such as FS-UAE without a Kickstart.
| `+import PATH...+`
| Installs the files that are not downloaded (see <<Firmware that is not
downloaded>>) from files, folders, `.zip` archives, or Amiga `.adf` disk
images, matched by checksum.
| `bundle FILE`
| Packs those files, as present on this machine, into `FILE` (a `.tar.gz`)
for a project to host.
|===
A target is a component name from `list`, or a group:
[cols="1,3"]
|===
| Target | Means
| `toolchain:PORT`
| Everything needed to build for one port: `iigs`, `amiga`, `atarist`, `dos`,
`x68000`, `dvx`, `sdl3` (SDL 3, built as a static library that every SDL3
program links in, so it runs without SDL installed), `web` (Emscripten,
through emsdk, and SDL 3 built with it), `macos` (zig, Apple's macOS SDK,
and SDL 3 built with them; there is no emulator: nothing here runs Mac
programs), `win32` (llvm-mingw; its emulator is a portable Wine), `win16`
(Open Watcom; its emulator is Windows for Workgroups 3.11 in DOSBox Staging,
set up from your own install disc, see <<Firmware that is not downloaded>>),
or `psp` (pspdev's prebuilt release, and SDL 3 built with it; its emulator
is PPSSPP's headless build, patched for the tests).
| `emulator:PORT`
| Everything needed to run that port's programs: the emulator and its
firmware.
| `PORT`
| Both of the above.
| `toolchains`
| Every port's toolchain.
| `emulators`
| Every port's emulator.
| `all`
| Everything except optional components (`dvx`, which unpacks DVX from a DVX
tree of yours), which are installed by name. `toolchains` and `emulators`
leave them out too.
|===
[cols="1,3"]
|===
| Option | Effect
| `-y`, `--yes`
| Install missing distribution packages without stopping to ask.
| `--install`
| With `deps`: install the missing packages.
| `--force`
| Reinstall components even when they are current.
| `--jobs N`
| Parallel build jobs. The default is every core.
| `--keep-build`
| Keep the scratch build trees (normally deleted after a successful install).
| `--llvm816-dir PATH`
| Use an existing checkout of llvm816, the IIgs compiler, instead of cloning
it. For working on the compiler and JoeyLib together. The setting is
remembered; `--llvm816-dir clone` goes back to a managed clone.
| `--dvx-dir PATH`
| The DVX tree the `dvx` component takes DVX and its SDK from: its
distribution, `dist/dvx.zip` (DVX as it installs) and `dist/sdk.zip` (the
SDK). The default is a `dvxgui` checkout beside this repository; the
setting is remembered. The component only reads that tree: it unpacks both
zips into `toolchains/opt/dvx`, and a new zip there makes the component out
of date, so `install dvx` unpacks it again. (A tree whose `dist/` has no
`sdk.zip` yet gives its built SDK, `bin/sdk`, instead.)
|===
Everything the installer creates stays inside `toolchains/`:
[cols="1,3"]
|===
| Path | Contents
| `toolchains/opt/`
| The installed components, one directory each.
| `toolchains/firmware/`
| ROM and system-disk images for the emulators.
| `toolchains/cache/`
| Downloads, kept and re-verified by checksum on reuse, and scratch build
trees.
| `toolchains/state/`
| Which version of each component is installed, and settings such as
`--llvm816-dir` and `--dvx-dir`.
| `toolchains/config.mk`, `toolchains/env.sh`
| The tool paths, for `make` and for shells.
|===
Nothing in `toolchains/` is part of the repository: delete the whole folder
to return the machine to a clean state, and `./install.sh` re-creates it. The
installer itself lives in `install.sh` and `installer/` (its component
recipes, patches, and package lists), and the build helpers the makefiles call
live in `make/support/`.
=== Building
[source,console]
----
$ make # every target whose toolchain is installed
$ make iigs # Apple IIgs only
$ make amiga # Commodore Amiga only
$ make atarist # Atari ST only
$ make dos # MS-DOS only
$ make x68000 # Sharp X68000 only
$ make dvx # DVX only
$ make sdl3 # native programs through SDL3 only
$ make web # web pages through Emscripten only
$ make macos # universal Mac apps only
$ make win32 # Windows programs only
$ make win16 # Windows 3.x programs only
$ make psp # PSP homebrew (EBOOT.PBP) only
$ make haiku # Haiku x86_64 programs only
$ make haiku32 # Haiku x86 (gcc 2.95, the BeOS ABI) programs only
$ make beos # BeOS R5 x86 programs only
$ make clean # remove all build outputs
----
Built programs land under `build/<platform>/bin/`. The IIgs additionally
produces a bootable disk image:
[source,console]
----
$ make iigs-disk # build/iigs/bin/joey.2mg: the first examples that fit
$ make iigs-game-disks # build/iigs/bin/NAME.2mg: every example, each bootable
----
[TIP]
====
Never judge a retro build by its exit status alone. Check that the file you
expect actually appeared and has a recent timestamp. `make iigs` builds the
library but *no examples* -- `make iigs-disk` and `make iigs-game-disks` are
what build and package them.
====
=== Hello, JoeyLib
The smallest complete program. This is `examples/hello/hello.c`:
[source,c]
----
#include <stdio.h>
#include <joey/joey.h>
int main(void) {
jlConfigT config;
config.codegenBytes = 8 * 1024;
config.noAudio = true;
if (!jlInit(&config)) {
fprintf(stderr, "jlInit failed: %s\n", jlLastError());
return 1;
}
printf("JoeyLib %s\n", jlVersionString());
printf("Platform: %s\n", jlPlatformName());
printf("Hello from JoeyLib.\n");
jlShutdown();
return 0;
}
----
Four things to notice, because they apply to every JoeyLib program:
. *One header.* `#include <joey/joey.h>` pulls in everything except the
optional serial add-on.
. *Set every field of `jlConfigT`.* It is read whole, so a field left unset
holds whatever was in memory. `noAudio` says whether the program wants sound:
`jlInit` starts audio unless it is `true`.
. *`jlInit` can fail*, and when it does `jlLastError()` tells you why. Always
check it.
. *`jlShutdown` is not optional.* It restores the display mode, releases the
Memory Manager blocks or DOS memory the library took, and on several ports
un-hooks interrupt vectors. Skipping it can leave the machine in an unusable
state.
=== Something on the Screen
`hello.c` prints text but never draws. Here is the smallest program that puts
graphics on screen and waits for a keypress:
[source,c]
----
#include <joey/joey.h>
int main(void) {
jlConfigT config;
jlSurfaceT *stage;
uint16_t colors[JL_SURFACE_COLORS_PER_PALETTE];
uint8_t i;
config.codegenBytes = 8 * 1024;
config.noAudio = true;
if (!jlInit(&config)) {
return 1;
}
stage = jlStageGet(); // the library-owned back buffer
// Build palette 0. Entry 0 is forced black whatever we put here.
for (i = 0; i < JL_SURFACE_COLORS_PER_PALETTE; i++) {
colors[i] = 0x000;
}
colors[1] = 0xFFF; // white
colors[2] = 0xF00; // red
colors[3] = 0x00F; // blue
jlPaletteSet(stage, 0, colors);
// Every scanline uses palette 0 (this is also the default).
jlScbSetRange(stage, 0, JL_SURFACE_HEIGHT - 1, 0);
jlSurfaceClear(stage, 0);
jlFillRect(stage, 40, 30, 240, 140, 3);
jlDrawRect(stage, 40, 30, 240, 140, 1);
jlDrawLine(stage, 0, 0, JL_SURFACE_WIDTH - 1, JL_SURFACE_HEIGHT - 1, 2);
jlStagePresent(); // nothing is visible until this runs
jlWaitForAnyKey();
jlShutdown();
return 0;
}
----
The critical line is `jlStagePresent()`. All drawing goes to an off-screen
back buffer called the *stage*; nothing reaches the display until you present.
=== Running What You Built
`joey-run`, at the top of the repository, starts a built program in the right
emulator (an SDL3 program needs none: it runs on your machine). The emulators,
and the firmware they boot, come from the installer:
[source,console]
----
$ ./install.sh install emulators # every machine
$ ./install.sh install emulator:dos # or just one
----
MAME (for the IIgs and X68000) is always built from source, because the test
tests need JoeyLib's patches to it. DOSBox Staging is upstream's own Linux
release. Hatari and FS-UAE are distribution packages on Debian and Ubuntu;
Fedora does not ship the versions the tests expect, so there the installer
builds both from source.
Point `joey-run` at a program, or name an example together with `--port`:
[source,console]
----
$ ./joey-run build/dos/bin/DRAW.EXE
$ ./joey-run build/amiga/bin/Draw
$ ./joey-run --port atarist draw
$ ./joey-run build/iigs/bin/DRAW.2mg
$ ./joey-run --port dvx draw
$ ./joey-run --port sdl3 draw
$ ./joey-run --port web draw
$ ./joey-run --port win32 draw
$ ./joey-run --port win16 draw
$ ./joey-run --port psp --headless --snapshot draw.png draw
$ ./joey-run --port haiku draw
$ ./joey-run --port beos draw
----
It recognizes the machine from the file itself. Interactive runs use the
program's own folder or disk image, so saves and logs persist from one run to
the next. Nothing is written to your home directory.
[cols="1,3"]
|===
| Option | Effect
| `--port PORT`
| The machine, when naming an example rather than a file.
| `--data DIR`
| Copy the files in `DIR` into the program's `DATA` folder for this run, for
example the game an interpreter plays.
| `--headless`
| No window and no sound, for scripts and continuous integration. Stops after
60 seconds unless `--seconds` says otherwise.
| `--seconds N`
| Stop after `N` seconds.
| `--snapshot FILE`
| Save a PNG of the screen when the run stops.
| `--machine rom01`
| Apple IIgs: the ROM 01 machine instead of ROM 03.
| `--machine st`
| Atari: Hatari's machine, `st`, `megast`, `ste`, or `megaste`. By default an
ST-build program (`make atarist`) gets a plain ST and an STe-build one
(`make ste`) an STe; the STe build runs only on `ste` and `megaste`.
| `--machine a1200`
| Amiga: FS-UAE's machine, `a500` (the default), `a1200` (68EC020, AGA), or
`a4000` (68040, AGA), each on its own Kickstart 3.1. The AGA ones need their
Kickstarts (`./install.sh install emulator:aga`).
| `--ram SIZE`
| Apple IIgs: MAME's memory size. The default is `4M`.
| `--debug`
| Apple IIgs and X68000: start MAME's debugger.
| `--serial HOST:PORT`
| Connect the machine's serial port to the TCP server at `HOST:PORT`. See
<<Serial Ports>>.
| `--serial-listen PORT`
| The machine's serial port waits for a TCP connection on `PORT` instead.
| `--serial-baud N`
| Apple IIgs and X68000: the rate MAME's end of the wire runs at. The
default is 9600.
| `-- ARGS`
| Pass `ARGS` to the program. DOS, SDL3, Win32, and Win16 only: the other
machines' autostart cannot pass arguments, and a page and a PSP program have
none.
|===
==== DVX
`joey-run` runs a DVX program in DOSBox Staging on a copy of the DVX the
installer took from a DVX tree (`./install.sh install dvx`), set up so DVX
boots straight into the program: it is DVX's desktop program, in its own
window on a 1024x768 desktop (640x480 with `--headless`), with a Sound
Blaster 16. The DVX of interactive runs is kept in `build/dvx/run`, so what
the program saves, in its folder in DVX's `USER` folder, is there the next
time; closing DOSBox ends the run. When the program ends, DVX stays up with an empty
desktop.
==== SDL3
An SDL3 program is a native program, so `joey-run` simply starts it, in a
window; running the file yourself does the same. `--headless` runs it on a
private virtual display at one window pixel per stage pixel, so a
`--snapshot` is exactly the 320x200 stage. The window's size, shape, and full
screen are set by environment variables (<<_sdl3_programs>>). `joey-run`
connects no serial port to it: the program opens the computer's own
(<<_serial_ports>>).
==== Web
A web program is a page: `joey-run` serves its folder over HTTP on this
machine (to this machine only) and opens it in your browser; Ctrl+C stops the
server. With `--headless` it runs in headless Chromium instead, at one canvas
pixel per stage pixel, so a `--snapshot` is the stage. Its `DATA/` is packed
in when it is built, so `--data` does not apply.
==== macOS
Nothing here runs a Mac program: copy its app, `build/macos/bin/NAME.app`, to
a Mac and open it there (<<_macos_programs>>). `joey-run` knows one when it
sees it and says so.
==== Win32
A Windows program runs under Wine: in a window on your display, with its
Wine settings kept in the project's `build/win32/prefix` so they are set up
once (nothing goes in `~/.wine`; a run with `--serial` uses a private one, so
the kept COM1 is left alone). The window's size, shape, and full screen are
set by the same environment variables as SDL3's, and Alt+Enter switches. With
`--headless` it runs on a private virtual display at one pixel per stage
pixel, so a `--snapshot` is the stage.
==== Win16
A Windows 3.x program runs on Windows for Workgroups 3.11 in DOSBox Staging,
on a fresh copy, each run, of the Windows the installer set up from your own
disc (`./install.sh install emulator:win16`): 800x600 in 256 colors through
the S3 Trio64V+ driver, with Windows' Sound Blaster driver and two drivers
of JoeyLib's own: KPJOY.DRV, the joystick driver Windows 3.1 lacks (DOSBox's
game port, two sticks), and KPCOMM.DRV in place of Windows' COMM.DRV (COM1
up to 115200 baud). Their components, `kpjoy` and `kpcomm`, build them from
the kpjoy and mscomm projects, checkouts beside JoeyLib's (`../kpjoy`,
`../mscomm/drv`; `KPJOY_DIR` and `KPCOMM_DIR` name others). The program is
Windows' shell, so Windows ends when the program does, and its folder is
drive D:, so what it saves stays there. The window's size, shape, and full
screen are set by the same environment variables as SDL3's: `joey-run` puts
them in the DOS environment Windows starts from. Alt+Enter is DOSBox's own
full-screen key, so the program switches with Alt and the keypad's Enter.
With `--headless` it runs on a private virtual display at one window pixel
per stage pixel, and a `--snapshot` is DOSBox's picture of the whole 800x600
screen.
==== PSP
A PSP program runs only with `--headless` here, under PPSSPP's headless
build (`./install.sh install emulator:psp`), from a copy of its folder on a
private memory stick, `PSP/GAME/NAME`, as on a PSP. PPSSPP checks every
memory access as a PSP does: an unaligned one stops the run, and `joey-run`
names the function it was in. A `--snapshot` is the PSP's whole 480x272
screen. To play the program, copy `build/psp/bin/NAME` into `PSP/GAME/` on
a PSP's memory stick, or open its `EBOOT.PBP` in PPSSPP. The PSP has no
serial port.
==== Haiku and BeOS
A Haiku (`haiku`, `haiku32`) or BeOS R5 (`beos`) program runs in that port's
VM under QEMU (`./install.sh install emulator:haiku`, `emulator:haiku32`, or
`emulator:beos`), in QEMU's window, from a copy of its folder on a second
disk. The machine boots from a disk it never writes to, runs the program,
and powers off when the program ends; what the program wrote in its folder
(saves, its log) is then copied back. The window's size, shape, and full
screen are set by the same environment variables as SDL3's. Haiku's VM has
sound; BeOS's has none, and is taken through R5's boot loader menu to its
fail-safe video mode (1024x768, 16-bit color), as R5 has no driver for any
of QEMU's video cards. With `--headless` it runs without a window at one
window pixel per stage pixel; `--seconds` counts from when the program
starts, after the boot, and a `--snapshot` is QEMU's picture of the whole
screen. Neither has a serial port here.
A headless run with a snapshot is the quickest way to check a change, and on
SDL3 it takes seconds, not the minutes an emulated machine needs:
[source,console]
----
$ ./joey-run --headless --seconds 5 --snapshot draw.png --port sdl3 draw
$ ./joey-run --headless --seconds 30 --snapshot draw.png --port dos draw
----
==== The Apple IIgs
The IIgs runs programs from disk images. `make iigs-game-disks` builds a
bootable one for every example, such as `build/iigs/bin/DRAW.2mg`, which is
also how a game ships. Given a data disk instead, such as `joey.2mg`, `joey-run` boots
GS/OS beside it and you open the program in the Finder. Given a bare program,
`build/iigs/bin/DRAW`, it builds both disks itself, which needs the IIgs
toolchain.
==== Serial Ports
`--serial HOST:PORT` plugs the emulated machine's serial port into a TCP
connection: to a BBS, a program of your own, `nc -l PORT`, or another
`joey-run` started with `--serial-listen PORT`, which waits for the
connection instead. `HOST` is a name or an IPv4 address, and a listening
port accepts connections on every network interface. The link carries raw
bytes, with no telnet negotiation. `examples/sertest` sends a banner and then
echoes whatever it receives, which makes it a quick test of a link:
[source,console]
----
$ nc -l 2323 # in one terminal
$ ./joey-run --serial localhost:2323 --port dos sertest
----
The port is each machine's usual one:
[cols="1,2,3",options="header"]
|===
| Machine | Port | How the link is made
| Apple IIgs
| The modem port
| MAME connects by itself. To listen, `socat` holds the TCP port and MAME
connects to it. The printer port and a Super Serial Card are not connected.
| X68000
| The RS-232C port
| As on the IIgs.
| Atari ST
| The Modem port
| Hatari's serial port can only be a device, so `socat` joins a
pseudo-terminal to the network both ways.
| Amiga
| `serial.device` unit 0
| FS-UAE listens by itself, and holds the whole machine until the connection
arrives. To connect out, `socat` joins a pseudo-terminal to the network.
| DOS
| COM1
| DOSBox does both by itself.
| DVX
| COM1
| As on DOS; DVX's serial library drives the port.
| Win16
| COM1
| As on DOS; Windows' own communications driver drives the port.
| Win32
| COM1
| As on the ST: Wine's COM1 can only be a device, so `socat` joins a
pseudo-terminal to the network both ways.
| SDL3, macOS, Haiku, BeOS
| The computer's own
| Not connected by `joey-run`: these programs run on a real computer (or
Haiku's and BeOS's VMs), and open its serial device themselves, a USB
adapter included. See <<_sdl3_programs>>, <<_macos_programs>>, and
<<_haiku_and_beos_programs>> for which device and how to choose another.
| Web, PSP
| None
| These have no serial port; `jlSerialOpen` fails there.
|===
`socat` comes from your distribution: `./install.sh deps host --install`
fetches it with the other host tools, and `joey-run` says so when a run needs
it and it is missing.
A few differences are worth knowing:
* On the IIgs and X68000 MAME's null modem clocks the wire, at 9600 baud,
8N1, unless `--serial-baud` says otherwise. A program that opens the port at
another rate receives garbage. The other emulators pass bytes at whatever
rate the program sets.
* When nothing answers at `HOST:PORT`, `joey-run` stops, except on the IIgs
and X68000, where MAME prints `Unable to load image` and runs with the port
unplugged.
* While a port is listening, what the program sends waits for the connection,
except on DOS, DVX, and Win16, where DOSBox drops it just as a cable with
nothing on the other end would. `examples/sertest` sends its banner at once,
so there a client that connects late sees only the echo.
==== Firmware that is not downloaded
Almost everything the emulators need is downloaded: EmuTOS for the Atari ST;
the Apple IIgs ROMs, GS/OS 6.0.4, and the CFFA2 card's firmware; and Sharp's own
free release of the X68000 IPL-ROM and Human68k 3.02. A few files are not,
because they were never released for free: the Amiga Kickstart 3.1 ROM, the
Amiga `serial.device` and `lowlevel.library` from Workbench 3.1 (Kickstart
3.1 has neither in ROM, and a program cannot open the serial port without
the one or see a joystick without the other), the A1200's and A4000's
Kickstart 3.1 (optional: only for running the Amiga programs on those
machines), the X68000 CG (font) ROM,
for the Win16 port the Windows for Workgroups 3.11 install disc (as an
`.iso`) and the S3 Trio64V+ 1.70.04 Windows 3.1 display driver, from which
the installer sets Windows up unattended (and, optionally, Microsoft's WinG
1.0 SDK, `WING10.EXE`, whose runtime the Win16 port draws through when it is
installed: import it, then `./install.sh install wing`; archive.org keeps a
copy), and for the BeOS port the BeOS 5
Professional CD (its CloneCD `.img`, or the `.7z` holding it), from which
the installer takes R5's headers and libraries and makes the VM. Supply your
copies once:
[source,console]
----
$ ./install.sh import ~/my-roms
----
`import` takes files, folders, `.zip` and `.7z` archives, and Amiga `.adf` disk images
(point it at your Workbench 3.1 disk for `serial.device` and
`lowlevel.library`, and at the S3
driver's `.zip` for its three files), identifies each file by its checksum
(the list is `installer/files.sha1`), and puts it in place.
A project that hands its setup to testers can host these files instead:
`./install.sh bundle joeylib-private.tar.gz` packs the ones present on
a machine that has them, and setting `JOEY_BUNDLE_URL` to where it is hosted,
in `installer/bundle.conf`, makes every `install` fetch it automatically.
=== The Example Programs
The `examples/` directory is the best available reference, and every example is
built for, and runs on, every platform. JoeyLib draws no text, so the examples
that show words share a small 5x7 font, `examples/common/exampleFont.c`:
[cols="1,4", options="header"]
|===
|Example |What it shows
|`hello` |The smallest program: its greeting, version, and machine on the screen in the default palette, and a key to end it.
|`draw` |Every drawing primitive, laid out in four quadrants.
|`pattern` |Palette and per-scanline palette (SCB) work.
|`keys` |Typed-character input, the key predicates, and the mouse.
|`joy` |Joystick axes, buttons, and recalibration.
|`sprite` |Sprite loading, compiling, save-under, and restore.
|`scroll` |A scrolling tile layer under a sprite, with a frame-rate bar.
|`audio` |Tracker music, `.MOD` playback, digital sound effects, a streamed sound, and the noise generator.
|`save` |Save files and the disk-space query.
|`tilebank` |Loading a baked tile bank both ways, and a bank for another machine refused.
|`serial` |A terminal on the optional RS-232 add-on.
|`sertest` |A serial self-test: a banner, then an echo of every byte received.
|`adventure` |A Sierra-style adventure demo: two rooms, a verb cursor, hotspots, an inventory, walk-mask pathfinding, and walking behind things.
|`adventure2` |One room drawn the way Sierra's SCI engine does, with visual, priority, and control screens.
|`uber` |The validation and benchmark harness.
|`scb` |The per-scanline palette under the heaviest load: all 16 palettes, changing as often as every line.
|`sermouse` |The serial port and the mouse together: a stream both ways while the mouse moves (the X68000 runs both on one chip).
|===
Two complete games built on JoeyLib live in repositories of their own and
show the library under real load: Space Taxi, a port of the 1984 Commodore 64
game, and JoeyAGI, an interpreter for Sierra's AGI adventures. Each builds
from its own directory against a JoeyLib checkout, as any program of yours
would (<<_building_your_program>>).
On DVX every example is a folder of its own under `build/dvx/bin/apps/kpunch/`
with its help file, and a package in `build/dvx/bin/packages/`
(<<_dvx_programs>>). On SDL3 every example is a native
program in `build/sdl3/bin/`, beside the shared `DATA/` (<<_sdl3_programs>>),
on the web a page in a folder of its own, `build/web/bin/NAME/`
(<<_web_programs>>), on macOS an app, `build/macos/bin/NAME.app`, with its
`DATA/` inside (<<_macos_programs>>), and on the PSP a folder for `PSP/GAME/`,
`build/psp/bin/NAME/` with `EBOOT.PBP` and its `DATA/` (<<_psp_programs>>).