Files
goldeneye-pc-port/scripts/gen_pcprotos.py
T
James Dansereau 98412c281c PC port: Phase 1.5 done, first frames render (D38-D42)
- D38: implicit function declarations truncated pointer returns on x86-64;
  added port/include/pc_protos.h prototype shim (398 decls, C-only, anchored
  in port/shim/PR/ucode.h) + pc_netorder.c for ntohl/ntohs; build warning-clean.
- D39: Globalimagetable rebasing - per-symbol offsets + GIMG_OFF() in
  image_bank.c (== N64 (u32)&sym incl. the 0x02000000 base); segment end
  markers extended to the true 0x13F8 size (CSV entry truncated by 0x930).
- D40: g_ModelHitEntries pool sized for the 40-byte PC ModelHitEntry stride
  (was a 12KB .bss overflow clobbering is_ramrom_flag -> demo-replay SIGSEGV).
- D41: release the GL context from the host main thread after videoInit so
  the game scheduler thread can bind it (WGL single-thread currency; this
  SDL2 build's MakeCurrent return value is an inverted ABI artifact).
- D42: rsp.c g_gfxTaskSettingsList XOR toggle -> explicit toggle on x86-64.

Boot now renders real frames ([NOTE] frame N rendered in ... us). Next
blocker D43 (model-file loading ABI mismatch) documented in PCPortResearch.md
section F/H; HANDOFF.md rewritten for it.
2026-08-22 04:07:07 -04:00

93 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""One-shot D38 generator for port/include/pc_protos.h (see docs/PCPortResearch.md §F/D38).
Pipeline (all inputs were captured from a PC build of the decomp):
1. Compile the game TUs and collect `implicit function declaration` warnings
-> build-pc/implicit_funcs.txt (one name per line).
2. Scan the tree for each name's true definition signature
-> build-pc/protomap.json (name -> [return type, params...]).
3. Run this script to emit port/include/pc_protos.h.
NOTE: the committed pc_protos.h is the source of truth and was hand-adjusted
after generation (C-only guard; full prototypes for the 11 functions whose true
signatures use default-promoted parameter types, which C11 forbids matching
with an empty parameter list). Re-running this script overwrites those tweaks —
regenerate only if new implicit declarations appear, then re-apply the tweaks.
"""
import json, re
names = [l.strip() for l in open('build-pc/implicit_funcs.txt') if l.strip()]
pm = json.load(open('build-pc/protomap.json'))
# MSVCRT / not-in-tree: fixed declarations
specials = {
'assert': 'void',
'memcmp': 'int',
'snprintf': 'int',
'time': 'long long',
'GetCurrentThreadStackLimits': 'int',
}
def clean(rtype):
rtype = re.sub(r'\s+', ' ', rtype).strip()
for kw in ('extern ', 'static ', 'inline '):
if rtype.startswith(kw):
rtype = rtype[len(kw):].strip()
return rtype
lines = []
for n in sorted(names):
if n in specials:
rt = specials[n]
elif n in pm:
rt = clean(pm[n][0])
assert rt, (n, pm[n])
else:
raise SystemExit('no type for %s' % n)
lines.append('%s %s();' % (rt, n))
hdr = '''/*
* pc_protos.h - PC-port-only prototypes for implicitly declared functions.
*
* D38 (docs/PCPortResearch.md section F): the decomp has ~72 translation units
* that call ~400 functions without any visible prototype (missing #include of
* the declaring header). Under C11 an implicit declaration assumes `int f()`,
* which on N64 (MIPS, 32-bit pointers) is harmless, but on x86-64 it silently
* truncates every pointer (and 64-bit scalar) return value to 32 bits - e.g.
* tokenFind() in set_mt_tex_alloc() returned a low-32-bit "pointer" that then
* faulted in strtol().
*
* This header declares each of those functions with its TRUE return type and
* an empty parameter list (no argument checking, no dependency on the
* parameter types' headers). Empty-paren declarations are compatible with the
* real prototypes elsewhere, so this is purely additive: it changes only the
* width of the returned value, restoring N64-correct semantics on x86-64.
*
* Anchored at the end of port/shim/PR/gbi.h (PC-only shim), which every game
* TU parses via <ultra64.h>. Inert in the N64 build (no -DPORT).
*/
#ifndef _PC_PROTOS_H_
#define _PC_PROTOS_H_
#if defined(PORT) && defined(__x86_64__)
#include <stddef.h> /* size_t */
#include <PR/gbi.h> /* Gfx, Mtx, Vtx, Light (shimmed on PC) */
#include "bondtypes.h" /* coord3d, PropRecord, ObjectRecord, ModelFileHeader, bool, ITEM_IDS */
#include "bondconstants.h" /* MPSCENARIOS, OBJECTIVESTATUS, PROP, DIFFICULTY, TICKOP */
#include "game/file.h" /* save_data */
#pragma push_macro("assert")
#undef assert
void assert();
#pragma pop_macro("assert")
''' + '\n'.join(lines) + '''
#endif /* PORT && __x86_64__ */
#endif /* _PC_PROTOS_H_ */
'''
open('port/include/pc_protos.h', 'w').write(hdr)
print("wrote port/include/pc_protos.h with %d declarations" % len(lines))