Skip to content

Environment Variables

M T edited this page Oct 4, 2026 · 1 revision

Environment Variables

The runtime is configured almost entirely through HALO_* environment variables. This page lists every environment variable read by the source tree at commit 9f915af: about 150 runtime switches plus the variables used by tools and tests. Each entry gives the default, the accepted values, the effect, and where it is read. Subsystem pages explain the behavior behind each switch in more depth.

How variables are applied

Read once. Most host switches go through HOST_ENV(name) (host.h:110-121). This macro caches getenv per call site for the life of the process, because several switches sit on the per-draw path. Others cache in a static int enabled = -1, or in pthread_once (HALO_RADIAL_FOG). Changing a variable after launch has no effect.

Launch defaults on visionOS. A normal headset launch has no shell environment. The engine worker therefore installs a fixed list of defaults with setenv(name, value, 0) before host_run (EngineVisionRuntime.m:612-645). Because overwrite is 0, a value supplied at launch always wins. That includes values from an Xcode scheme's environment, or from a devicectl process launch that passes environment variables. The list is mirrored in mods/runtime-settings.json:

Variable Headset default
HALO_FF3D 1
HALO_PANORAMA 1
HALO_PANORAMA_DENSE 1
HALO_PANORAMA_WORLD_FP 1
HALO_PV_SKIN_FAST 1
HALO_NATIVE_GATHER 1
HALO_DRAW_FASTPATH 1
HALO_PAD2KEY 1
HALO_A10_AUTOPLAY 0
HALO_UNLOCK_CAMPAIGN 1
HALO_AUDIO_VOICE_TRACE 1
HALO_CTLLOG 1
HALO_HSC_TRACE 120
HALO_HSC_TRACE_MAX 128
HALO_CORE_TELEMETRY 1
HALO_TEXTURE_PACK path of the bundled TextureMods.hvt, if present
HALO_SHADER_PACK path of the bundled ShaderMods.hvs, if present
HALO_CMDLINE_EXTRA -vidmode W,H,60, from HALO_VIDMODE, else the stored HaloRenderResolution, else 2048,1536,60

On the Mac (halo-host and the probes), none of these defaults are applied. The "Default" column below means the value when the variable is unset. Where the headset default differs, it is noted.

Live settings. The variables in the Live settings table only seed HaloSettings. The in-app settings window can change them afterwards. See Runtime Settings.


Live settings

These are read by ensure() in halo_settings.c:43-84. Numeric values outside the accepted range fall back to the default.

Variable Default Accepted Effect
HALO_STEREO on 0 turns it off 0 forces mono, with zero eye separation.
HALO_STEREO_IPD 63 mm 40–90 Half-separation in world units = mm / 1000 / 2 / 3.048.
HALO_STEREO_SEPARATION derived from the IPD 0–1 Sets the half-separation in world units directly.
HALO_PANORAMA_VFOV 105° 60–175 Vertical field of view of every panorama view.
HALO_HAPTICS strength 1 0 turns it off 0 sets haptics strength to 0.
HALO_BACKDROP 1.0 0–2 Brightness of the surround backdrop.
HALO_SPATIAL_MENU on 0 turns it off 0 renders the front-end menu flat instead of spatially.
HALO_PANORAMA_TARGET_FPS 30 10–60 The "keep at least" target that steers the bearing budget.
HALO_SELF_GAIN_DB 18 dB 0–24 Gain added to the player's own weapon sounds.
HALO_GAZE_POINTER off exactly 1 The menu cursor follows the head.
HALO_LAYER_ALIGN off exactly 1 Experimental Layer Alignment.
HALO_FRAME_PACING off 1, even or on Experimental Frame Pacing.
HALO_RADIAL_FOG off exactly 1 Eye-distance Radial Fog. Read once with pthread_once (halo_settings.c:20-31).

Startup and the command line

