diff --git a/port/shim/PR/gbi.h b/port/shim/PR/gbi.h index ca4a6f92..99e5a2d2 100644 --- a/port/shim/PR/gbi.h +++ b/port/shim/PR/gbi.h @@ -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 + * without (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_ */ diff --git a/port/shim/PR/ucode.h b/port/shim/PR/ucode.h index a891cec2..998cf993 100644 --- a/port/shim/PR/ucode.h +++ b/port/shim/PR/ucode.h @@ -13,7 +13,18 @@ #if defined(PORT) # include "include/PR/ucode.h" -# include "pc_protos.h" +# /* D402 (Linux build): a TU that includes before +# * (e.g. port/src/optionsoverlay.c) sets src/bondconstants.h's +# * include-guard, then that header's own top `#include ` 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 #endif diff --git a/port/shim/bondconstants.h b/port/shim/bondconstants.h index c876c076..5a75ef0b 100644 --- a/port/shim/bondconstants.h +++ b/port/shim/bondconstants.h @@ -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 + * before 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 +# undef _PORT_DEFER_PC_PROTOS + #include "src/bondconstants.h" +#include "pc_protos.h" /* * D38: src/bondconstants.h defines ntohl()/ntohs() as function-like macros