Skip to content

Audit: shared runtime helpers, incremental build, lighter docs, iOS split, review fixes - #25

Open
kanapitsas wants to merge 11 commits into
mainfrom
refactor/audit-nov08
Open

kanapitsas wants to merge 11 commits into
mainfrom
refactor/audit-nov08

Conversation

@kanapitsas

Copy link
Copy Markdown
Owner

What

An audit pass over the runtime, tools, tests, iOS layer and docs (8 November 2026), plus the review fixes that followed.

  • Runtime helpers (rt.h): rt_arg32, rt_guest_cstr, rt_guest_strdup, rt_intern_string, rt_handle_require, rt_trapf, rt_executable_dir, RT_ENV_FLAG, RT_BLOCKING, an RT_E* Linux errno enum. Every shim and bridge file drops its private copy (22 argument readers, 11 string readers, 5 interned-string tables).
  • libc.c routed through a name table, a switch and a resolver instead of a strcmp chain.
  • Bugs: pthread_create error path releases the TLS block; guest stack guards cover a whole host page; 8/16-bit IDIV guards the minimum / -1 quotient; narrow stat returns EOVERFLOW on a 64-bit inode; writes checked with the read span; an SDL event watch invoked from a non-guest thread no longer aborts the game; a failed munmap leaves vm.c consistent; installer Stop reaches the compiler; die() messages fit the installer; ios/deps/build.sh survives a prefix with spaces; layout.json stores absolute paths; bench_game.py no longer reports a stale log.
  • Build: one object per C file with -MMD, make -j check parallel and incremental, check is the default goal, a flags stamp recompiles when CC/CFLAGS change, CI calls make check. lift.py merges shards one at a time instead of holding 1.4 GB of generated C.
  • Generators: D3D9_SLOT_* for every method (no hand-written slot numbers), gl_bridge.h shared by gl.c and the generated thunks.
  • iOS: touch_controls.m from 1315 to ~800 lines (back-tap, gyro and simulator test mode in their own files), one fps counter shared with the F3 overlay, GL debug tracing only with build_ios.py --debug.
  • Docs: STATUS.md from 33 KB to 16 KB; install steps, co-op and measurements live in one place each.
  • Includes the editoritems.txt fix already on main.

Verification

  • make -j8 test: 246 C checks, 176 Python tests, UBSan variant, tier0-smoke relifted with the new lift.py.
  • Both games rebuilt and linked (build/portal2-native, build/hl2/hl2-native); --check-game-data tested on a complete install and on an empty file.
  • Generated files reproduced byte for byte by their generators.
  • Independent review of the runtime diff (regressions found and fixed in 95915c9).
  • Not done: no in-game run on Mac or iPhone yet, the iOS app was not rebuilt.

Left for later

C test helpers (tests/checks.h arena), stat.c/posix.c/math.c tables, Steam per-call-site resolver, GL binding cache (measure first), games.py as the single game table for setup.sh and the installer.

🤖 Generated with Claude Code

kanapitsas and others added 11 commits November 8, 2026 15:51
…strings, handles and traps

rt_arg32/rt_arg64/rt_arg_f32/rt_arg_f64, rt_guest_cstr(_or_null),
rt_guest_strdup(_or_trap), rt_intern_string/rt_is_interned,
rt_handle_require, rt_guest_address, rt_return_sret, rt_trapf,
rt_executable_dir, rt_env_flag/RT_ENV_FLAG and RT_BLOCKING replace the
copies every shim and bridge file carried (22 argument readers, 11 string
readers, 5 interned-string tables...). The copies are removed file by file
in the following commits. Also drops the never-defined rt_rand32 and a
duplicate rt_guest_poll declaration.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…story; deduplicate install and performance text

STATUS.md drops the 25 October checkpoint, the renderer-comparison method
and the superseded bridge section (33 KB to 16 KB). Install steps, HL2
performance, co-op and the Metal-vs-OpenGL numbers now live in one place
each (usage.md, STATUS measurements), the other pages link to them.
Stale claims fixed: Direct3DCreate9Ex is bridged too, method counts point
at the generators, iOS debug variables need a debug build, P2_TOUCH_TEST_*
is simulator-only, the installer zip is signed but not notarized.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ay split