Variable Default Effect Read at
HALO_VIDMODE unset W,H,Hz for the game's -vidmode. Overrides the stored resolution and the 2048,1536,60 default. EngineVisionRuntime.m:681
HALO_CMDLINE_EXTRA unset; on the headset, set from HALO_VIDMODE Extra arguments appended to "C:\Halo\halo.exe" -window -novideo. main.c:15, EngineVisionRuntime.m:711
HALO_CORE_TELEMETRY app: on; anything starting with 0 turns it off Engine-thread frame-split, residency and wait telemetry. Decided once before host_run. EngineVisionRuntime.m:658
HALO_PANORAMA_GPU headset: on unless 0; Mac: off unless set and not 0 Zero-copy panorama hand-off through the bridge's GPU slot pool. EngineVisionRuntime.m:704
HALO_UNLOCK_CAMPAIGN off (headset 1) Unlocks every campaign level in the menu, in memory, on each main-loop tick. See Engine Overrides and Hooks. overrides.c:245

Panorama and stereo

See Panorama System and Panorama Budget and LOD.

Variable Default Effect Read at
HALO_PANORAMA off (headset 1) Exactly 1 enables multi-bearing panorama rendering. panorama_hooks.inc:381
HALO_PANORAMA_DENSE off (headset 1) Narrower projections: 32° half-angle for the ring, 48° for the caps. panorama_hooks.inc:267
HALO_PANORAMA_CAP_HALF_FOV 48 Cap half-angle in degrees, 20–80. panorama_hooks.inc:281
HALO_PANORAMA_WORLD_FP off (headset 1) Builds the first-person weapon once per view from the centre pose and draws it as world geometry. panorama_hooks.inc:396
HALO_PANORAMA_VIEWS unset all keeps the game's own renderer record count in every pass. panorama_hooks.inc:30
HALO_PANORAMA_OVERLAY_ALL_VIEWS unset 1 runs weapon, HUD and interface code in every bearing, not only the centre. panorama_hooks.inc:334
HALO_PANORAMA_FRAME_PER_BEARING unset 1 restores the old per-bearing frame-counter and time-step advance, for comparison. panorama_hooks.inc:527
HALO_PANORAMA_TIGHT_BUDGET on 0 restores the older schedule (gaze views plus one rotating layer) and never forces mono. panorama_hooks.inc:459
HALO_PANORAMA_ALL_VIEWS unset 1 ignores the budget and draws every layer every frame. panorama_hooks.inc:451
HALO_PANORAMA_FORCE_TIER unset 0–3 holds a budget tier outside menus. A Mac measurement aid. panorama_hooks.inc:491
HALO_PANORAMA_LOD distance nearest measures along the nearest bearing's axis. bearing or 0 uses the original per-bearing depth. panorama_hooks.inc:68
HALO_STEREO_ROLL on 0 offsets the eyes along the level camera instead of the rolled head. panorama_hooks.inc:43
HALO_LENS_FLARES off 1 keeps lens flares. Otherwise they are cleared each frame because they do not stitch. panorama_hooks.inc:538
HALO_FXAA on 0 copies world layers without FXAA on the zero-copy path. panorama_render.inc:325

Panorama diagnostics:

Variable Effect Read at
HALO_PANORAMA_TRACE Bounded logs of entry, projection, visibility and interface events panorama_hooks.inc:205,363,376, panorama_render.inc:170,180,290
HALO_PANORAMA_SCOPE_TRACE 1 logs weapon and material scope boundaries panorama_hooks.inc:152
HALO_PANORAMA_FP_PROJECTION_TRACE 1 logs first-person projection values panorama_hooks.inc:121
HALO_PANORAMA_WORLD_FP_TRACE 1 logs first-person cache build and reuse panorama_hooks.inc:100
HALO_VIEW_DUMP Logs the first 8 frustums panorama_hooks.inc:596
HALO_PANORAMA_CAPTURE (with HALO_FRAME_CAPTURE) Writes every layer as .bgra every 60th valid frame panorama_render.inc:390-391

Rendering (Direct3D 9 to Metal)

See Direct3D9 Bridge and Metal Renderer.

