Owner ruling 2026-09-20: admit as proposed - the iterator and single-exit result
are natural; document the load-bearing declaration order in the ledger, not with
an intrusive source comment. No source comment is added.
The loop is rewritten with prop_iterator, this file's own idiom: both props.c
siblings that walk props use it (prop_get_base_by_unit_index,
prop_new_unacknowledged), January inlines it in both - there are no
_prop_iterator_* relocations - and January's prop_get_base bytes show the same
inlined header, cmp ecx,-1 then index := next then je, as this function. The
match predicate and the single-exit result follow the sibling. No new symbol is
defined.
LEDGER - THE LOAD-BEARING DECLARATION ORDER. The one fact that decides the match
is not visible in January's bytes: the single-exit initialiser long result =
NONE must EXECUTE AFTER the target-actor selection, so it is the last
declaration. Its web and the -1 constant then sit in the pre-loop join block that
initialises the cursor, lifting the cursor web's priority from 36 to 40 - a tie
with the state web that the [W+0x44] position tie-break awards to the cursor, so
it takes ecx, which is January's colouring. Declaring result first, as the
sibling does, is measured residual. Both the result web and the constant vanish
from the final code, which is why more than fifty earlier spellings - all without
a result variable, or with it initialised first - never reached it. The decoded
allocator's force-test confirms the threshold exactly (state <= 36 or cursor >= 40).
This reverses recorded conclusions R16 ("closed class-C colouring tie"), the
wave-I oracle's "UNREACHABLE by natural source", and props_obj.md's "do not
repeat" on the combined predicate, which does fail inside the plain loop but is
exact inside the iterator loop.
Verified: full ninja green; code 1,462,991 -> 1,463,135 (7,304 -> 7,305
functions); props 16/1 -> 17/0 with .text at 100%; 11,060 function rows and
1,706 section rows diffed board-wide, 0 worse; parks 179 / 0 / 0; forbid guard
exit 0; fake_match_scan 0 findings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Halo 1 decompilation

This is a work-in-progress decompilation of Halo: Combat Evolved build 2342 (cachebeta.exe, sha256 4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520).
Agent quick references
- Current campaign house rules and batch/treemap cadence
- Common constants, types, float patterns, tag IDs, and flag conventions
- Shared assertion macros and byte-matching examples
- Supplied CE source maps, recovered names, and next reconstruction packets
- Matching methodology and source-credibility rules
Build instructions
You must source the Halo 1 PAL debug build and the August 2001 Xbox SDK yourself. You also need ninja-build on your PATH.
Extract the XDK/xbox folder from the installer into the repository root such that xbox/{bin,include} are valid paths. Place cachebeta.exe from the Halo 1 build into your repository root. Navigate to the repository and run configure.py in the terminal.
Then, use ninja build to compile the game and report progress statistics, or open the cachebeta.sln VS2022 project under projects on Windows.
Where's all the type information?
We use debug symbols from later Halo games to help map structures, enums, type definitions, function signatures and some variable names. You should obtain a copy of the Halo CEA beta and run it through pdb-decompiler to obtain debug info for yourself. Note that CEA is based off of Halo PC and has its own modifications which make it not 100% accurate to the original Xbox title.