Commit Graph
453 Commits
Author SHA1 Message Date
James Dansereau 66e38e27d7 docs: v0.1.0 alpha framing + hygiene pass
Update the public-facing docs to the M-49 state (v0.1.0 alpha, first
full-campaign playtest: 19/21 missions completable, D191 crashes Bunker ii
+ Statue, D193 AI pacing is the top flaw).

- README: lead with what it is + status, research angle second; new
  Quick start section; Status/Download rewritten for the alpha + dual
  platform; "By the numbers" refreshed (~3 weeks, ~320 commits, ~190
  findings, ~49 sessions, 69 PORT files).
- .github/release-notes.md: v0.1.0 title + known-issues rewrite.
- .github/social-preview.html: status/stat lines (regen + re-upload the
  PNG separately).
- docs/index.md, docs/dev/LEVEL-STATUS.md: M-49 status.
- docs/dev/findings.md, docs/dev/GRAPHICS-BACKLOG.md: D191-D197 +
  D148/D170/D173 M-49 escalations.

Hygiene:
- Fix the `&` literal in internals.md H1.
- Repoint two ../README.md links that 404 on the Pages site.
- Standardise British -> American spelling across the public docs
  (behaviour->behavior, colour->color, catalogue->catalog,
  centre->center, etc.). Deep internal logs left untouched.
- .gitignore: document the local-notes convention (docs/HANDOFF.md,
  docs/BACKLOG.md, and a new docs/dev/notes/ drop for roadmaps and
  session plans) so it survives a fresh clone.
v0.1.0
2026-09-04 00:05:46 -04:00
James Dansereau 86440e3b58 fix(linux): survive the decomp's latent stack-buffer overruns (D189) (#24)
* fix(linux): survive the decomp's latent stack-buffer overruns (D189)

The decompiled game code has a class of fixed-size stack-buffer over/under-
runs that write a few words into adjacent stack scratch:

  * stan.c  sub_GAME_7F0B1DDC  — `StandTile *tileStack[39]` with a bail check
    of `if (cat >= 41)` that only runs once per outer iteration, so `cat`
    reaches 40 + pointCount and the append writes several slots past the end.
    BUNKER1 (-level_09) prop room-list setup legitimately visits ~40 tiles.
  * bondview2.c  bondviewCalcIntroSwirlCamera  — `f32 pointbuf[10]` indexed
    `&pointbuf[i*3]` for i in [-1..2] then written [0..5], i.e. [-3 .. 11].

On the N64 and on the MinGW/Windows build (neither uses a stack protector)
these are harmless in practice — the Windows build is stable over thousands
of frames. Only Ubuntu's gcc default (`-fstack-protector-strong`) turns them
into a fatal `__stack_chk_fail`, at BUNKER1 stage load and again at the intro
swirl camera (~frame 5).