Variable Default Effect Read at
HALO_FF3D off (headset 1) Enables the CPU fixed-function 3D path for declaration draws with no shaders. d3d9_render.inc:831
HALO_DRAW_FASTPATH off (headset 1) Exactly 1 enables resident static vertex buffers (128 MiB cap), folded clears and encoder-state reuse. 0 keeps the comparison path. metalrenderer.m:197
HALO_NO_ANISO off Non-0 disables the forced 8× anisotropic trilinear filtering. metalrenderer.m:2602
HALO_TEX_FALLBACK off Non-0 binds white when a fixed-function stage's texture is missing. metalrenderer.m:2603
HALO_PIPELINE_WORKERS 3 Background pipeline-compile threads, clamped to 0–6. metalrenderer.m:2014
HALO_SHADER_PREWARM 1 0 disables shader prewarming. metalrenderer.m:2015
HALO_PIPELINE_CACHE 1 0 disables the persistent pipeline recipe store. metalrenderer.m:2213
HALO_PIPELINE_CACHE_DIR <Caches>/HaloVision/pipelines Location of the pipeline store. metalrenderer.m:2214
HALO_PIPELINE_ARCHIVE 0 Non-zero enables a Metal binary archive, when the device supports one. metalrenderer.m:2183
HALO_PIPELINE_ARCHIVE_SAVE_MS 15000 Delay before the archive is saved. metalrenderer.m:2094
HALO_TEXTURE_PACK unset (headset: bundled .hvt) Path of the texture replacement pack. texture_mod_runtime.inc:17
HALO_TEXTURE_MODS enabled 0 disables texture replacement. texture_mod_runtime.inc:17
HALO_SHADER_PACK unset (headset: bundled .hvs) Path of the pixel-shader replacement pack. shader_mod_runtime.inc:7
HALO_SHADER_MODS enabled 0 disables shader replacement. shader_mod_runtime.inc:7

Rendering diagnostics (all off by default):

Variable Effect Read at
HALO_PIPELINE_TRACE Pipeline creation log metalrenderer.m:1390
HALO_STATEBLOCK_TRACE 1 logs stateblock capture and apply d3d9.c:321
HALO_SAMPLER_TRACE Logs distinct sampler settings d3d9_render.inc:473
HALO_DRAW_PROFILE Per-draw CPU timing, plus a [draw-profile] log every 120 frames d3d9_render.inc:404,414
HALO_DROPTALLY Per-reason counts of rejected draws d3d9_render.inc:264
HALO_DRAW_REJECT_TRACE, HALO_DRAW_REJECT_FROM, HALO_DRAW_REJECT_TO Rejected-draw trace over a frame window d3d9_render.inc:212
HALO_RENDER_TRACE_FROM, HALO_RENDER_TRACE_TO, HALO_RENDER_TRACE_EVERY Per-frame draw summary over a frame window d3d9_capture.inc:28-29
HALO_RENDER_CAPTURE (directory), HALO_RENDER_CAPTURE_FROM, HALO_RENDER_CAPTURE_TO, HALO_RENDER_CAPTURE_PASS (0–2), HALO_RENDER_CAPTURE_LIMIT (default 40, max 256), HALO_RENDER_CAPTURE_VS (only shader draws), HALO_RENDER_CAPTURE_FVF (FVF filter) Draw payload capture with selectors. Invalid selectors disable capture. d3d9_capture.inc:170-172,210-212
HALO_FRAME_CAPTURE (directory), HALO_FRAME_CAPTURE_EVERY (default 250), HALO_CAPTURE_DENSE (every 20) Back-buffer frame-NNNN.bgra + .json dumps at Present d3d9.c:733-737
HALO_FF3D_FLAT, HALO_FF3D_SHADE, HALO_FF3D_WHITE Debug colouring in the FF3D path d3d9_render.inc:714-716
HALO_FF3D_NOALPHA Ignore the alpha test in the FF3D path d3d9_render.inc:709
HALO_FF3D_LOG, HALO_FF3D_PASSES, HALO_FF3D_RAW FF3D logging (material, light, pass signature, raw vertices) d3d9_render.inc:672,739,761, d3d9.c:771-775
HALO_FF3D_DUMPTEX (directory) Dump the first 40 decoded textures as BGRA d3d9_render.inc:343

Geometry and native engine routines

See Geometry Fast Paths and Engine Overrides and Hooks.

