feat(runtime): one list of the game's switches, host/switches.def, kept in step with the reads #62

Open
dyst wants to merge 3 commits from dyst/Longshot:feat/switch-list into main
Member

Type: feat · Risk: low · Tested on: Windows 11, RTX 3080 (NVIDIA 621.14), in the game · Needs: Linux, any GPU, in the game

Why

The game reads 774 switches and nothing lists them: a new one goes unnoticed, a removed one stays in the docs, and longshot_env.txt's safety rules keep their own hand-written table of the switches a shared file must not set. This adds one list that a check keeps in step with the code.

What changed

host/switches.def lists every switch the game reads, one line each with its type, its scope and the file that reads it, and a check fails when the code and the list disagree. longshot_env.txt's allow-list takes the switches a shared file must not set from that list, in place of its own table; what it refuses is unchanged.

  • host: host/switches.def (new): one X-macro line per switch that host/, gpu/vk, gpu/render and gpu/compat read, SWITCH(NAME, TYPE, SCOPE, "area", "what").
    • TYPE: FLAG, INT, FLOAT, TEXT, PATH, or ANY where the reads don't make it certain yet.
    • SCOPE: GAME (may be set in longshot_env.txt), LOCAL (from the environment only: it names a file or presses inputs on a timer), or SYSTEM (the OS's or a library's variable).
    • area: a file that reads it. what: a one-line description; the docs' tables gave 90 of today's, and the rest are "" until someone who knows the switch writes one.
  • host: env_line_allowed in host/hos_main.c builds its table from the list (listed, through SWITCH_LOCAL_GAME/LOCAL/SYSTEM) and refuses its LOCAL switches, in place of its own by_name table and the two names it checked apart (RX_VK_FRAME_LOG, HOS_PRESENT_TRACE). Otherwise unchanged: the names it refused before are LOCAL (main's HOS_CRASH_TEST, #593, among them); a _FILE or _DIR name not listed yet is still refused; RX_VK_DLSS_DIR, paths in values and the system's names behave as before.
  • scripts: scripts/switch_list.py (new, standard library): reads, listed and compare list what's read and not listed, and what's listed and read nowhere; --update (update, certain_type, line_for) writes the missing lines (the type where the reads make it certain), drops the dead ones, and moves an area when that file no longer reads the switch.
  • build: nx2/build.py counts host/*.def among the host's dependencies (host_deps), so an edit to the list compiles hos_main.c again; nx2/version.py's fingerprint counts .def files among the sources.
  • tests: tests/test_switch_list.py (new); tests/test_env_file.py's fixture compiles env_line_allowed with host/ on the include path.

The cost for everyone: a new switch needs its line (python -I scripts/switch_list.py --update, then the description), or test_switch_list fails and names it.

Measurements

Verdict: passes: longshot_env.txt leaves out exactly the four lines it must (three LOCAL switches and an unlisted _FILE name) and takes RX_VK_PACE=1, as main's own table does: in the game on this branch (no file written), and game-free on the rebased head against main @ 7bacf846. Nothing to time.

Hardware: RTX 3080 (NVIDIA 621.14), Ryzen 9 3900X, 64 GB, Windows 11
Scene: one launch, from a save into Kokiri Forest
Method: one launch of this branch's build (on main 82de567a) with the longshot_env.txt below; what the log names as left out, and whether the files were written. On the rebased head, game-free: env_line_allowed cut out of main's host/hos_main.c and out of this branch's, each compiled (clang, -I host) and asked about the same five lines
How to reproduce: put these five lines in longshot_env.txt beside the game, start it, and read longshot_log.txt

HOS_AUDIO_DUMP=test.wav
HOS_INPUT_SCRIPT=0:A
RX_VK_FRAME_LOG=frames.csv
RX_E1_NOT_LISTED_FILE=x.txt
RX_VK_PACE=1
Set in longshot_env.txt Before: main @ 7bacf846 (allow-list, game-free) After: this PR @ c6c08d40 (allow-list, game-free) After, in the game: this PR @ 5255a001
HOS_AUDIO_DUMP=test.wav left out left out left out (named in the log); test.wav not written
HOS_INPUT_SCRIPT=0:A left out left out left out (named in the log)
RX_VK_FRAME_LOG=frames.csv left out left out left out (named in the log); frames.csv not written
RX_E1_NOT_LISTED_FILE=x.txt left out left out left out (named in the log): a _FILE name not listed
RX_VK_PACE=1 taken taken taken (not named as left out)
main HOS_AUDIO_DUMP=test.wav left out     pr HOS_AUDIO_DUMP=test.wav left out
main HOS_INPUT_SCRIPT=0:A left out        pr HOS_INPUT_SCRIPT=0:A left out
main RX_VK_FRAME_LOG=frames.csv left out  pr RX_VK_FRAME_LOG=frames.csv left out
main RX_E1_NOT_LISTED_FILE=x.txt left out pr RX_E1_NOT_LISTED_FILE=x.txt left out
main RX_VK_PACE=1 taken                   pr RX_VK_PACE=1 taken
in the game (5255a001): the log names exactly the first four as left out
the game reached play from a save, Kokiri Forest at 23-28 fps, no errors in the log

Rebased since onto main d652bbb4 (this PR @ c6c08d40), not run in the game again. Main's env_line_allowed had gained HOS_CRASH_TEST in its table (#593); the rebase keeps it refused as a LOCAL line. Since 82de567a main also added 59 switches and stopped reading 221 (#577 took the WebGPU renderer out, and every RX_ switch only it read), so a third commit brings the list in step (switch_list.py --update): the new ones are GAME as main's allow-list took them (the two _FILE names LOCAL), GAMESCOPE_WAYLAND_DISPLAY the system's. The names main's table refused that the game no longer reads leave the list and the test's names refused before: LONGSHOT_BUILDER_HOME (#13; only the builder's scripts read it, and the game starts no builder) and the WebGPU renderer's RX_DUMP_WGSL, RX_DUMP_SLOW_WGSL, RX_DUMP_TICS, RX_WGSL_OVERRIDE.

Flags and settings

No switch is added or changed. scripts/check_pr_description.py finds the names below because host/switches.def names them in backquotes in other switches' descriptions, or the test's fixtures make them up; each existing one keeps its own line in the list.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
HOS_PROFILE, RX_VK_DUMP_DIR, RX_VK_HANG_SEC, RX_VK_PRESENTS_AHEAD, RX_VK_PRESENT_AHEAD, RX_VK_SHOT_EVERY, RX_VK_SHOT_W, RX_VK_SHOT_H, RX_VK_TRANSLATE_WAIT_MS Existing switches, named in other switches' descriptions in the list unchanged unchanged none: this PR only lists them - unchanged (this PR only lists them)
HOS_GONE, HOS_KEPT, HOS_MOVED, HOS_NEW_LEVEL, RX_NEW_DUMP_DIR, RX_VK_FROM_A_TABLE, RX_NOT_LISTED_YET_DIR, RX_NOT_LISTED_YET_FILE, RX_VK_SOMETHING Test only: made-up names in tests/test_switch_list.py's fixtures; the game reads none of them - - none - -
scripts/switch_list.py [--update] The switches read and not listed, and the listed ones read nowhere; --update fixes the list - (no such tool) a developer tool none on the game Helps: keeping the list in step Run it when test_switch_list names a switch

Testing

Tested: the run under Measurements (Windows, in the game, this branch before the rebase); every check that read the changed files then (56; 51 passed, the 5 others failing the same way on main). On this rebased head (c6c08d40, on main @ d652bbb4), Windows with the Builder's llvm-mingw clang (6 at once): the 68 checks that read this diff (listed below: the tests that name a changed file, and the tests it adds or changes), not the whole suite: 58 passed, 1 skipped (tools this PC lacks, the Vulkan headers among them), 9 failed, each also failing on main: test_appimage_player_build, test_crash_dialog, test_linux_preflight, test_oot_state_tap, test_vk_pgo in the full run on main @ 1310ecc6; and test_dll, test_driver_cache_folder, test_pipeline_tour, test_udmabuf_warning on main @ 7bacf846 (run there alone, on a clean checkout of main from a few commits before this branch's base: they fail the same way; they passed in the 1310ecc6 run).

The 68 checks run

nx2/test_dll.py, nx2/test_version.py, tests/test_appimage_headers.py, tests/test_appimage_licenses.py, tests/test_appimage_player_build.py, tests/test_aspect_default.py, tests/test_auto_settings.py, tests/test_bake_ds.py, tests/test_bake_skeleton.py, tests/test_bug_report.py, tests/test_build_cleanup_scope.py, tests/test_build_hash_cache.py, tests/test_build_times.py, tests/test_cheat_items.py, tests/test_compile_retry_jobs.py, tests/test_compiler_failure.py, tests/test_cpm_discovery.py, tests/test_cpu_target.py, tests/test_crash_dialog.py, tests/test_crash_record.py, tests/test_debug_tools_linux.py, tests/test_dev_packs.py, tests/test_display_modes.py, tests/test_display_startup_failure.py, tests/test_dlss_sdk_cache.py, tests/test_driver_cache_folder.py, tests/test_driver_cache_room.py, tests/test_env_file.py, tests/test_exclusive_marks.py, tests/test_failed_compile_keeps_objects.py, tests/test_flight_yields_to_events.py, tests/test_fpx_sticky.py, tests/test_hle_stats.py, tests/test_kept_translation.py, tests/test_late_fix_build.py, tests/test_lift_cache.py, tests/test_link_path_comma.py, tests/test_linux_preflight.py, tests/test_linux_saves_move.py, tests/test_low_memory_notice.py, tests/test_make_game_ngx.py, tests/test_mem_gate.py, tests/test_mem_gate_children.py, tests/test_mem_gate_leases.py, tests/test_mem_limit.py, tests/test_menu_restart.py, tests/test_movement_speed.py, tests/test_no_release_lookup.py, tests/test_no_webgpu.py, tests/test_oot_state_tap.py, tests/test_opening_skip.py, tests/test_output_resolution.py, tests/test_pipeline_tour.py, tests/test_prepare_at_build.py, tests/test_program_cache_format.py, tests/test_recorder_sync.py, tests/test_shader_stamp_cache.py, tests/test_shader_stamp_inputs.py, tests/test_split_giants.py, tests/test_stale_hot_pieces.py, tests/test_switch_list.py, tests/test_switches_removed.py, tests/test_teleport_minimap_flag.py, tests/test_third_party_objects.py, tests/test_udmabuf_warning.py, tests/test_utf8_paths.py, tests/test_vk_pgo.py, tests/test_widescreen_shapes.py

Host build: host/hos_main.c (with the host/switches.def it includes) compiled to an object on this head (c6c08d40) and on main @ d652bbb4, both clean: on Windows with the Builder's llvm-mingw clang (x86_64-w64-mingw32), on Linux with gcc 14.2 (Docker python:3.12, host/posix on the include path); build.py's flags for one object, the runtime headers a lift makes (a64.h, a64_suyu.h, a64_fpx.h) copied from a local work folder, and for the renderer files the Builder's CPM Vulkan, SPIR-V and VMA headers. It covers the files this PR changes, not a whole game build.

Not tested: Linux (the same C; the check runs there); the game on this rebased head.

Must be tested:

  • Linux, any GPU (by hand, test request to open): longshot_env.txt setting a LOCAL switch (HOS_AUDIO_DUMP=test.wav), expecting it logged as left out and no file written (by hand: the log line, and no test.wav)

Risks

What could break: a switch marked LOCAL by mistake is refused from longshot_env.txt, so a shared file loses that setting; one marked GAME by mistake that writes a file would be let through. The names refused before that the game still reads are held LOCAL by test_switch_list, and an unlisted _FILE or _DIR name is still refused. Every new switch now needs its line in host/switches.def, or test_switch_list fails. Host objects compile once after this change (host/*.def in host_deps). With #911 (longshot_env.txt can't set HOS_CONTROL_PEER_SID): the two merge cleanly, but this list has HOS_CONTROL_PEER_SID as GAME; whichever of the two merges second marks it LOCAL in host/switches.def (one line), so the list says what the allow-list does.

Turning it off: no switch: revert the commits.

Compatibility: Nothing changes: longshot_env.txt takes and refuses what it did on main (apart from the five names its table refused that the game no longer reads: LONGSHOT_BUILDER_HOME and the WebGPU renderer's four).

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.

🤖 Generated with Claude Code

**Type:** feat · **Risk:** low · **Tested on:** Windows 11, RTX 3080 (NVIDIA 621.14), in the game · **Needs:** Linux, any GPU, in the game ## Why The game reads 774 switches and nothing lists them: a new one goes unnoticed, a removed one stays in the docs, and `longshot_env.txt`'s safety rules keep their own hand-written table of the switches a shared file must not set. This adds one list that a check keeps in step with the code. ## What changed `host/switches.def` lists every switch the game reads, one line each with its type, its scope and the file that reads it, and a check fails when the code and the list disagree. `longshot_env.txt`'s allow-list takes the switches a shared file must not set from that list, in place of its own table; what it refuses is unchanged. - host: `host/switches.def` (new): one X-macro line per switch that `host/`, `gpu/vk`, `gpu/render` and `gpu/compat` read, `SWITCH(NAME, TYPE, SCOPE, "area", "what")`. - TYPE: `FLAG`, `INT`, `FLOAT`, `TEXT`, `PATH`, or `ANY` where the reads don't make it certain yet. - SCOPE: `GAME` (may be set in `longshot_env.txt`), `LOCAL` (from the environment only: it names a file or presses inputs on a timer), or `SYSTEM` (the OS's or a library's variable). - area: a file that reads it. what: a one-line description; the docs' tables gave 90 of today's, and the rest are `""` until someone who knows the switch writes one. - host: `env_line_allowed` in `host/hos_main.c` builds its table from the list (`listed`, through `SWITCH_LOCAL_GAME`/`LOCAL`/`SYSTEM`) and refuses its `LOCAL` switches, in place of its own `by_name` table and the two names it checked apart (`RX_VK_FRAME_LOG`, `HOS_PRESENT_TRACE`). Otherwise unchanged: the names it refused before are `LOCAL` (main's `HOS_CRASH_TEST`, #593, among them); a `_FILE` or `_DIR` name not listed yet is still refused; `RX_VK_DLSS_DIR`, paths in values and the system's names behave as before. - scripts: `scripts/switch_list.py` (new, standard library): `reads`, `listed` and `compare` list what's read and not listed, and what's listed and read nowhere; `--update` (`update`, `certain_type`, `line_for`) writes the missing lines (the type where the reads make it certain), drops the dead ones, and moves an area when that file no longer reads the switch. - build: `nx2/build.py` counts `host/*.def` among the host's dependencies (`host_deps`), so an edit to the list compiles `hos_main.c` again; `nx2/version.py`'s fingerprint counts `.def` files among the sources. - tests: `tests/test_switch_list.py` (new); `tests/test_env_file.py`'s fixture compiles `env_line_allowed` with `host/` on the include path. The cost for everyone: a new switch needs its line (`python -I scripts/switch_list.py --update`, then the description), or `test_switch_list` fails and names it. ## Measurements **Verdict:** passes: `longshot_env.txt` leaves out exactly the four lines it must (three `LOCAL` switches and an unlisted `_FILE` name) and takes `RX_VK_PACE=1`, as main's own table does: in the game on this branch (no file written), and game-free on the rebased head against main @ 7bacf846. Nothing to time. Hardware: RTX 3080 (NVIDIA 621.14), Ryzen 9 3900X, 64 GB, Windows 11 Scene: one launch, from a save into Kokiri Forest Method: one launch of this branch's build (on main 82de567a) with the `longshot_env.txt` below; what the log names as left out, and whether the files were written. On the rebased head, game-free: `env_line_allowed` cut out of main's `host/hos_main.c` and out of this branch's, each compiled (clang, `-I host`) and asked about the same five lines How to reproduce: put these five lines in `longshot_env.txt` beside the game, start it, and read `longshot_log.txt` ``` HOS_AUDIO_DUMP=test.wav HOS_INPUT_SCRIPT=0:A RX_VK_FRAME_LOG=frames.csv RX_E1_NOT_LISTED_FILE=x.txt RX_VK_PACE=1 ``` | Set in `longshot_env.txt` | Before: main @ 7bacf846 (allow-list, game-free) | After: this PR @ c6c08d40 (allow-list, game-free) | After, in the game: this PR @ 5255a001 | |---|---|---|---| | `HOS_AUDIO_DUMP=test.wav` | left out | left out | left out (named in the log); `test.wav` not written | | `HOS_INPUT_SCRIPT=0:A` | left out | left out | left out (named in the log) | | `RX_VK_FRAME_LOG=frames.csv` | left out | left out | left out (named in the log); `frames.csv` not written | | `RX_E1_NOT_LISTED_FILE=x.txt` | left out | left out | left out (named in the log): a `_FILE` name not listed | | `RX_VK_PACE=1` | taken | taken | taken (not named as left out) | ``` main HOS_AUDIO_DUMP=test.wav left out pr HOS_AUDIO_DUMP=test.wav left out main HOS_INPUT_SCRIPT=0:A left out pr HOS_INPUT_SCRIPT=0:A left out main RX_VK_FRAME_LOG=frames.csv left out pr RX_VK_FRAME_LOG=frames.csv left out main RX_E1_NOT_LISTED_FILE=x.txt left out pr RX_E1_NOT_LISTED_FILE=x.txt left out main RX_VK_PACE=1 taken pr RX_VK_PACE=1 taken in the game (5255a001): the log names exactly the first four as left out the game reached play from a save, Kokiri Forest at 23-28 fps, no errors in the log ``` Rebased since onto main d652bbb4 (this PR @ c6c08d40), not run in the game again. Main's `env_line_allowed` had gained `HOS_CRASH_TEST` in its table (#593); the rebase keeps it refused as a `LOCAL` line. Since 82de567a main also added 59 switches and stopped reading 221 (#577 took the WebGPU renderer out, and every `RX_` switch only it read), so a third commit brings the list in step (`switch_list.py --update`): the new ones are `GAME` as main's allow-list took them (the two `_FILE` names `LOCAL`), `GAMESCOPE_WAYLAND_DISPLAY` the system's. The names main's table refused that the game no longer reads leave the list and the test's names refused before: `LONGSHOT_BUILDER_HOME` (#13; only the builder's scripts read it, and the game starts no builder) and the WebGPU renderer's `RX_DUMP_WGSL`, `RX_DUMP_SLOW_WGSL`, `RX_DUMP_TICS`, `RX_WGSL_OVERRIDE`. ### Flags and settings No switch is added or changed. `scripts/check_pr_description.py` finds the names below because `host/switches.def` names them in backquotes in other switches' descriptions, or the test's fixtures make them up; each existing one keeps its own line in the list. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `HOS_PROFILE`, `RX_VK_DUMP_DIR`, `RX_VK_HANG_SEC`, `RX_VK_PRESENTS_AHEAD`, `RX_VK_PRESENT_AHEAD`, `RX_VK_SHOT_EVERY`, `RX_VK_SHOT_W`, `RX_VK_SHOT_H`, `RX_VK_TRANSLATE_WAIT_MS` | Existing switches, named in other switches' descriptions in the list | unchanged | unchanged | none: this PR only lists them | - | unchanged (this PR only lists them) | | `HOS_GONE`, `HOS_KEPT`, `HOS_MOVED`, `HOS_NEW_LEVEL`, `RX_NEW_DUMP_DIR`, `RX_VK_FROM_A_TABLE`, `RX_NOT_LISTED_YET_DIR`, `RX_NOT_LISTED_YET_FILE`, `RX_VK_SOMETHING` | Test only: made-up names in `tests/test_switch_list.py`'s fixtures; the game reads none of them | - | - | none | - | - | | `scripts/switch_list.py [--update]` | The switches read and not listed, and the listed ones read nowhere; `--update` fixes the list | - (no such tool) | a developer tool | none on the game | Helps: keeping the list in step | Run it when `test_switch_list` names a switch | ## Testing **Tested:** the run under Measurements (Windows, in the game, this branch before the rebase); every check that read the changed files then (56; 51 passed, the 5 others failing the same way on main). On this rebased head (c6c08d40, on main @ d652bbb4), Windows with the Builder's llvm-mingw clang (6 at once): the 68 checks that read this diff (listed below: the tests that name a changed file, and the tests it adds or changes), not the whole suite: 58 passed, 1 skipped (tools this PC lacks, the Vulkan headers among them), 9 failed, each also failing on main: `test_appimage_player_build`, `test_crash_dialog`, `test_linux_preflight`, `test_oot_state_tap`, `test_vk_pgo` in the full run on main @ 1310ecc6; and `test_dll`, `test_driver_cache_folder`, `test_pipeline_tour`, `test_udmabuf_warning` on main @ 7bacf846 (run there alone, on a clean checkout of main from a few commits before this branch's base: they fail the same way; they passed in the 1310ecc6 run). <details><summary>The 68 checks run</summary> `nx2/test_dll.py`, `nx2/test_version.py`, `tests/test_appimage_headers.py`, `tests/test_appimage_licenses.py`, `tests/test_appimage_player_build.py`, `tests/test_aspect_default.py`, `tests/test_auto_settings.py`, `tests/test_bake_ds.py`, `tests/test_bake_skeleton.py`, `tests/test_bug_report.py`, `tests/test_build_cleanup_scope.py`, `tests/test_build_hash_cache.py`, `tests/test_build_times.py`, `tests/test_cheat_items.py`, `tests/test_compile_retry_jobs.py`, `tests/test_compiler_failure.py`, `tests/test_cpm_discovery.py`, `tests/test_cpu_target.py`, `tests/test_crash_dialog.py`, `tests/test_crash_record.py`, `tests/test_debug_tools_linux.py`, `tests/test_dev_packs.py`, `tests/test_display_modes.py`, `tests/test_display_startup_failure.py`, `tests/test_dlss_sdk_cache.py`, `tests/test_driver_cache_folder.py`, `tests/test_driver_cache_room.py`, `tests/test_env_file.py`, `tests/test_exclusive_marks.py`, `tests/test_failed_compile_keeps_objects.py`, `tests/test_flight_yields_to_events.py`, `tests/test_fpx_sticky.py`, `tests/test_hle_stats.py`, `tests/test_kept_translation.py`, `tests/test_late_fix_build.py`, `tests/test_lift_cache.py`, `tests/test_link_path_comma.py`, `tests/test_linux_preflight.py`, `tests/test_linux_saves_move.py`, `tests/test_low_memory_notice.py`, `tests/test_make_game_ngx.py`, `tests/test_mem_gate.py`, `tests/test_mem_gate_children.py`, `tests/test_mem_gate_leases.py`, `tests/test_mem_limit.py`, `tests/test_menu_restart.py`, `tests/test_movement_speed.py`, `tests/test_no_release_lookup.py`, `tests/test_no_webgpu.py`, `tests/test_oot_state_tap.py`, `tests/test_opening_skip.py`, `tests/test_output_resolution.py`, `tests/test_pipeline_tour.py`, `tests/test_prepare_at_build.py`, `tests/test_program_cache_format.py`, `tests/test_recorder_sync.py`, `tests/test_shader_stamp_cache.py`, `tests/test_shader_stamp_inputs.py`, `tests/test_split_giants.py`, `tests/test_stale_hot_pieces.py`, `tests/test_switch_list.py`, `tests/test_switches_removed.py`, `tests/test_teleport_minimap_flag.py`, `tests/test_third_party_objects.py`, `tests/test_udmabuf_warning.py`, `tests/test_utf8_paths.py`, `tests/test_vk_pgo.py`, `tests/test_widescreen_shapes.py` </details> **Host build:** `host/hos_main.c` (with the `host/switches.def` it includes) compiled to an object on this head (c6c08d40) and on main @ d652bbb4, both clean: on Windows with the Builder's llvm-mingw clang (`x86_64-w64-mingw32`), on Linux with gcc 14.2 (Docker `python:3.12`, `host/posix` on the include path); build.py's flags for one object, the runtime headers a lift makes (`a64.h`, `a64_suyu.h`, `a64_fpx.h`) copied from a local work folder, and for the renderer files the Builder's CPM Vulkan, SPIR-V and VMA headers. It covers the files this PR changes, not a whole game build. **Not tested:** Linux (the same C; the check runs there); the game on this rebased head. **Must be tested:** - Linux, any GPU (by hand, test request to open): `longshot_env.txt` setting a `LOCAL` switch (`HOS_AUDIO_DUMP=test.wav`), expecting it logged as left out and no file written (by hand: the log line, and no `test.wav`) ## Risks **What could break:** a switch marked `LOCAL` by mistake is refused from `longshot_env.txt`, so a shared file loses that setting; one marked `GAME` by mistake that writes a file would be let through. The names refused before that the game still reads are held `LOCAL` by `test_switch_list`, and an unlisted `_FILE` or `_DIR` name is still refused. Every new switch now needs its line in `host/switches.def`, or `test_switch_list` fails. Host objects compile once after this change (`host/*.def` in `host_deps`). With #911 (`longshot_env.txt` can't set `HOS_CONTROL_PEER_SID`): the two merge cleanly, but this list has `HOS_CONTROL_PEER_SID` as `GAME`; whichever of the two merges second marks it `LOCAL` in `host/switches.def` (one line), so the list says what the allow-list does. **Turning it off:** no switch: revert the commits. **Compatibility:** Nothing changes: `longshot_env.txt` takes and refuses what it did on main (apart from the five names its table refused that the game no longer reads: `LONGSHOT_BUILDER_HOME` and the WebGPU renderer's four). ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The game reads 935 switches (host/, gpu/vk, gpu/render, gpu/compat) and nothing listed them: a new one could go
unnoticed, a dead one stay documented, and longshot_env.txt's allow-list kept its own hand table of the switches that
must not come from a shared file. host/switches.def lists each (type, scope, area, what; the docs' tables gave 91
descriptions, the rest say "" until someone does). tests/test_switch_list.py fails when a read switch is missing or a
listed one is read nowhere; scripts/switch_list.py --update writes the line. env_line_allowed refuses the LOCAL ones
from the list (the names it refused before stay LOCAL, and a _FILE or _DIR name not listed yet is refused as before);
build.py counts the list among the host's headers. The dev-loop proposal's E1 (NotRexed/Hookshot#2636).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
test: test_env_file compiles env_line_allowed with host/ on the include path (switches.def)
All checks were successful
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
5255a0012a
Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
dyst changed title from feat(runtime): one list of the game's switches, host/switches.def, kept in step with the reads to WIP: feat(runtime): one list of the game's switches, host/switches.def, kept in step with the reads 2026-11-13 01:14:03 +00:00
Author
Member

Back to WIP under #48's process: this was carried over before the new template. Its description will be brought to the template and measured on Longshot (main against this PR, at named commits) when it's wanted for review; ask here if you'd like it sooner.

Back to WIP under #48's process: this was carried over before the new template. Its description will be brought to the template and measured on Longshot (main against this PR, at named commits) when it's wanted for review; ask here if you'd like it sooner.
Author
Member

Description brought to Longshot's PR template (#48). Still WIP: it has a game run on this branch but no main-against-this-PR measurement yet, and it isn't rebased on current main.

Description brought to Longshot's PR template (#48). Still WIP: it has a game run on this branch but no main-against-this-PR measurement yet, and it isn't rebased on current main.
Author
Member

Description moved to the template's Testing section and whole checklist (#72): what was tested, what wasn't, and what needs other testers (their test requests to open while this is WIP).

Description moved to the template's Testing section and whole checklist (#72): what was tested, what wasn't, and what needs other testers (their test requests to open while this is WIP).
Author
Member

The description follows the template after #76 and #106: If applicable keeps only the boxes that apply (one that applies and isn't done yet stays unticked while this is WIP), the Flags table has the template's seven columns (Goal is now Recommendation), and GitHub references are full URLs. Nothing else changed.

The description follows the template after #76 and #106: If applicable keeps only the boxes that apply (one that applies and isn't done yet stays unticked while this is WIP), the Flags table has the template's seven columns (Goal is now Recommendation), and GitHub references are full URLs. Nothing else changed.
Owner

This conflicts with main now: host/hos_main.c's env_line_allowed (the names that take a file or folder) was changed by #593 (the crash window), and this PR replaces that list with host/switches.def. Please rebase onto current main (bbe6fdf2), keeping the entries main added in the list. Not rebased here since it needs the new switch added to the def file.

This conflicts with `main` now: `host/hos_main.c`'s `env_line_allowed` (the names that take a file or folder) was changed by https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/593 (the crash window), and this PR replaces that list with `host/switches.def`. Please rebase onto current `main` (bbe6fdf2), keeping the entries main added in the list. Not rebased here since it needs the new switch added to the def file.
dyst force-pushed feat/switch-list from 5255a0012a
All checks were successful
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
to c6c08d4032
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 3s
2026-11-15 19:11:57 +00:00
Compare
Author
Member

Rebased onto main d652bbb4 (head now c6c08d40); the conflict was env_line_allowed's table, where main had added HOS_CRASH_TEST (kept refused, as a LOCAL line). A new commit brings host/switches.def in step with main (59 added, 221 gone with #577's WebGPU removal and others) and has nx2/version.py's fingerprint count .def files. Checks that read this diff, not the whole suite: 68 run, 58 passed, 1 skipped, 9 failed, each failing on main too (5 at 1310ecc6, 4 at 7bacf846); the allow-list refuses and takes the same five lines as main's (game-free A/B). Description moved to the current template. Still WIP: the host's Linux build is not checked yet (Must be tested).

Rebased onto main d652bbb4 (head now c6c08d40); the conflict was env_line_allowed's table, where main had added HOS_CRASH_TEST (kept refused, as a LOCAL line). A new commit brings host/switches.def in step with main (59 added, 221 gone with #577's WebGPU removal and others) and has nx2/version.py's fingerprint count .def files. Checks that read this diff, not the whole suite: 68 run, 58 passed, 1 skipped, 9 failed, each failing on main too (5 at 1310ecc6, 4 at 7bacf846); the allow-list refuses and takes the same five lines as main's (game-free A/B). Description moved to the current template. Still WIP: the host's Linux build is not checked yet (Must be tested).
Author
Member

Host build box ticked: host/hos_main.c (with host/switches.def) compiles to an object on c6c08d40 and on main d652bbb4 for Windows (llvm-mingw clang) and Linux (gcc in Docker); changed files only, not a whole game build. Risks now say whichever of this and #911 merges second marks HOS_CONTROL_PEER_SID LOCAL in the list.

Host build box ticked: host/hos_main.c (with host/switches.def) compiles to an object on c6c08d40 and on main d652bbb4 for Windows (llvm-mingw clang) and Linux (gcc in Docker); changed files only, not a whole game build. Risks now say whichever of this and #911 merges second marks HOS_CONTROL_PEER_SID LOCAL in the list.
dyst changed title from WIP: feat(runtime): one list of the game's switches, host/switches.def, kept in step with the reads to feat(runtime): one list of the game's switches, host/switches.def, kept in step with the reads 2026-11-15 20:53:12 +00:00
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 5s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 8s
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 3s
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'feat/switch-list:dyst-feat/switch-list'
git switch 'dyst-feat/switch-list'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!62
No description provided.