Skip to content

Contributing Guide

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

Contributing Guide

This page expands CONTRIBUTING.md and AGENTS.md into a working guide for people changing the code. It covers what to install, where a change belongs, how to test it, and the rules that keep the public tree free of game data and private material.

1. Set up a development checkout

git clone https://github.com/mitchaiet/master-chef.git
cd master-chef
python3.12 -m venv .venv && source .venv/bin/activate
python -m pip install -r requirements-development.txt   # capstone, pefile, numpy, Pillow, unicorn
python3 tools/run_source_checks.py --portable-only      # no game files needed

You can do most work on the host runtime without game files. That includes renderer state handling, the mixer, the panorama scheduler, pacing, settings, setup and tooling, all of which are covered by synthetic fixtures. Some work needs your own game/halo.exe and a generated engine:

  • running the app, on the Mac probe or the headset;
  • differential tests against translated original functions (they print SKIP without them);
  • anything that changes generated code.

The Setup Wizard and Build System pages explain how to produce these.

Task Needs game files? Needs Apple signing? Needs a headset?
Portable source checks No No No
Full source checks (Metal, Swift, Obj-C) No No No (an Apple Silicon Mac)
Engine generation Yes (game/halo.exe) No No
Unsigned --direct Release build Yes No No
Installing and running Yes Yes Yes

2. Know where your change belongs

You are changing... Start in Read first
How x86 instructions become C tools/engine_reuse/, third_party/xwa/tools/ Static Translation Pipeline, XWA Decoder and Lifter
Guest CPU semantics (flags, x87, memory) native/EngineReuse/ EngineReuse Runtime, x87 Floating Point
A Windows API the game calls native/EngineHost/shims_*.c, threading.c Win32 Compatibility Layer
Replacing or observing an engine function native/EngineHost/overrides.c, engine_hooks.h Engine Overrides and Hooks
Direct3D 9 behavior d3d9.c, d3d9_render.inc Direct3D9 Bridge
Metal pipelines, samplers, caches metalrenderer.m Metal Renderer
Shader conversion metalshader.c, third_party/mojoshader Shader Translation
Panorama views or scheduling panorama_*.h/.inc Panorama System, Panorama Budget and LOD
Audio directsound*.c and audio_session.inc Audio System
Controllers, menus, haptics dinput8.c, gamecontroller.m, haptics.c, EngineMenuInput.swift Input and Controllers, Haptics
The headset presentation native/EngineVision/Sources/EngineImmersive*.swift Immersive Presenter
Diagnostics and reports EngineDiagnostics*.swift, core_telemetry.h, tools/*telemetry* Diagnostics and Telemetry
Setup and packaging tools/setup_halo.py, tools/visual_assets.py, tools/prepare_engine_vision_device.py Setup Wizard, Visual Mods Pipeline

3. Code conventions you will see

  • Explain the evidence in the comment. Comments cite the original function address (for example 0050BEA0), the measured result, and the build where a behavior was verified. They also say why the obvious alternative was rejected. Keep that style. A future reader needs to know whether a constant was measured or guessed.
  • Default-off diagnostics. Tracing and capture switches are HALO_* environment variables. They are read once and cached, usually through HOST_ENV() in host.h, because several sit on the per-draw path. A diagnostic must never change guest state or choose a render path. See Environment Variables.
  • Feature switches keep the comparison path. Optimizations such as HALO_NATIVE_GATHER, HALO_DRAW_FASTPATH and HALO_PV_SKIN_FAST keep the translated original path when explicitly turned off. This allows A/B comparisons on the same build.
  • Bounded everything. Caches, traces, history files and captures have fixed caps. Examples: the 128 MiB geometry ownership cap, the capped diagnostic history, and render-capture limits of 1–256. New caches need a cap and a defined behavior under pressure. Since 1.0.2, a full cache reuses entries instead of refusing new state.
  • Fail visibly. Unsupported D3D state or shader paths return a real failure and record a diagnostic. They are not counted as draws. Unsupported translated instructions fail generation. The lifter has no no-op fallback.
  • .inc units are included into one translation unit (usually d3d9.c) and share its static state. Tests often #include the same .inc to test the exact production code.
  • Exact floating point. The app target compiles host and generated code with -frounding-math -ffp-contract=off (project.yml), and so do the x87 source checks. The desktop Makefile does not pass these flags. Do not let the compiler fuse or reorder arithmetic that must match the original engine.

4. Testing a change

  1. Run the portable suite: python3 tools/run_source_checks.py --portable-only.
  2. On Apple Silicon, run the full suite: python3 tools/run_source_checks.py. It adds the Metal, Obj-C and Swift checks.
  3. Optionally run the sanitizer pass: --portable-only --sanitize. CI runs it.
  4. For setup changes: python3 tools/test_setup_halo.py.
  5. Add a regression next to the code. For a host C file, add native/EngineHost/tests/test_<area>.c and register it in tools/run_source_checks.py. For the app, add a validation main in native/EngineVision/Tests/. Testing and Source Checks describes the registration patterns.

When you report results, keep the levels of evidence separate, as the project's own docs do:

Level What it shows What it does not show
Source checks The logic matches synthetic fixtures The original game behaves the same
Differential checks against generated code The native replacement matches translated original code on recorded inputs A full mission behaves the same
Desktop Metal checks or the Mac probe Rendering and shaders work on a desktop GPU Headset performance, compositor behavior
Unsigned build succeeds Everything compiles and links Signing, installation or launch
Headset launch Install and startup Gameplay quality, stable FPS, audio continuity
Headset gameplay measurements Frame rate and behavior in that mission or checkpoint Other missions, long sessions

5. What must never be committed

The public tree contains only source, documentation and small manifests. .gitignore and tools/check_repository_hygiene.py --strict enforce this. CI also runs the strict audit.

  • Game files: halo.exe, maps, Strings.dll, movies, saves, profiles.
  • Generated engine code (native/build/) and compiled objects.
  • Product keys, registry exports (*.reg, halo-vision-registry.txt).
  • Signing material (*.p12, *.p8, *.mobileprovision, …), app packages (*.app, *.ipa, *.xcarchive), device identifiers.
  • Visual packs (*.hvt, *.hvs, *.tpf). These are release assets, not Git content.
  • Raw diagnostic captures. Attach only reviewed excerpts to issues.

Third-party notices must stay intact beside vendored code and in native/EngineVision/Resources/ThirdPartyNotices.txt.

6. Reporting bugs

Use the bug report form. Include:

  • the release tag and app build;
  • the visionOS version and controller model;
  • the mission and checkpoint;
  • the reproduction steps;
  • for graphics issues, whether the problem happens while stationary, while turning with the stick, or while moving your head.

Check Known Issues first.

Related pages

Clone this wiki locally