Variable Default Effect Read at
HALO_NATIVE_GATHER off (headset 1) Exactly 1 uses exact native BSP gathers (005540C0, 00553C40, 00553F10). overrides.c:193
HALO_NATIVE_VISIBILITY native 0 uses the translated 00553920. verify runs both and compares. overrides.c:157
HALO_NATIVE_LEAVES on 0 disables the native hot math leaves. native_leaves.h:441
HALO_PV_SKIN_FAST off (headset 1) Exactly 1 enables the exact-token skinning fast path in ProcessVertices. d3d9_process_vertices.inc:19
HALO_PV_DIFFERENTIAL, HALO_PV_DIFFERENTIAL_FROM_FRAME off Compare the fast and generic ProcessVertices, starting at a frame. d3d9_process_vertices.inc:5,8
HALO_PROCESS_VERTICES_TRACE, HALO_PROCESS_VERTICES_CAPTURE off ProcessVertices logging and capture. d3d9_render.inc:1060, d3d9_capture.inc:210
HALO_FP_CAPTURE (directory), HALO_FP_CAPTURE_FROM off One-frame first-person weapon vertex capture. fp_vertex_capture.inc:21-22
HALO_MODEL_CAPTURE (directory), HALO_MODEL_CAPTURE_FROM, HALO_MODEL_CAPTURE_OBJECT off One-frame actor model capture. model_capture_hooks.inc:9, model_vertex_capture.inc:28-29

Audio

See Audio System.

Variable Default Effect Read at
HALO_AUDIO_FRAMES 1536 AudioQueue frames per buffer, 64–2048. There are always 3 buffers. directsound.c:306
HALO_AUDIO_CAPTURE_WAV unset Write the final mix as a 16-bit stereo 48 kHz WAV to this path. directsound.c:309
HALO_AUDIO_CAPTURE_SECONDS 30 Capture length, 1–1800 s. directsound.c:314
HALO_AUDIO_VOICE_TRACE off (headset 1) Voice, listener and Vorbis tracing, with bounded 5-second summaries. directsound.c:101
HALO_AUDIO_OWNERSHIP_TRACE off Exactly 1 logs sound-ownership snapshots (max 512). audio_ownership_trace.inc:63

Input, controllers and haptics

See Input and Controllers and Haptics.

Variable Default Effect Read at
HALO_PAD2KEY on (headset 1) Pad to keyboard and mouse bridge. 0 disables it and exposes the native DirectInput joystick instead. dinput8.c:328, d3d9.c:551
HALO_LOOKSCALE 25 Mouse counts per frame at full right-stick deflection. d3d9.c:564
HALO_PAD_REUSE_US 4000 One controller capture serves all polls within this window, 0–20000 µs. gamecontroller.m:81
HALO_HAPTICS_ONSET on 0 disables the per-voice onset detector. haptics.c:95
HALO_HAPTICS_GUARD on 0 disables the haptics link guard (pacing and backoff). gamecontroller.m:110
HALO_HAPTIC_MIN_INTERVAL_MS 250 Minimum pulse spacing, 0–5000. gamecontroller.m:112
HALO_HAPTIC_CONNECT_GRACE_MS 3000 No pulses for this long after a controller connects, 0–60000. gamecontroller.m:113
HALO_A10_GAMEPAD off 1 installs a session-only joystick binding preset in a10. a10_gamepad.inc:39
HALO_EYE_MENU off 1 attempts CompositorServices tracking areas for eye-hover menus. EngineImmersive.swift:52

Input diagnostics and scripting (Mac probes):

Variable Format Effect Read at
HALO_KEYSEQ start:end:hexScan,... Holds DirectInput scan codes during a frame window. d3d9.c:528
HALO_LOOKSEQ start:end:dx:dy,... Injects relative mouse deltas during a frame window. d3d9.c:536
HALO_CTLLOG presence Every 60 frames, logs the pad, device packet and control record. On by default on the headset. d3d9.c:570
HALO_A10_TRACE presence a10 main-loop and gamepad diagnostics. a10_control.inc:9, a10_gamepad.inc:41
HALO_A10_AUTOPLAY 1 Diagnostic only. Forces Heroic, mark_fast_setup and input gates so a10 skips the tutorial. It changes save state, so it is not evidence of playability. The headset sets it to 0. d3d9.c:625

