7.2 KiB
render_contrails.obj exact-match log
Outcome
source/render/render_contrails.obj is a strict whole-object match for the
January 14, 2002 Xbox build. All six functions match in padded size,
relocation count and identity, relocation-normalized bytes, and SHA-256. The
three target-owned string COMDATs also match exactly. The consolidated XDK
3911 build succeeds, and the shared rasterizer ABI/layout corrections preserve
the already-Matching 131-function rasterizer.obj.
In plain English: this file builds and traverses each live contrail, computes
the strip's two vertices per point, shades and fades them, builds its triangle
indices, and submits the completed dynamic geometry. The reconstruction uses
ordinary readable C. It contains no inline assembly, volatile codegen trick,
__forceinline, undefined behavior, byte patch, compiler-flag override, or
fuzzy acceptance.
Strict evidence
| Function | Meaningful bytes | Padded bytes | Relocations | Normalized SHA-256 |
|---|---|---|---|---|
_contrail_fade |
143 | 144 | 6 | 7dc3dde6b3c8f5af61facf91de6d51d91ff268eaf8173d9911a94fbc6a867f83 |
_code_00177860 |
1945 | 1952 | 57 | 70d28d083222f55ac171cb1aa9676d018fb2bcae9ee54f09facee54755cef5e8 |
_code_00178000 |
176 | 176 | 9 | 16ce1e5bee24c8a0f0e79659476d2d619b783419e9ba49d3cb2a2c71bccd94fa |
_render_contrails_ground_mapped |
9 | 16 | 1 | 1b1a80b01bf5912843c9d879bc793dd8ac269b037598c7afa05a0752095dbb5f |
_render_contrails_media_mapped |
9 | 16 | 1 | f27c91ab09dc5b6f75808b4ae85f5e00e23c249e0ad6466b48ef6c5bc216fe06 |
_render_contrails_normal |
9 | 16 | 1 | 07a8bcb483de4cb8bba2c0b5dac4ad15eb04f47cde8cb833f3b376ba44abf179 |
Total code is 2,291 meaningful bytes and 2,320 padded bytes. The target-owned
.rdata COMDATs are also exact:
| Data | Bytes | SHA-256 |
|---|---|---|
"contrail %s uses an unsupported render type." |
45 | 38b10bfb93e324bcd9ff15b429387e6e917890cf2b008360bddc77ce09375249 |
"triangles && vertices" |
22 | 6faca77985ef8484b9433bf5961df25e5c373bbb4a3515ebc9fc5a29ba2e0aa2 |
| January assert file path | 41 | 9a3ff7ea5d44b5f3e438ca53d746335c870e6add38e784766b7d21f22e4cce17 |
The ordinary visual reporter still assigns _code_00177860 98.45% because it
does not understand all local-label/section representations. The hardened
COFF comparator proves the 1,952-byte function and all 57 resolved relocation
destinations are identical; this is a known reporter false negative, not a
tolerance or semantic approximation.
Recovered types and interfaces
contrail_point_stateis0x68bytes.contrail_shaderplacesframebuffer_fade_modeat+0x2c.contrail_definitionis0x144bytes and itsstatesblock is at+0x138.contrail_datumis0x44bytes.contrail_point_datumis0x38bytes.rasterizer_globals.current_lock_operationis ashortat+2; the full rasterizer-global structure remains0x68bytes.- The corrected unlit draw ABI is
(shader, bitmap, animation, triangle_buffer_index, vertex_buffer_index, vertex_count, centroid, flags). - Typed access uses
contrail_definition_get,object_get, andTAG_BLOCK_GET_ELEMENT, in line with the project house rules.
Experiment history
The object began with only the three tiny render-mode wrappers exact. The following source shapes were accepted:
- Expressing
contrail_fadethrough the existing vector helpers reproduced the 144-byte function; manual scalar arithmetic produced 160 bytes and was rejected. - The natural
data_next_indexiterator, typed contrail tag getter, and four instance loop reproduced_code_00178000at 176 bytes and nine relocs. - Correcting the recovered vertex, point, state, shader, definition, and rasterizer-global layouts moved the large renderer from 1,888 bytes/58 relocs through 1,904 and 1,920-byte shapes to the target 1,952/57 topology.
- Direct scalar eye/tangent calculations and the January cross-product operand order reproduced the viewer-facing branch and both orientation normalizations.
- Moving
half_width *= 0.5fimmediately before the four texture-coordinate stores fixed an otherwise independent three-byte scheduling window. - The final mismatch was only two compiler stack slots. Writing the two
loop-carried updates as
texture_u += texture_u_step;followed byprevious_point = point;changed their live-range order and closed every remaining byte without changing the algorithm.
Measured and rejected shapes included aggregate/union packing of the two loop
locals, declaration-order permutations, declaration initializers, an early
NULL initialization, delayed texture initialization, nested scopes, and
several alias forms. These either had no effect, changed broad register
allocation, or regressed already-correct code. They should not be repeated.
The unsupported-render-type arm retains its early return because that is the
January control-flow shape. This is the documented house-rule exception to the
preferred single-return style; forcing a common exit changes the exact object.
That arm also preserves an original cleanup bug: it skips the dynamic-buffer
unlock/delete calls and leaves current_lock_operation set. The source labels
the bug and describes the non-matching fix (route the arm through common
cleanup) without changing January behavior.
Shared-header blast radius
The recovered layouts and corrected rasterizer ABI live in shared headers, so
the audit did not rely on Ninja's ordinary header tracking. A detached clean
worktree at campaign tip e30b1568 and the candidate worktree each rebuilt
the same seven translation units from scratch: render_contrails, contrails,
objects, rasterizer, ai_debug, cinematics, and main. Comparing every
defined function with section_infos_equal and every non-debug data section
found zero changes outside render_contrails.obj.
The raw regression manifest reported debug-record, section-number, and accepted
evidence churn, including an apparent ai_debug_render_actor regression. That
was not a code regression: a fresh baseline build already has the same current
nonexact function, and baseline-to-candidate hardened comparison is exact.
This fresh-build cross-check prevents stale .obj files from being mistaken
for a patch regression while still failing closed on real code, relocation, or
owned-data changes.
Verification commands
The final candidate was rebuilt with repository-configured XDK 3911
CL 13.00.9254.1 and /O2 /Oy- /DDEBUG /Dxbox, then checked with:
ninja build/base/source/render/render_contrails.obj
python -m tools.coff_compare build/split/source/render/render_contrails.obj build/base/source/render/render_contrails.obj <all six function symbols>
python -m tools.coff_compare build/split/source/render/render_contrails.obj build/base/source/render/render_contrails.obj <all three target-owned rdata symbols>
ninja halobetacache_build
ninja semantic_progress
ninja progress
python -m unittest discover -s tools -p "test*.py" -v
All strict comparisons returned all_equal: true; the consolidated build and
semantic report completed with zero errors. The progress gate admitted the
object (262/468 Halo units Matching at this checkout), and all 173 tooling
tests passed.