- Pascal 70.8%
- Python 18%
- C 5%
- JavaScript 3.3%
- Nix 1.4%
- Other 1.4%
Each session runs with HOLIDAY_GL_CHECK and HOLIDAY_PRESENT_CHECK -- the build's own path, OpenGL where the X server has GLX, SDL's renderer without or with HOLIDAY_GL=0 -- and fails on a frame that differs: a part not uploaded, which a build leaving one out had passed in every session. The report counts the frames on the screen checked. Both paths, all six sessions: none differ; the broken build fails at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JsUgeyk9CsEXERdwUGTuD |
||
|---|---|---|
| docs | ||
| game | ||
| port | ||
| recon | ||
| tools | ||
| .editorconfig | ||
| .envrc | ||
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| PLAN.md | ||
| README.md | ||
Holiday Island
Reviving Holiday Island (1996, Sunflowers / Bomico), a 16-bit Windows isometric resort-tycoon game, as a native, improvable program.
recon/: the original's Delphi 1 source, reconstructed. Borland's compiler turns it into the shipped executables, the German 1.0 byte for byte (recon/README.md).- The port: the same tree builds with Free Pascal and the Lazarus LCL
into a native program that plays the game, on Linux, Windows, a Nintendo
Switch (homebrew, on a console), a Steam Deck, Android (a phone so far), in
a browser (WebAssembly: Firefox and Chromium) and on MS-DOS (a 32-bit DPMI
program: DOSBox-X and a Pentium II laptop), and agrees with the original tick for tick
(
docs/port.md). It can keep its bitmaps as a 256-colour display did, a quarter of the memory (docs/port.md). game/: the port's improvement tree, where the game changes: a resizable view and overview map, the whole screen on a Switch or a Steam Deck so far (game/README.md).
PLAN.md has the goals, the rules and what is open.
Everything works from the user's own copy of the game, kept in iso/ with
the Delphi 1 archives the reconstruction builds with. No CD image, and
nothing extracted from one, is committed or redistributed.
Quick start
nix develop # FPC, Lazarus, just, tools (or: direnv allow)
just unpack iso/Holiday_Island_Win_ROM_EN.zip # -> extracted/en
just run # build game/ for English 1.1 and play it
The justfile holds the everyday steps over tools/; just
lists them. build, run and smoke take a version, en (the default),
fr, de or de10, and optionally a tree, game (the default, but for
de10) or recon. game/ builds the three 1.1s with --language;
recon/ builds the originals, the German ones with --variant:
just run de builds game/ with --language de into build/game-de/
and plays it in extracted/de, just run de recon builds recon/ with
--variant v11de into build/recon-de/.
Outside the dev shells the recipes run the tools in them.
just switch, just switch-romfs, just deck, just appimage, just windows and just release (all of the ports, Android's the no-SDK build) make the
version's game for a Nintendo Switch's SD card (a folder, or one .nro), a
Steam Deck, one file on Linux (an AppImage) and Windows, in build/release-TREE-VERSION/:
switch-sd.zip, switch-romfs/switch/holiday/holiday.nro,
deck/holiday-deck.tar.gz, appimage/Holiday_Island-x86_64.AppImage and
windows/holiday-windows.zip, from your install's files (about a minute
each; docs/port.md,
AppImage,
Windows). The 1.1s from game/ fill the
Switch's and the Deck's screens; recon/ keeps the original's 640x480.
The Windows build has run only under Wine so far. just frame makes the Deck's
folder for a Steam Frame (aarch64, SteamOS on ARM), frame/holiday-frame.tar.gz,
untried on one (docs/port.md).
just web makes the version's game for a browser: build/release-TREE-VERSION/web/holiday-web/
and holiday-web.zip, with your install's files and the music's SoundFont in it.
python3 serve.py in the folder serves it and opens the page, which starts the
game at once (docs/port.md). It is part of just release.
The MS-DOS build is a Free Pascal i386-go32v2 program on its own platform
(VESA 8-bit video, the mouse driver, IRQ 1, a Sound Blaster, an MPU-401 or
an FM chip for the music),
built in .#dos and tried under DOSBox-X in it and on a real PC, a Pentium II
laptop:
nix develop .#dos -c python3 tools/fpc_build.py game/holiday.dpr --target i386-go32v2 --dos --out /tmp/dos. just dos makes the version's game for a
real PC: build/release-TREE-VERSION/dos/holiday-dos/ and holiday-dos.zip
(HOLIDAY.EXE, CWSDPMI.EXE, a README and your install's files, 193 MB; type
HOLIDAY in the folder), part of just release
(docs/port.md).
just nt makes the version's game for Windows NT 3.51 and on, Windows 95, 98 and ME, and Windows 3.1 with Win32s: a 32-bit
program on Win32 alone (GDI, waveOut, MCI's sequencer for the music), no
DLL beside it, in build/release-TREE-VERSION/nt/holiday-nt/ and
holiday-nt.zip (195 MB). just nt-mips makes the same for NT 3.51 on
MIPS, with a Free Pascal target and a linker of the flake's own:
build/release-TREE-VERSION/nt-mips/holiday-nt-mips/
and its .zip; just nt-ppc the same for NT 3.51 on PowerPC:
build/release-TREE-VERSION/nt-ppc/holiday-nt-ppc/. All three played on NT
3.51 in QEMU so far (the first on Windows 95 in QEMU and on Windows 3.11 with Win32s in DOSBox-X too). just release makes
all three (docs/port.md).
just wii makes the version's game for a Wii's SD card, for the Homebrew
Channel: build/release-TREE-VERSION/wii-sd/ (its apps/ to the card) and
wii-sd.zip (227 MB: the game as a .dol built with Free Pascal and
devkitPPC, your install's files and the music's SoundFont cut down for the
console's memory). It plays in Dolphin with its sound and music, the Wiimote
pointing; it has not run on a console yet. Its files are a PC's, though the
Wii is big-endian: the CD's tutorial and scenarios and a PC's saves load (not
yet tried in Dolphin), and its saves load on a PC. Part of just release
(docs/port.md).
just android makes an Android APK of the version's game, with your
install's files in it, to sideload: build/release-TREE-VERSION/android/holiday.apk
(docs/port.md). It is not part of just release:
it fetches the Android SDK and NDK (about 1 GB, under their licence) and
has run on one phone so far. just android-nosdk makes the same game on
Android's own NativeActivity with nothing of Google's SDK or NDK (AOSP's
headers, nixpkgs' clang and lld), an app of its own beside the other:
build/release-TREE-VERSION/android-nosdk/holiday.apk, which plays on the
same phone, controllers too, and is the one just release makes
(docs/port.md).
just unpack (unpack_game.py) turns any of the CDs (ISO,
.bin/.mdf/.cue, a directory, or a .zip/.7z holding one) into a
directory the game plays from, with no installer and no Wine. Unless told
otherwise it picks the directory the tools expect for the version it finds:
| directory | from | used for |
|---|---|---|
extracted/de10 |
the German CD (iso/Holiday Island (1996)(Bomico)(DE).iso) |
1.0: the Delphi check, the original under Wine, fpc_run.py's default |
extracted/en |
the English CD | 1.1: running and smoke-testing the port |
extracted/fr |
the French CD | the French 1.1 |
extracted/nsis |
nsis_extract.py iso/Holiday_Island.exe |
the 1.1 executable recon/ reproduces |
extracted/de |
the German "Erweiterte Version" CD | the German 1.1 check |
The checks
just smoke # fresh builds of game/ and recon/, both through port_smoke.py side by side (~1.5 min)
just check-versions # recon/ still compiles to the originals
just check-docs # links and tables in the Markdown
just smoke after any change to port/. check_versions.py after any
change to recon/; it needs the German retail Delphi 1 and the French
Delphi 1 Client/Server CD in iso/ (recon/README.md), which it unpacks
itself the first time.
Documentation
PLAN.md |
goals, rules, status and open work |
recon/README.md |
the reconstruction: versions, building and checking, the rules for editing, why the source looks as it does, the units |
docs/port.md |
the Free Pascal port: build, run, test; the compat layer; the guards; Delphi 1 vs FPC hazards; environment variables |
game/README.md |
the improvement tree |
docs/game.md |
the copies of the game, its files, the save format, timing and randomness |
docs/original.md |
running the original under Wine, reading its state, comparing it with the port |
The code is documented in place: the units' comments in recon/ and
port/compat/ say what each routine and global is, and every tool's
docstring says what it does (python3 tools/X.py --help).
Dev shells
| shell | contents | download | unpacked |
|---|---|---|---|
nix develop (.#lite) |
disc and media tools, Free Pascal + Lazarus (qt6), SDL3, SDL2, FluidSynth | ~1.3 GB | ~4.6 GB |
nix develop .#emu |
lite + Wine (with Win16), DOSBox-X for Borland's tools, Xvfb | ~2.0 GB | ~6.5 GB |
nix develop .#re |
lite + Ghidra, gdb | ~2.3 GB | ~6.1 GB |
nix develop .#full |
everything | ~3.0 GB | ~8.0 GB |
nix develop .#win |
lite + the Windows cross toolchains (i386-win32, x86_64-win64; built locally) + a 64-bit Wine and Xvfb (docs/port.md) |
||
nix develop .#arm |
lite + the aarch64-linux cross toolchain (built locally) + qemu-user and Xvfb (docs/port.md) |
||
nix develop .#be |
lite + the powerpc-linux cross compiler (built locally, a big-endian CPU) + qemu-user (docs/port.md) |
||
nix develop .#wasm |
lite + Free Pascal trunk's wasm32 cross compiler (built locally), wasmtime, Node, and .#be's PowerPC compiler and qemu-user (docs/port.md) |
||
nix develop .#web |
.#wasm and a headless Chromium, for tools/web_test.mjs (docs/port.md) |
||
nix develop .#dos |
lite + Free Pascal's i386-go32v2 compiler and RTL (built locally, with DJGPP's binutils for the start-up file), DOSBox-X and Xvfb (docs/port.md) |
||
nix develop .#switch |
lite + devkitPro's Switch toolchain, the aarch64 cross compiler (built locally) + Ryujinx and Xvfb (docs/port.md) |
||
nix develop .#wii |
lite + devkitPro's Wii toolchain, a PowerPC cross compiler (built locally) + Dolphin, gdb and Xvfb (docs/port.md) |
||
nix develop .#android |
lite + the Android SDK and NDK (fetched, under their licence), JDK 17, CMake, the aarch64 cross compiler and its Android run time library (built locally) (docs/port.md) |
The shells export what the port needs to build and run (FPC_LIBRARY_PATH,
QT_PLUGIN_PATH, SOUNDFONT, TINYSOUNDFONT); .#emu and .#full also set up Wine
(WINEPREFIX in extracted/wine/prefix, a 32-bit prefix, quiet, no Mono or
Gecko installers). .#win sets up its own Wine prefix, a 64-bit one in
extracted/wine/port, which runs both Windows builds of the port. Each shell
names itself in HOLIDAY_SHELL. The Python tools are stdlib-only and also
run without nix.
Layout
recon/ the reconstructed Delphi 1 source: 1.1, and 1.0 / German 1.1 as patches (v10/, v11de/)
game/ the improvement tree: recon/ as Free Pascal reads it, free to change
port/ fpc.inc and the compat units both trees build with; tests/
tools/ stdlib-only Python tools; ghidra_scripts/
docs/ the reference documents above
extracted/ working area (gitignored): unpacked games, run directories, traces
flake.nix the toolchain
justfile the everyday steps: unpack, build, run, smoke, the checks
build/ the justfile's builds (gitignored)