Win32, threads, script tracing

See Win32 Compatibility Layer and Threading and Synchronization.

Variable Default Effect Read at
HALO_GUEST_THREAD_QOS inherit QoS for Halo's own threads: inherit, interactive, initiated, default or utility. off or an unrecognised value means no QoS attribute. threading.c:249
HALO_IO_WAIT on 0 restores the Sleep(0) spin at the map cache-read wait sites. On by default, it is a bounded 1 ms condvar wait. shims_kernel32.c:231
HALO_FILELOG off Logs opens of .map, savegame and a10 files. shims_kernel32.c:440,531
HALO_FINDLOG off Logs FindFirstFile patterns and matches. shims_kernel32.c:544-546
HALO_HSC_TRACE off (headset 120) Script-thread snapshot interval. 0, empty or non-numeric means 120. hsc_trace.inc:103
HALO_HSC_TRACE_MAX 128 (max 512) Events per snapshot. hsc_trace.inc:106
HALO_HSC_TRACE_ALL off Also emits dormant threads (wake −1). hsc_trace.inc:108
HALO_TRACE_LO, HALO_TRACE_HI unset Hex guest PC range for an instruction trace. Requires chunks built with ENGINE_STEP_FULL=1. host.c:627
HALO_CAPTURE_PC, HALO_CAPTURE_DIR unset Test-only capture of resident guest memory at a PC, for differential tests. host_snapshot.h:6

Present-time engine debugging hooks

These live in IDirect3DDevice9::Present in d3d9.c:583-709. They are development tools that write guest memory or call guest functions. They are not for normal play.

Variable Effect
HALO_POKE8, HALO_POKE32 hexaddr=value,... writes bytes or words to the image range 0x400000–0xC00000 every frame.
HALO_PEEK hexaddr,... logs those words every 60 frames.
HALO_FORCEDIFF Forces the campaign difficulty (0 easy to 3 legendary) in both the options global and the live game globals.
HALO_SETGLOBAL idx=val,... sets HSC scenario boolean globals by descriptor index.
HALO_SETMODE1_AT At frame N, sets the game mode word to single-player.
HALO_MKSESSION_AT, HALO_MKSESSION_FN At frame N, calls a guest function (default 0049d210).
HALO_SAVEWATCH, HALO_SAVEFORCE Logs save-busy flags; forces the save-busy flag clear.
HALO_WAKE_SCRIPT Wakes a dormant HSC thread by script index.
HALO_SCAN_THREADS Logs the HSC thread table every 90 frames.
HALO_SCAN_DEVICES, HALO_OPEN_DEVICES Logs nearby device machines every 120 frames, and optionally forces them open.
HALO_TRACE Logs mode, map, screen and session globals on change or every 60 frames.
HALO_CONSOLE_FRAME, HALO_CONSOLE_CMD At frame N, runs a console command through the game's console executor (004c6a80).
HALO_LOADMAP, HALO_LOADMAP_FRAME, HALO_CAMPAIGN, HALO_DIFF, HALO_GAMEMODE, HALO_GAMEMODE_FRAME Requests a map load at frame N. With HALO_CAMPAIGN, it calls the real solo campaign start (0049cfd0) at difficulty HALO_DIFF (default 1).

visionOS presenter and diagnostics (Swift)

Variable Default Effect Read at
HALO_REPORT_SECONDS 30 report.json write interval, clamped to 1–600. Non-numeric values use 30. EngineDiagnosticReportWriter.swift:50
HALO_SIM_HEAD unset yaw,pitch in degrees replaces the head pose (Simulator). EngineImmersive.swift:356
HALO_SIM_CAPTURE unset 1 writes a PNG every 60th frame to Documents/SimCaptures. EngineImmersive.swift:869
HALO_SIM_CAPTURE_LAYERS unset 1 also captures each layer. EngineImmersive.swift:870
PANEL_DIVISIONS 64 Grid divisions per panorama panel edge. EngineImmersiveScreenGeometry.swift:261

See Immersive Presenter and Diagnostics and Telemetry.