Bugs: the installer's Stop now reaches the compiler (process-group kill
plus a trap in setup.sh), die() messages are one line so the installer
shows the actionable part, unpackSource keeps the old source until the
new one is in place, ios/deps/build.sh survives a prefix with spaces,
run_ios_sim.sh stops on errors, sign.py no longer leaks a plist, codesign
errors are shown, rt_ios_metal_active is atomic, NULL checks in two tests.

Dead code: rt_ios_console_command, RT_ESSL3_TEST main, the write-only
backtap candidate field, make_app renderer_line, Settings label
"Native (×3)" (×2 on iPad).

One fps counter: fps_overlay.c owns the glyph table and the frame
measurement; the touch overlay reads it (the F3 overlay text is now in
capitals). env_ios.h gains rt_ios_env_* helpers used instead of ad-hoc
getenv parsing. touch_controls.m goes from 1315 to about 800 lines:
back-tap and gyro plumbing in backtap_ios.m / gyro_ios.m, simulator test
mode in touch_test.m, one event push, cached button layout, orientation
read once per tick. GL debug tracing compiles only with
build_ios.py --debug (RT_IOS_GL_DEBUG). ios_device.sh, build_ios_probe.sh
and ios_bench.py take --game instead of Portal 2 paths.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…l incremental make, lift.py memory

layout.json now stores absolute image paths (old relative layouts are
resolved against the layout file). bench_game.py checks run_game's exit
status instead of re-reading a stale launch.log; run_game.py reports a
missing linux_root like a missing game_root and loses the unused --build
flag; language.py warns on a malformed config/local.json; build_game.py
exits cleanly on plugin errors. run_game, discover_game, bench_game and
steam_callsites get a main(); tools/launch.py holds the launch command and
environment shared with bench_renderer.py. tools/steam_metadata.py
(unreferenced) and registry.py's CLI are gone; --objdump is threaded
through. The Makefile reads config/local.json once through localconfig.py
--make, compiles one object per C file with dependency files (make -j
check is parallel and incremental) and makes check the default goal; CI
calls make check. lift.py writes one .part per shard and merges shard by
shard instead of holding all generated C in memory, keys the disassembly
cache by path/size/mtime, drops the legacy .json cache files and indexes
data segments for JumpTables.module(); _module_named and _rows remove
repeated lookups; float_lift.py hoists its duplicated st/scalar/xmm
helpers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ridge.h

gl.c, sdl_video.c, sdl_input.c, d3d9.c, fonts.c and net.c drop their own
argument readers, guest string readers, interned-string tables, handle
lookups, trap formatters and cached getenv flags in favour of rt.h's.
gen_d3d9.py emits D3D9_SLOT_* for every method, so d3d9.c loses slot_of()
and its hand-written slot numbers; the generated thunks no longer copy
each scalar argument twice. gl_generated.c includes the new gl_bridge.h
instead of re-declaring gl.c's functions. Fixes: an SDL event watch
invoked from a non-guest thread returns instead of aborting the game,
the GL kind table is allocated once, SDL_LoadBMP_RW refuses freesrc=0
(the RWops could never be released). Stale comments corrected
(Direct3DCreate9Ex, GL addresses only for known names, RT_SDL_WINDOW
user).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s for libc

Every core shim file drops its private cdecl reader, guest string reader,
strdup, errno translator and rename aliases for rt.h's helpers; posix.h's
errno functions move to rt.h with an RT_E* enum of the Linux i386 values.
libc.c routes its imports through a name table, a switch and a resolver
instead of a strcmp chain. Fixes: pthread_create's error path releases
the TLS block, guest stack guards cover a whole host page, 8/16-bit IDIV
guards the minimum / -1 quotient, the narrow stat returns EOVERFLOW for a
64-bit inode, writes checked with the read span use rt_write_span, lazily
initialised diagnostics and the scheduler's timing flag are atomic, a
failed munmap leaves vm.c's permissions and mapping list consistent.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A player created an empty editoritems.txt by hand and still crashed: the
messages now say that a placeholder does not help, that Steam's Verify
integrity of game files restores the file, and that no rebuild is needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e, LoadBMP_RW freesrc=0, empty env flags

make P2_HOST_PREFIX=... check works again; a build/obj/flags stamp
recompiles every object when CC/CFLAGS change (setup.sh switching to the
prebuilt bundle); D3DFMT_A1 user-memory textures are no longer rejected
as 4 bytes per pixel; SDL_LoadBMP_RW with freesrc=0 keeps the old
pass-through instead of trapping; an empty environment value counts as
off, as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… in CI)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant