port: D402 — fix the first clean Linux (glibc/SteamOS) build

The release/v0.4.0 branch had never been compiled on Linux; two
port-layer include-resolution spots that MinGW tolerated break under
glibc. Shim-only fixes, zero src/ edits, no rule-2:

- port/shim/PR/ucode.h + port/shim/bondconstants.h: break the
  bondconstants.h -> ultra64.h -> pc_protos.h -> bondtypes.h ->
  bondconstants.h first-include re-entry by deferring pc_protos.h during
  bondconstants.h's own ultra64.h pass (_PORT_DEFER_PC_PROTOS).
- port/shim/PR/gbi.h: define _SHIFTL/_SHIFTR when absent, so video.c's
  gbi.h macros keep their mbi.h definitions on Linux.

Builds + links clean on Ubuntu 24.04 (glibc 2.39 <= SteamOS 2.41).
This commit is contained in:
James Dansereau committed 2026-09-27 23:53:03 -04:00
1 parent 9fb381eab1
commit ed991dd1cb
3 files changed
+42 -1

No files matched your search

+16
View File
@@ -136,5 +136,21 @@ typedef union {
#define Gfx Gfx_le
/*
* The gDP* display-list macros in the real gbi.h use _SHIFTL/_SHIFTR, which
* the N64 headers define in PR/mbi.h. A port TU that includes <PR/gbi.h>
* without <ultra64.h> (e.g. port/src/video.c) never reaches mbi.h; on Linux
* no other header in its include chain pulls it in, so the gDP* calls expand
* to implicit _SHIFTL()/_SHIFTR() function calls and fail to link (D402).
* Define them if absent. Guarded so a TU that also reaches mbi.h keeps
* mbi.h's own definitions.
*/
#ifndef _SHIFTL
# define _SHIFTL(v, s, w) ((u32)(((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
#endif
#ifndef _SHIFTR
# define _SHIFTR(v, s, w) ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
#endif
#endif /* defined(PORT) */
#endif /* _PORT_SHIM_GBI_H_ */
+12 -1
View File
@@ -13,7 +13,18 @@
#if defined(PORT)
# include "include/PR/ucode.h"
# include "pc_protos.h"
# /* D402 (Linux build): a TU that includes <bondconstants.h> before
# * <ultra64.h> (e.g. port/src/optionsoverlay.c) sets src/bondconstants.h's
# * include-guard, then that header's own top `#include <ultra64.h>` reaches
# * this pc_protos.h -> bondtypes.h -> bondconstants.h chain while
# * src/bondconstants.h is still mid-parse (its ITEM_IDS/ACT_TYPE/... are
# * defined only later in the file). glibc GCC rejects the half-defined
# * types hard (MinGW tolerated it, so this only surfaced on Linux). The
# * bondconstants.h shim sets _PORT_DEFER_PC_PROTOS around that pass so the
# * D38 prototypes are pulled in only once, after the constants are whole. */
# if !defined(_PORT_DEFER_PC_PROTOS)
# include "pc_protos.h"
# endif
#else
# include <PR/ucode.h>
#endif
+14
View File
@@ -21,7 +21,21 @@
* Inert in the N64 build (no -DPORT): pure pass-through.
*/
#if defined(PORT)
/* D402 (Linux build): parse the PR base headers first, but tell the PR/ucode.h
* shim to defer pc_protos.h for this pass. pc_protos.h reaches bondtypes.h,
* which needs the bondconstants.h types (ITEM_IDS, ACT_TYPE, ...) that are only
* defined later in src/bondconstants.h. Without this, a TU that includes
* <bondconstants.h> before <ultra64.h> re-enters the still-parsing
* src/bondconstants.h (guard already set) from bondtypes.h and glibc GCC
* rejects the half-defined types (MinGW tolerated it). We finish
* src/bondconstants.h below and then pull pc_protos.h so the D38 prototypes
* are still seen exactly once. */
# define _PORT_DEFER_PC_PROTOS
# include <ultra64.h>
# undef _PORT_DEFER_PC_PROTOS
#include "src/bondconstants.h"
#include "pc_protos.h"
/*
* D38: src/bondconstants.h defines ntohl()/ntohs() as function-like macros