Repository navigation
Building
Two builds exist, and they are different things:
- the native Windows build —
build\win32\sightline.exe, produced bytools\windows\build.ps1. This is what you play, and what a release package contains. - the matching build — the original decomp compiled to a byte-identical
N64 ROM with the IDO compiler, driven by
makeon Linux. This is the correctness oracle and is kept buildable permanently.
You do not need to build anything to play: see Releases. This page is for building from source.
Three commands and one gate, all from an ordinary Windows PowerShell prompt at the repository root:
.\tools\windows\setup.ps1 # check the toolchain (add -Install to fix it)
.\tools\windows\build.ps1 # build build\win32\sightline.exe
.\tools\windows\play.ps1 # launch the game
.\tools\windows\test.ps1 # headless Facility acceptancesetup.ps1 reports; setup.ps1 -Install installs what is missing with
MSYS2's pacman. MSYS2 is used purely as a toolchain provider — nothing
asks you to open an MSYS2 shell, and nothing is downloaded into the
repository. If you do not have MSYS2:
winget install --id MSYS2.MSYS2
.\tools\windows\setup.ps1 -InstallEvery requirement is validated by querying the executable, and the last check compiles and links a real SDL2 program and reads its PE header back, so "Toolchain satisfied" means the toolchain actually produced a 32-bit, large-address-aware image with SDL2 linked. The checks:
| Check | Package installed by -Install
|
|---|---|
i686-w64-mingw32-gcc (targets i686) |
mingw-w64-i686-gcc |
binutils (as, ld, objdump, nm) |
mingw-w64-i686-gcc / mingw-w64-i686-binutils
|
pkgconf (asked for the SDL2 flags) |
mingw-w64-i686-pkgconf |
SDL2 development files and a 32-bit SDL2.dll
|
mingw-w64-i686-SDL2 |
sed (applies tools/native/aiprint.sed) |
sed |
Python — .venv\Scripts\python.exe, or python.exe on PATH |
not installed; create the venv yourself with python -m venv .venv
|
the matching build's map, build\u\ge007.u.map
|
see the note below — build.ps1 no longer needs it |
a ROM at SL_ROM or baserom.u.z64
|
reported, but not a build requirement |
Parameters: -Install, -Yes (do not prompt before installing), and
-Msys2Root <path> (or the SL_MSYS2_ROOT environment variable) when MSYS2
is not in one of the usual places. An explicitly named root is
authoritative; the script will not quietly fall back to another
installation.
build.ps1 places the ROM-flavoured symbols and the segment windows from
the matching build's linker map. Since v0.2.0 what it reads is a tracked
extraction of that map, tools\native\ge007.u.linkmap.txt — symbol names
and link addresses only (no ROM bytes, no game data), with its provenance
(the source map's SHA-256, the commit make matching ran at, the ROM it
reproduced) in its header. A fresh clone on a Windows-only machine
therefore builds without ever running the matching build. SL_LINKMAP can
name a raw map or another extraction for comparison;
tools\native\extract_linkmap.py regenerates and verifies the extraction
after a make matching.
Note that setup.ps1 in the current tree still reports the raw
build\u\ge007.u.map as a check and counts it missing when absent. That
line describes the old input; build.ps1 does not read it and does not
require it.
.\tools\windows\build.ps1 # incremental
.\tools\windows\build.ps1 -Clean # delete build\win32 firstObjects and the executable land in build\win32\ (git-ignored). The script
stages the non-system runtime DLLs next to the exe — read out of the PE
import table rather than guessed — so a launch needs nothing on PATH. It also
converts the committed model source packages under
data\asset-overrides\source\ (the four boot models and the two controller
models) into build\win32\data\asset-overrides\
(see Custom Boot Models).
The build needs no ROM and nothing ROM-derived: the ROM is read at run
time — the audio microcode's tables included, which are derived from the
player's ROM at start-up rather than generated or compiled in. The build
flags (-mno-ms-bitfields, -fno-common, -Wl,--large-address-aware,
-mconsole, -DSDL_MAIN_HANDLED) are each there for a measured reason and
are documented in
tools/windows/README.md.
Environment overrides: SL_MSYS2_ROOT, SL_PYTHON, SL_LINKMAP,
SL_TRACE_DEFS (extra -D flags; changing it invalidates all objects),
SL_SDL_CFLAGS and SL_SDL_LIBS. -Demo builds the private demo core
(package-demo.ps1); a release is never a demo build.
.\tools\windows\test.ps1
.\tools\windows\test.ps1 -Runs 2Boots the level with no window, pumps a fixed number of frames, and passes
only when the binary itself prints sightline native: survived <N> pumped frames and exits 0. Anything else is a failure, including a zero exit with
no line. Parameters: -Level (default facility), -Frames (default 300),
-Runs (default 1), -TimeoutSeconds (default 180 — a hang is a failure
with evidence, not a test that never returns). It needs the ROM, and builds
first if the executable is missing.
Beside it are self-tests for the native platform layer, each compiling one
subsystem with its fixture and exiting 0 on success: settingstest.ps1
(the settings store), displaytest.ps1 (the aspect / viewport fit and the
window-mode seam), inputtest.ps1 (the input path) and ucodetabtest.ps1
(the run-time derivation of the audio microcode tables from a ROM, and that
a ROM with one changed byte is refused).
.\tools\windows\package-release.ps1 -Version X.Y.Z -SourceDir <clean checkout> `
-OutDir <dir> [-Rom <your ROM>] [-CanonicalTag vX.Y.Z] [-PublicTag vX.Y.Z] ...Builds nothing and touches no remote. It takes the normal (never -Demo)
build.ps1 output already in <SourceDir>\build\win32, refuses a dirty
checkout, and stages exactly what a player needs — the executable, the DLLs
its import table names (walked transitively with objdump), every built
.slmodel, Sightline.cmd and README.txt from tools\windows\release\,
the LICENSES\ tree plus the controller models' ATTRIBUTION.md files, and
a generated VERSION.txt (version, commits and tags, build date, toolchain
identity, build flags, the hash of every non-Git build input, the SHA-256 of
every file). It then runs validate-package.ps1 on the staged directory,
zips it, validates the ZIP again and writes the .sha256 file last. With
-Rom the validator scans every shipped file for ROM-derived excerpts (the
ROM header, the audio microcode data segment, the two tables) and a hit is
a rejection that leaves no ZIP behind. See Releases for what
the result looks like.
make verify-rom # check the ROM before anything else
make venv # Python tooling in .venv
make matching # build tools, extract assets, build the ROM
make trace-verify # replay every recorded trace, diff state hashes
make matching ends with MATCH! and writes build/u/ge007.u.z64, which is
bit-for-bit identical to the base ROM. It also produces
build/u/ge007.u.map, the raw linker map from which
tools/native/ge007.u.linkmap.txt is extracted.
The environment, package list, the vendored IDO recompiler, the two-phase
build (asset extraction writes source files that the main dependency graph
then globs, so it runs to completion first) and the known sharp edges are in
docs/toolchain.md;
the upstream decomp's setup, including the Docker route, is in
docs/SetupGuide.md.
Keep the repository on a real Linux filesystem under WSL2 (not /mnt/c):
the case-insensitive DrvFs mangles generated symbol files.
make trace-verify and the rest of the harness are described in
Trace Harness.
Written from the public Sightline source tree. Bug reports and questions go to GitHub Issues; pull requests are not accepted.