Files
goldeneye-pc-port/docs/dev/LINUX-PORT.md
T
James Dansereau b01c7fa89c port(romdata): POSIX fixed-address ROM map (mmap) for the Linux build
The cart-base map at 0x10000000 (so absolute ROM-asset symbols are live host
pointers) was Windows-only; the #else branch was a stub that logged
"not implemented" and fell to the degraded heap-copy path.

- Factor the post-map work (memcpy + pcmodels/pccg sidecar load + D55 RLE
  header fixup) into romdataFinishCartMap(), shared by both paths.
- POSIX #else: anonymous mmap at CART_BASE with MAP_FIXED_NOREPLACE where
  available; on any failure munmap + fall through to the identical heap copy.
- romdataDestroy() munmaps on POSIX (length tracked in mappedLen).

Verified on Windows: builds 242/242, -level_09 boots crash-free (identical
behaviour with/without the refactor). Linux compile + runtime verification
owed — see docs/dev/LINUX-PORT.md. No behaviour change on Windows.
2026-09-02 21:15:01 -04:00

5.1 KiB

Linux port — status & gap analysis

Session M-38 (2026-09-02). Goal-2 on the roadmap (after the Windows alpha / release artifact). This is a scoping + first-patch pass; nothing here has run on a Linux machine yet.

Method

Read build-pc.sh, CMakeLists.txt, docs/building.md, and grepped port/src, port/fast3d, port/include for Windows-only headers / Win32 APIs / unguarded _WIN32 branches. A local Qwen triage pass seeded the hunt; every claim below was re-checked against the real files (the 27B was wrong on two of three headline items — see "Ruled out").

What is already Linux-ready (verified by reading)

  • port/include/platform.h — sets PLATFORM_LINUX / PLATFORM_MACOS / PLATFORM_WINDOWS cleanly.
  • CMakeLists.txt — find_package(SDL2 REQUIRED), find_package(ZLIB REQUIRED), and else() branches already present for the non-Windows case: GL_LIBRARY = GL (l.291), EXTRA_LIBRARIES = stdc++ m dl pthread (l.304), elseif(UNIX) platform block (l.86). WIN32_EXECUTABLE and the MinGW zlib fallback are correctly if(WIN32) / if(MINGW) guarded.
  • build-pc.sh — already documents the Linux apt deps (cmake libsdl2-dev zlib1g-dev libgl1-mesa-dev) and is a plain bash script, no MSYS-isms in the executable body.
  • port/src/system.c — sysSleep() has a nanosleep() #else branch (l.76-82); <windows.h> is PLATFORM_WINDOWS-guarded.
  • port/src/libultra.c — the OS-thread kernel has a real pthreads branch next to the Win32 _beginthreadex one.
  • port/src/crash.c — MessageBoxW / SetThreadPriority / __debugbreak all _WIN32-guarded, with PLATFORM_LINUX counterparts.
  • port/src/video.c — GE_MKDIR has both _mkdir and mkdir(p,0777).
  • No __declspec, #pragma comment, or hardcoded \-path / drive-letter usage anywhere in port/.

Ruled out (Qwen triage false positives)

  • system.c:75 Sleep() has no POSIX branch — it does (nanosleep).
  • CMake needs else() branches for zlib/pthread on Linux — already there.

The one real code gap — FIXED this session (verification owed)

port/src/romdata.c — the fixed-address cart map (0x10000000, so absolute ROM-asset symbols are live host pointers) had a Windows-only implementation (VirtualAlloc); the #else branch was a stub that logged "not implemented on this platform" and fell straight to the heap-copy fallback. In heap-copy mode anything that dereferences a cart address directly (not via romdataGetRom() / the PI shims) reads wrong memory — so Linux would run, if at all, in the same degraded mode Windows only hits when VirtualAlloc loses the address race.

Change (M-38):

  • Factored the post-map work (memcpy + pcmodelsLoadSidecars + pccgLoadSidecars + D55 RLE-header fixup) into romdataFinishCartMap(), shared by both paths so they cannot drift.
  • POSIX #else now does an anonymous mmap((void*)CART_BASE, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED_NOREPLACE, -1, 0). MAP_FIXED_NOREPLACE (Linux 4.17+) fails rather than clobbering an existing mapping; where the macro is absent the plain hint is advisory and the at == CART_BASE check catches a relocated result. On any failure it munmaps and falls through to the identical heap-copy path as before.
  • romdataDestroy() munmaps on POSIX (tracked length in mappedLen).

Owed verification (needs a Linux box):

  1. Compiles under GCC on Linux (<sys/mman.h> resolves; no decomp-include-path shadowing surprise).
  2. mmap actually lands at 0x10000000 on a stock ASLR Linux — 0x10000000 (256 MB) is low but usually free; if the kernel routinely refuses it, consider linking the binary no-PIE or reserving the range via a linker script so the loader keeps it clear.
  3. -level_09 boots crash-free with the mapped path taken (check the log says "mapped at 0x10000000 (cart base)", not "using heap copy").
  4. Whether the heap-copy fallback is actually survivable on Linux if step 2 fails — audit for direct 0x1xxxxxxx derefs outside the PI shims.

Remaining Linux work after the romdata patch lands

# Item Size Note
1 Run the Ubuntu validate CI job → upgrade it to a real compile job S .github/workflows/ci.yml already configures on Ubuntu; flipping it to cmake --build surfaces the real GCC-strictness gaps cheaply
2 First actual Linux runtime bring-up (-level_09) M expect a short tail of unguarded calls / struct-layout asserts GCC-on-Linux vs MinGW
3 docs/building.md — promote Linux from "untested" to "supported" once 1+2 pass S
4 SDL2 / GL context creation on X11 + Wayland M fast3d is GL 3.3 core; PD port runs on Linux so the path is known-good
5 Package: an AppImage or tarball equivalent of bundle-win.sh M reuse prepare-assets.py verbatim — it is already OS-agnostic

Land the romdata patch behind CI (item 1) — turn the Ubuntu validate job into a compile job in the same PR so the "does it build on Linux" question is answered by the bots, then do the runtime bring-up on a real machine.