Tools and tests

Variable Used by Effect
HALO_EXE tools/engine_reuse/upstream.py:21; set by setup_halo.py:362 Executable read by the generator, the import export and test_decode (default game/halo.exe).
HALO_GENERATED_ENGINE, HALO_ENGINE_GEN run_source_checks.py:25, benchmark_x87_rotating_stack.py:35 Generated engine directory. By default the checks auto-detect native/build/engine-reuse/whole-exe, also in the main worktree. Checks that need it print SKIP without it.
HALO_RADIAL_FOG_GENERATED_DIR run_source_checks.py:101 Generated directory for the radial fog test only.
HALO_ENGINE_TRANSLATION run_source_checks.py:155 Directory for the translated-allocator voice-reuse check.
CC run_source_checks.py, the benchmark C compiler (default clang).
WINEPREFIX, WINEDEBUG setup_halo.py:173 Set to .setup/wine-prefix and -all for the installer. An inherited WINEARCH is removed.
HALO_RADIAL_FOG_VSH, HALO_RADIAL_FOG_RDATA, HALO_RADIAL_FOG_MSL_DIR test_radial_fog.c, test_radial_fog_renderer.m Optional fixtures, and the generated MSL output directory.
HALO_TEST_GATHER_MAP, HALO_TEST_B30_MAP test_gather_pipeline.c:365-366 Your own map file, for the real-level gather test.
HALO_TEST_TEXTURE_PACK test_texture_mod_pack.c:61 An optional real .hvt to parse.
HALO_FRAME_CAPTURE and the probe variables below native/EngineVision/Tests/MenuInputProbe.m, tools/probe_engine_menu_input.py Mac menu and input probe controls. See Input and Controllers.
PREVIEW_FLAT, PREVIEW_HALF_FOV PanoramaCompositePreview.swift Composite preview tool options.

Mac menu and input probe (MenuInputProbe.m)

Variable Effect
HALO_PROBE_FRAMES Frame limit for the probe run.
HALO_PROBE_LIVE_SECONDS Length of a live-controlled session.
HALO_PROBE_INPUT_FILE, HALO_PROBE_INPUT_FROM_FRAME A live JSON pad mailbox, and the frame from which it is honoured.
HALO_PADSEQ, HALO_STICKSEQ, HALO_NO_PROBE_INPUT Scripted pad buttons and sticks, or no injected input.
HALO_PROBE_POINTER u,v pointer target test from frame 300.
HALO_PROBE_MOUSE_TRACE (dx,dy,frames), HALO_PROBE_MOUSE_STAIR, HALO_PROBE_FIND_CURSOR Cursor-response measurements.
HALO_PROBE_SNAPSHOT_AT, HALO_PROBE_CAPTURE_PANORAMA Exact-frame snapshot, and panorama layer capture.
HALO_PROBE_FRAME_TIMING 1 reports frame timing and the draw profile every 120 frames, and observes guest pose without live input.
HALO_PROBE_GPU_CENSUS, HALO_PROBE_GPU_CAPTURE_AT Periodic GPU resource census; a Metal GPU capture at a frame.
HALO_PROBE_RENDER_AB 1 runs an in-process ABBA comparison from frame 1441. It toggles the draw fast paths and the fast texture CRC in 240-frame blocks.
HALO_PROBE_SUSPEND_AUDIO 1 pauses audio before the engine starts.
HALO_OBJECT_CENSUS Periodic object census after frame 450.

Compile-time switches (not environment variables)

Macro Default Effect
ENGINE_FLAT_MEMORY defined by every build Flat 4 GiB guest addressing.
HALO_ARM64_FENV_FAST 1 in every game build Inline FPCR rounding for non-nearest x87 modes. See x87 Floating Point.
ENGINE_STEP_FULL 0 Instruction budget, counter and PC trace.
ENGINE_TRACE_HOOKS 0 Treats trace-only addresses as hooked.
HALO_TRANSLATED_ALLOCATOR test only Builds a voice-reuse check against translated allocator code.
HALO_HASH_BENCH test only Benchmark mode for test_texture_content_hash.c.

Related pages

Clone this wiki locally