Two-part fix:
  * `-fno-stack-protector` globally (CMakeLists) — matches the N64 and MinGW
    builds so the same code runs the same way. A hardened Linux build would
    need the whole overrun class swept first.
  * `StandTile *tileStack[64]` under `#ifdef PORT` (stan.c) — the one case
    that is cleanly understood and bounded (`pointCount` is 4-bit, so 40+15
    is the true worst case). Pure local scratch, never escapes, no behaviour
    change. N64 keeps `[39]` under `#else`.
  * stan.c:2225 link-resolve also switched to the D177 PORT_PTRADD macro for
    idiom consistency (the blob maps below 4 GiB so the bare cast is
    currently lossless; #else is byte-identical).

Stacked on the D188 xprintf fix. Verified: Windows -level_09 framediff 3/3
within golden threshold (all changes are #ifdef PORT or no-op on MinGW);
Linux -O2 -level_09 now runs to frame 2100+ with no crash.

* docs: D189 update (stack-protector / latent overrun class) + porting-notes D8

* docs: D190 — Linux -level_45 objective.c load crash (open); D189 sweep 5/6
2026-09-03 20:18:25 -04:00
James Dansereau 1261389a5c fix(linux): thread a va_list* through _Printf (x86-64 SysV ABI) (#22)
* fix(linux): thread a va_list* through _Printf (x86-64 SysV ABI)

On the x86-64 System V ABI `va_list` is an array type, so a by-value
`va_list` parameter decays to a pointer. `_Printf()` was passing `&args`
(the address of that local pointer, not the argument list) to `_Putfld()`,
which does `va_arg(*args, ...)` — so `_Putfld` walked garbage and
segfaulted. Latent at `-Og`, fatal at `-O2` (PR #9), which is why the
Linux release build crashed at boot:

  bossInitMainthreadData (boss.c:247, the D121 per-level -m token sprintf)
    -> sprintf("-level_%c%c %s", ...) -> _Putfld -> SIGSEGV @ xprintf.c

Same UB class as D187. Windows x64's `va_list` is a scalar (`char*`), so
`&args` happened to work there — the Windows build is unaffected.

Fix: under `#ifdef PORT`, `_Printf` takes `va_list *` and passes it
straight to `_Putfld` (which already expects `va_list *`); `src/sprintf.c`
(the only PC caller — `rmon.c` is excluded from the build) passes `&args`
of a real `va_list` object. N64 build untouched (`#ifdef PORT`, and it
byte-matches the ROM).

Verified:
- Windows: build links, `-level_09` framediff 3/3 within golden threshold.
- Linux -O2: boot crash gone, now advances past bossInitMainthreadData
  into stage load (uncovers a separate pre-existing stan.c stack overflow
  during BUNKER1 prop setup — tracked separately).

* docs: D188 (xprintf va_list ABI) + D189 (stan.c stack-smash) findings + porting-notes D7
2026-09-03 20:12:56 -04:00
James Dansereau bde5e0bdfa docs(release): drop fixed items from the alpha known-issues list (#21)
The HUD weapon/ammo-type icon (D187, PR #19) and blank briefing objective
text (D178, cd1ed574) are both fixed and on main. Remove them from the
release-notes and bundled-README known-issues blurbs so a v0.1.0 tag ships
an accurate list. Black sky and the front-end 3D models (Nintendo logo,
MISSION COMPLETE / mode-select) are still open and stay listed.
2026-09-03 16:37:10 -04:00
James Dansereau ed6e677d06 build(release): fall back to 7z / Compress-Archive when zip is absent (#20)
A stock MSYS2 MINGW64 shell ships neither `zip` nor `unzip`, so
`tools_pc/bundle-win.sh` failed at the packaging step for a local release
build (the M-45 handoff's documented v0.1.0 cut path). CI is unaffected
(it `pacman -S zip unzip`, so the `zip` branch is still taken).

Fallback order: zip -> 7z on PATH -> "C:\Program Files\7-Zip\7z.exe" ->
powershell Compress-Archive. Verified end-to-end: bundle builds, unpacks
to a clean dir, prepare-assets runs, ge007.x86_64.exe boots -level_09 to
frame 2100+ crash-free.
2026-09-03 16:36:42 -04:00
James Dansereau 368062e319 Merge pull request #19 from jkdansereau/fix/hud-weapon-icon-missing-return
fix(hud): restore missing return → weapon/ammo-type icon draws again
2026-09-03 15:20:31 -04:00
James Dansereau 187d792e23 Merge branch 'main' into fix/hud-weapon-icon-missing-return 2026-09-03 15:04:54 -04:00
James Dansereau ac7223959f docs(hud): D187 finding + porting-notes D6 (missing-return / -O2 class)
M-47 root-cause + interactive-console verification for the missing HUD
ammo-type icon: framediff -level_09 frame 320 worst-cell dmean 21.8 -> 4.0
with the one-line AVOID_UB return; orange clip glyph confirmed present
again. porting-notes D6 covers the non-void-no-return / latent-until-O2
pattern.
2026-09-03 15:04:16 -04:00
James Dansereau a9d8e4d44c fix(hud): restore missing return in set_rgba_redirect_generate_microcode
The HUD weapon/ammo-type icon (bottom-right, and bottom-left when
dual-wielding) stopped drawing ~2026-09-02; the ammo *numbers* still
render. Root cause: set_rgba_redirect_generate_microcode (gunfire.c, the
sole icon emitter) is non-void but has no return statement (the decomp
banner flags it). At -Og the tail call's result stayed in $v0 and it
worked; commit 7549570b restored -O2 for playtest builds, where the
undefined return register makes callers resume the DL from the icon's
start offset and overwrite the icon commands with the following
microcode_constructor / gunDrawHudInteger output.

Fix: add the return under AVOID_UB (already -D'd in the PC build;
CMakeLists.txt:207), N64 byte-match path unchanged under #else.
Codegen-correctness only, same class as the existing AVOID_UB edits.

Owed: build (-O2) + -level_09 capture diff vs docs/img/bunker1-2.png.
A/B: Debug build (-Og) shows the icon, -O2 build without this fix does not.
2026-09-03 13:11:42 -04:00
James Dansereau fcc23dd584 Merge pull request #17 from jkdansereau/release/v0.1.0-alpha-dual-platform
release: Linux x86-64 bundle + dual-platform alpha release notes
2026-09-03 12:13:32 -04:00
James Dansereau 174233f89f ci: mark bundle-linux.sh executable
Committed without the +x bit from a Windows checkout -> CI hit
"Permission denied" (exit 126) invoking tools_pc/bundle-linux.sh.

Claude-Session: https://claude.ai/code/session_01V4pK3pT83YnPsBp3Ey4RP2
2026-09-03 11:50:29 -04:00
James Dansereau 7a3791b533 Merge pull request #16 from jkdansereau/ci/docs-pr-mergeable
ci: make docs-only PRs mergeable
2026-09-03 10:55:22 -04:00
James Dansereau a0611727e9 release: add Linux x86-64 bundle + dual-platform release notes
- tools_pc/bundle-linux.sh: package a Linux build (exe + README + licenses +
  prepare-assets) as a .tar.gz. Mirrors bundle-win.sh's ROM / size guards and
  prepare-assets assembly. No shared libs bundled — the generated README tells
  the user to install SDL2 / zlib / libGL from their distro.
- tools_pc/dist/README.md.in: made OS-neutral via @PLATFORM@ / @EXE@ / @DEPS@ /
  @LICENSE_EXTRA@ tokens; refreshed the known-issues list (dropped the stale
  "ladders don't work" line — D177 fixed M-36; added black sky + missing HUD
  weapon icon).
- .github/workflows/ci.yml: linux-build now packages + uploads the Linux
  bundle; the release job attaches both platforms to the draft pre-release.
- .github/release-notes.md: rewritten for the two-platform NTSC-U alpha with
  the prepare-assets step and current known issues.

Alpha scope: NTSC-U only, one-time prepare-assets step (Part A launcher and
Part B native converter from release-dropin-rom-plan.md remain follow-ups).

Claude-Session: https://claude.ai/code/session_01V4pK3pT83YnPsBp3Ey4RP2
2026-09-03 10:54:06 -04:00
James Dansereau e886b970d7 ci: make docs-only PRs mergeable
Drop `paths-ignore` from the `pull_request:` trigger. With it, a docs-only
PR never triggered the workflow, so the required `validate` / `windows-build`
checks stayed "expected" forever and the PR could not be merged without an
owner bypass (M-44 hit this on #14/#15).

The workflow now always runs on PRs; the `changes` job diffs the PR against
its base sha (mirroring the existing branch-push logic against
`github.event.before`) and, for a docs-only change, reports the build jobs
as skipped — which branch protection accepts as success.

Claude-Session: https://claude.ai/code/session_01V4pK3pT83YnPsBp3Ey4RP2
2026-09-03 10:41:41 -04:00
James Dansereau 362a386650 Merge pull request #14 from jkdansereau/docs/m42-graphics-honesty
docs: D176(a) -level_22 headless repro; retire stale D74 wrap-block row
2026-09-03 10:19:59 -04:00
James Dansereau 7d90aca7d3 Merge remote-tracking branch 'origin/main' into docs/m42-graphics-honesty
# Conflicts:
#	docs/dev/findings.md
2026-09-03 10:18:06 -04:00
James Dansereau ae29fe2b3b Merge pull request #15 from jkdansereau/docs/d176a-sky-stream-spec
docs(D176a): full RDPHALF sky-tri stream spec + implementation paths
2026-09-03 10:17:00 -04:00
James Dansereau 2b7d3d5df4 Merge branch 'main' into docs/d176a-sky-stream-spec 2026-09-03 10:16:50 -04:00
James Dansereau 70d8ebdd4d Merge pull request #10 from jkdansereau/feat/f10-options-overlay
port: D184 — F10 in-game options overlay
2026-09-03 10:09:55 -04:00
James Dansereau 17e6e1ffb3 Merge pull request #11 from jkdansereau/feat/alpha-asset-prep-tool
feat(release): self-contained asset-prep tool for the alpha bundle
2026-09-03 10:09:36 -04:00
James Dansereau ccff1374b5 Merge branch 'main' into feat/f10-options-overlay 2026-09-03 10:03:23 -04:00
James Dansereau fdf34a7dcd Merge branch 'main' into feat/alpha-asset-prep-tool 2026-09-03 10:03:05 -04:00
James Dansereau 1df53d4cf3 Merge branch 'main' into docs/d176a-sky-stream-spec 2026-09-03 10:03:02 -04:00
James Dansereau e3a3edd121 Merge branch 'main' into docs/m42-graphics-honesty 2026-09-03 10:00:52 -04:00
James Dansereau 1ef57b936d Merge pull request #13 from jkdansereau/docs/building-d88-step
docs(building): add the missing d88_emit.py --regen sidecar step
2026-09-03 10:00:25 -04:00
James Dansereau 6af779b261 Merge pull request #12 from jkdansereau/fix/d186-fpscap-clamp
port: D186 — refuse a sub-30 Video.FpsCap instead of throttling the sim
2026-09-03 10:00:17 -04:00
James Dansereau 203ceaf717 port: fix linux-build link error in optionsoverlay (_SHIFTL)
gbi.h's gDP* DL macros use _SHIFTL/_SHIFTR without defining them; game TUs
pull them in via <ultra64.h>. This is the first port/src TU to build a
display list, and on GCC/ld the missing macro became an undefined symbol
(MinGW's include chain happens to provide it). Define the two pure macros
locally, verbatim from PR/mbi.h -- including mbi.h itself drags in N64 OS
headers that shadow libc.
2026-09-03 09:59:50 -04:00
James Dansereau 76fb7b7a25 port: D184 F10 overlay v2 — mouse control + resolution/fullscreen rows
- Fix invisible text: drawText passed the measured text w/h into textRender's
  width/height args, which are the on-screen CLIP rect (not the text size), so
  every glyph failed the clip test. Pass the full 2D viewport like bondview2.c's
  debug-text path.
- Mouse UI: hover-to-highlight; left-click in the value column toggles/cycles;
  drag sliders; red X close box (clicking a row's label only focuses it, so
  selecting can't flip a toggle). inputSuspendForOverlay() forces the OS cursor
  free + visible while the overlay owns the mouse.
- New rows: Fullscreen (live) and Resolution (windowed presets filtered to the
  desktop, live resize + recenter). SDL window ops are posted from the
  scheduler thread and drained host-side in videoPumpEvents.
- Layout recomputed for the wide BankGothic font: right-aligned values, wider
  row pitch, all 13 rows fit the ~240-unit 2D space; nothing clips.

Port-layer only. Links clean; runtime-verified on a real display (front end +
-level_09): layout, hover/click/drag, live VSync/filter/fullscreen/resolution.
2026-09-03 09:54:21 -04:00
James Dansereau 2d7add1ef9 Merge branch 'main' into feat/f10-options-overlay 2026-09-03 01:15:26 -04:00
James Dansereau 475385edb1 docs(D176a): full RDPHALF sky-tri stream spec + two implementation paths
The M-37 scratch note (D176a-sky-rootcause.md) was never committed. Re-derive
the complete format from src/game/sky.c and include/PR/gbi.h:

- skyRenderTri/skyRenderFull emit a verbatim N64 RDP triangle command
  (2-word header + 3 edge-slope pairs + 16-word shade block + 16-word
  texture block) chopped into gImmp1(G_RDPHALF_1/_CONT) pairs, terminated
  by G_RDPHALF_2. GE's RSP ucode DMAs it straight to the RDP.
- sub_GAME_7F097388 already yields complete screen-space verts; the
  projection math is endian-clean and is not the defect.

Two implementation paths documented with a recommendation (Path B: an
#ifdef PORT emit swap in sky.c, first; Path A: an RDP-tri decoder in
gfx_pc.cpp, as the long-term answer). Word layout cross-checked against
gbi.h packing conventions.
2026-09-03 01:13:47 -04:00
James Dansereau af881ff33c Merge branch 'main' into feat/alpha-asset-prep-tool 2026-09-03 01:05:38 -04:00
James Dansereau 7863ec096f port: D186 — refuse a sub-30 Video.FpsCap instead of throttling the sim
sync_framerate_with_timer() runs inline on the scheduler thread
(osSpTaskStartGo -> gfx_run -> swap_buffers_begin), so a low frame cap
blocks VI-retrace delivery and drags every game thread down to the cap
rate rather than just dropping presented frames. There is no N64 analogue
(RSP/RDP/VI are separate silicon; the CPU never waits on them).

Clamp 0 < FpsCap < 30 to 0 (uncapped) with a warning, at both:
  - videoInit, so a bad ge007.ini value (e.g. dinged to 10 via the F10
    options overlay) is normalised and persists sane on next configSave();
  - gfx_sdl_set_target_fps, the fast3d chokepoint, which also covers the
    overlay's live set path.

Caps >= 30 are unchanged. Default (FpsCap = 0) is byte-identical to
golden (-level_09 framediff 3/3). The real fix — moving frame pacing off
the scheduler thread — is documented as owed in findings.md D186.
2026-09-03 00:51:40 -04:00
James Dansereau ea11bdf01f docs: D176(a) -level_22 headless repro; retire stale D74 wrap-block row
- findings.md / GRAPHICS-BACKLOG.md: -level_22 (Statue, night) is a clean
  no-input headless repro of the D176(a) black sky — bare boot, frame ~360,
  upper half pure black. Best verification target for the RDPHALF sky-tri
  decoder. Note -level_36/-43 intro cams face the terrain (not a sky test
  without GE_INPUTSCRIPT); -level_29 top-of-frame is dim, not black.
- GRAPHICS-BACKLOG "D74 wrap-block": struck through — the dead-code / OOB
  in-vertex-loop wrap block was reworked and hoisted to a per-texunit
  pre-wrap window behind Video.WrapFix at M-30 (RC3/D167). No longer latent.
2026-09-03 00:49:38 -04:00
James Dansereau 547c564c98 docs(building): add the missing d88_emit.py --regen sidecar step
building.md listed only d43 + d69; d88 (per-level Usetup*Z stage setup,
appended to the pccg dir) was omitted, so a source build per these
instructions produced a game that crashed on first level load.
2026-09-03 00:45:33 -04:00
James Dansereau e548dec129 Merge pull request #9 from jkdansereau/perf/release-opt
build: keep release -O2 instead of forcing -Og
2026-09-03 00:26:25 -04:00
James Dansereau 7549570bb5 build: keep release optimisation (-O2) instead of forcing -Og
The non-Debug branch unconditionally appended -Og, which (last -O wins)
overrode RelWithDebInfo's -O2 for every TU. -Og is a ~10% frame-time
regression on the software RSP/rasteriser hot path and is not what a
release/playtest build wants. Restrict -Og to explicit Debug builds.

Note: does NOT fix the ~1 fps issue under investigation — the software
renderer is ~950 ms/frame at both -Og and -O2 on this box; this is just
the correct default.
2026-09-03 00:18:45 -04:00
James Dansereau a0ba900d48 Merge pull request #8 from jkdansereau/feat/linux-ci-compile
Linux: CI compile job + romdata POSIX mmap
2026-09-03 00:17:20 -04:00
James Dansereau 05b89374e8 Merge branch 'main' into feat/linux-ci-compile 2026-09-03 00:13:40 -04:00
James Dansereau c346f5c18c Merge pull request #7 from jkdansereau/docs/dropin-release-plan-and-status
Harness: Local Qwen 3.8 dispatch
2026-09-03 00:13:26 -04:00
James Dansereau ff957c21fc linux: quiet the false-positive kernel heartbeat watchdog
portHeartbeatCheck fired on any >3s frame gap and re-fired every 2s,
spamming ge007.crash.log with thread dumps during gdb pauses, level
loads, and SIGTERM teardown on a slow/software-GL setup. Widen to 8s and
stop after 3 reports. A genuine hang is permanent so it still gets caught.
2026-09-03 00:00:07 -04:00
James Dansereau b49907ded9 build: opt-in ccache + BUILD_DIR override
CMakeLists.txt: CMAKE_{C,CXX}_COMPILER_LAUNCHER=ccache when found (no-op
otherwise); game sources are frozen so branch-switch rebuilds get near-free.
build-pc.sh: BUILD_DIR=${BUILD_DIR:-build-pc} so parallel agents/worktrees
can use separate build dirs.
2026-09-02 23:54:36 -04:00
James Dansereau 20cd247084 fast3d: reliable pre-swap frame capture + fb_id 0 = window
- gfx_opengl_start_draw_to_framebuffer: fb_id 0 now binds GL framebuffer 0
  (the window) instead of framebuffers[0].fbo, a generated attachment-less
  FBO. Harmless on Windows (verified: -level_09 renders, mean RGB ~80);
  strict GL (Mesa) treats the incomplete FBO as an error and drops draws.
- GE_PCDUMP / F12 screenshots move to a pre-swap hook (gfx_pre_swap_hook,
  called from gfx_sdl_swap_buffers_begin before SDL_GL_SwapWindow). Reading
  the back buffer AFTER the swap is undefined on buffer-exchange drivers
  (Mesa/WSLg) -> black capture. Also: read GL_BACK explicitly, glFinish
  first, GL_PACK_ALIGNMENT=1 (639*3 is not 4-aligned -> row shear), and log
  any glReadPixels error.

Windows -level_09 verified: renders, no crash, capture non-black.
2026-09-02 23:54:35 -04:00
James Dansereau cd6af6c5fd linux-runtime: image base 0x20000000 to clear the N64 address ranges
The no-PIE default base 0x400000 puts .data/.bss around 0x00500000-
0x00600000, colliding with the address space fast3d's seg_addr() decodes.
A game-built display list embeds &symbol (osVirtualToPhysical identity
shim); seg_addr sees w1 < 0x800000, treats it as a K0-physical DRAM
offset and remaps to 0x80xxxxxx (zeroed DRAM mirror) -> 'unknown GBI
opcode 0x00 at 0x80575d40' twice per frame -> DL walk aborts.

Move the image to 0x20000000 -- the gap between segmented addrs
(<0x10000000), the cart map (0x10000000), the D131 module range
([0x40000000,0x70000000)) and DRAM (>=0x70000000). seg_addr passes
0x20xxxxxx through untouched. Still <2GiB so -mcmodel=small relocations
are fine (0x140000000 needed mcmodel=large). ELF analogue of the Windows
0x140000000 base. D146 opcode-0x00 errors: 2/frame -> 0.
2026-09-02 23:16:53 -04:00
James Dansereau 7b9e078991 linux-runtime: declare getenv()/realloc() for the strict-host build
The N64 <stdlib.h> stub declares neither. MinGW's other CRT headers leak
them; a strict host GCC (Linux/macOS, -std=gnu11) does not, so getenv()'s
64-bit char* return is assumed int and truncated -> configGetFrameDump
(GE_PCDUMP path) dereferenced a low-32 pointer and segfaulted. Add K&R
decls: pc_protos.h (D38 mechanism -> game TUs via <ultra64.h>) and the
port/shim/stdlib.h non-Windows branch (-> port TUs that #include
<stdlib.h>). K&R form stays compatible with the real prototypes; malloc/
calloc/free are already covered elsewhere so not repeated.
2026-09-02 23:03:46 -04:00
James Dansereau fe3d543647 linux-runtime: BUNKER1 boots + renders on Linux
First runtime bring-up on Linux (Ubuntu, gcc-14). -level_09 now renders
past frame 1200 crash-free with a clean shutdown, matching Windows.

- port/src/romdata.c: no-PIE loads the image at 0x400000, so the D34
  'clear low 32 bits of a symbol address' gives 0 -> false 'image base not
  4GiB-aligned' abort. The ANIM_DATA_* lvalues are only ever address-taken
  (never dereferenced), so fall back to a fixed 4GiB-aligned sentinel
  (0x100000000) for g_pc_animdata_base.
- port/src/main.c: the 'image must load at 0x140000000' assertion is
  PE-specific (.refptr base relocations); ELF no-PIE resolves dram_syms.s
  absolute symbols literally regardless of load address. Guard it to
  PLATFORM_WINDOWS.
- port/src/libultra.c: mmap game-thread stacks with MAP_32BIT so they sit
  in the low 2GiB. The decomp truncates stack-buffer pointers to u32 (e.g.
   in texLoad); glibc pthread stacks live above 4GiB and
  those truncations corrupt. One fix covers the whole idiom class. Windows
  pthread stacks are already low.
- src/game/image.c: belt-and-braces #ifdef PORT -- align compbuffer at
  uintptr_t width (identical result on N64).
- CMakeLists.txt: drop the -Ttext-segment experiment (needs -mcmodel=large;
  breaks R_X86_64_32 relocs) -- comment only.

Windows: build 240/241, -level_09 crash-free past frame 1440.
2026-09-02 22:50:56 -04:00
James Dansereau 875b3c7653 linux-build: POSIX crashDumpThreads (watchdog thread dump)
crashDumpThreads was defined only in the PLATFORM_WINDOWS block; the
kernel-heartbeat watchdog in port/src/libultra.c references it
unconditionally -> undefined reference at link on Linux. Add a
PLATFORM_LINUX implementation: log the live thread roster + the watchdog
thread's own backtrace (a full cross-thread stackwalk needs signal-based
peer unwinding -- deferred). Linux-only block; Windows unaffected.
2026-09-02 22:35:37 -04:00
James Dansereau fe7a34c56e linux-build: port/shim/sched.h routes C++ TUs to the host <sched.h>
The decomp's src/sched.h (N64 OSSc* scheduler) is on the include path and
shadows the system header. libstdc++'s <thread>/<mutex> gthr headers in the
fast3d C++ TUs #include <sched.h> and need the real one (cpu_set_t,
sched_yield) -- with -std=gnu++20 libstdc++ defines _GNU_SOURCE so
<pthread.h> also references cpu_set_t. New shim: C++ -> generated
hostsched.h (absolute path, hoststring pattern); C -> #include_next so
src/sched.h still wins as before. Windows build verified green (240/241).
2026-09-02 22:31:33 -04:00
James Dansereau 8eb2efa6ca linux-build: resolve host <stddef.h> via -print-file-name
<stddef.h> is compiler-internal (lib/gcc/<triple>/<ver>/include), not in
bin/../include on a native Linux GCC, so the MinGW-layout guess produced
/usr/include/stddef.h which does not exist -> fatal error in every fast3d
C++ TU. Ask the compiler with -print-file-name=include/stddef.h and fall
back to the old path. MinGW resolves to its own lib/gcc internal copy;
Windows build verified green (240/241).
2026-09-02 22:16:20 -04:00
James Dansereau 7c3bb42687 linux-build: -std=gnu extensions + fix remaining snprintf decls
- CMakeLists: CMAKE_C_EXTENSIONS/CXX_EXTENSIONS ON. Strict -std=c11/c++20
  define __STRICT_ANSI__, which disables glibc _DEFAULT_SOURCE and hides
  clock_gettime(CLOCK_REALTIME) etc. that port/src/libultra.c needs.
  -std=gnu11/gnu++20 is GCC's default and what MinGW already used.
- port/src/{pccg,pcmodels,romdata}.c: local 'extern int snprintf(...,
  unsigned long long maxsize, ...)' decls conflict with glibc's size_t one
  (same bug already fixed in pc_protos.h in M-39); spell it size_t.
- libultra.c: drop the _GNU_SOURCE define (pulls cpu_set_t refs into
  <pthread.h> without <sched.h>); the D60 POSIX stack-bounds diagnostic
  now just prints n/a rather than needing pthread_getattr_np.

Windows: full rebuild 240/241, -level_09 crash-free past frame 1740.
2026-09-02 22:12:58 -04:00
James Dansereau 59751d608c linux-build: POSIX branches for time()/bcopy/bzero and Win32-only probes
- pc_protos.h: the vestigial 'long long time()' prototype conflicts with
  glibc's time_t time(time_t*); no game code calls time(), guard it to
  _WIN32 (MinGW shadows <time.h> with the N64 stub; POSIX gets the real one).
- n64stubs.c: don't redefine bcopy/bzero on POSIX -- glibc exports them
  (via <strings.h>, size_t sizes); the local int-signature definitions
  conflict. _WIN32-only now.
- libultra.c: #define _GNU_SOURCE on POSIX for clock_gettime(CLOCK_*) and
  pthread_getattr_np; guard the D60 VirtualQuery committed-memory probe and
  GetCurrentThreadStackLimits behind PLATFORM_WINDOWS with a
  pthread_getattr_np-based stack-bounds fallback for the diagnostic path.

Windows build verified green.
2026-09-02 22:07:36 -04:00