Video Setup > FOV and Viewmodels > Shield Color: DEFAULT (the shield's own)
or one of the 18 multiplayer armor colors (player_profile.c's table: white,
black, red, blue, gray, yellow, green, pink, purple, cyan, cobalt, orange,
teal, sage, brown, tan, maroon, salmon), whatever the armor's color.
No new assets: the shield's own plasma shader is drawn, its perpendicular
and parallel colors replaced by the chosen color at their own brightness
(their brightest channel), so its noise, animation and intensity are the
shader's. A local player's unit is drawn with a copy of its change colors as
the modifier's colors (render_object_list); rasterizer_plasma_energy_draw
knows that copy again and replaces the shader's colors only for it. Plasma is
added to what is behind it, so black is drawn as a faint grey.
Only this machine's drawing of its own players' shields changes: others see
your shield as their own settings draw it, and nothing sent between machines
changes. Checked by compiling the changed units.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jtk9vPUKbWd48oBMzXuzd
Video Setup > FOV and Viewmodels > Legs, off by default. In first person the
player's own body, which the game animates as everyone else sees it but does
not draw for its own player, is drawn from the waist down: looking down,
your legs walk, run, strafe and crouch as the body's animation moves them.
How it is drawn (port/linux/game/first_person_legs.c):
- A copy of the body's pose as drawn: everything but the hips and legs (by
node name: pelvis, thigh, calf, foot, toe) folded into a lid over the
waist, the root kept.
- The body set back behind the eye, each frame, as far as keeps the waist's
open rim beyond the bottom plane of the view (the way Halo 2's fp_body
keeps its open top out of sight): looking ahead, 4 cm; straight down at
105 degrees, about 67 cm. The legs are seen as they swing forward.
- Drawn with the world's camera, so it keeps its place and size at any FOV;
not in mirrors, not in the shadow pass, without what it carries.
The waist's rim is found from the model's own triangles: object_mesh.c reads
an object's drawn mesh (its most detailed geometry, in the permutations it
shows) from the vertex and index buffers the game draws it from, as
powerup_render_bounds.c reads them; its cache is forgotten on a new map
(objects_initialize_for_new_map).
Only the drawing changes: the body, its hit boxes, markers, the camera and
everything sent between machines are the game's. Checked by compiling the
changed units; the fold and set-back were checked against a capture of the
cyborg's mesh and pose and played on Windows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jtk9vPUKbWd48oBMzXuzd
render_fov.c, viewmodel_fov.c and viewmodel_visibility.c are one unit,
port/linux/game/view_fov.c, with a header comment as the others have, real
for float, _pi for its own pi, the rasterizer's target by name, and no
isfinite shim in math.h (the angles' range test already refuses NaN). The
game code's hooks are marked "port:", their include at the end of each
block, and rasterizer_lights.c's loops declare before they act (C89).
The first-person weapon's lens flares are not culled by the world's
frustum (main's new off-screen cull): they are
drawn at the weapon's own projection, which display.viewmodel_fov can make
wider than the world's.
HALO_VIEWMODEL_VIS is HALO_VIEWMODEL_VISIBLE; the settings' descriptions and
help lines say "stock" view and fit their boxes; Video Setup's XML is
written again by ce_menus.py; the README's field of view text is a section
of its own.
The raised limits' and the walk's comments are marked as the port's, with the unverified HAC2 and MCC comparison left out; the walk's says why the index is compared whole, and the once-only log of a frame reaching the limit gets a comment of its own.
Particles of one kind are drawn together, at most 8 bitmaps' worth. A Halo
PC map's particle may have a bitmap a frame: beavercreek_rev_beta's fluid
bursts have up to 56. A debug build halted ("a build_sprites_begin call can
accomodate at most 8 bitmaps") when such particles were in view; a release
build drew the first 8 bitmaps' sprites and not the others. The builds that
play Halo PC's maps now do as a release build does in a debug build too, and
log it once. The Xbox's maps' particles stay within 8, and the Xbox build is
unchanged.
Without its #ifdef HALO_CUSTOM_EDITION, which OpenCE never defines (it
compiled to nothing): the log is for Custom Edition maps
(custom_edition_cache_tags_loaded), the assertion stays for the Xbox's.
(cherry picked from commit afa6413f1e922621cc04e7953e730d5571b3aae6)
25 notes ("left unassigned only by this default arm ... approval pending,
2026-09-27 audit") argued that a variable was never read unset. Where the
arm ends in system_exit they were right and simply go. A release build's
assertions return, though, so where the arm only asserts the variable now
starts with a value (a Custom Edition map's HUD data can reach hud_draw's).
A failed map precache reads as failed.
rasterizer_debug_drawing_begin had two declarations, one with an argument
its definition never takes; it now has one, and the port's macro papering
over the mismatch is gone.
(cherry picked from commit 74f8a048e4c3cc7dbc4b050dd41a8bae912bb367)
The average radius of a group whose particles were all culled divided
zero by zero, leaving a NaN in the effect shader's secondary map radius.
(cherry picked from commit 11128fd78ade85c50a9a3a5a292bd2bb33bebf30)
(cherry picked from commit b52d79541dc2143de41943367542ae63ad4f384f)
Rotational sprites draw their edge-on view from the sequence after the state's. A particle bitmap on foundation has only one sequence, which halted the game in particle_system_render. Without that sequence the face-on sprite is drawn alone.
(cherry picked from commit d436a0c0c3abaf069dd34e4b8d761b49569311e6)
display.anti_aliasing, off by default: "fxaa" or "smaa" (a pass over the
3D view before the HUD and menus; SMAA vendored from port/third_party/smaa,
MIT), "ssaa2x" (the screen's targets at twice the resolution, at most the
GPU's largest target) and "msaa2x" to "msaa8x". Multisampled framebuffers
have every attachment multisampled, so the mirror's view with the back
buffer's depth buffer is too, and a target's texture and renderbuffer stay
coherent. The setting is read again between frames. Android has FXAA for
SMAA and no supersampling.
Based on #38 and #39 by Tyberious.
Recover transparent geometry submit (+1,285 meaningful code, zero exact losses); reconcile COMMON ownership and Q10 85+EXT1 credit, actions/main data, and separately disclosed denominator corrections. Preserve canonical-only repairs and all held research. C09 is ordinary disclosed cleanup, not a claim of proven scaffolding intent. Clean rebuild, 1,663 tests, parks, audits, provider links and independent EXT1 check pass. Local reconciliation only.
Import only independently reviewed production changes. Preserve canonical physics and virtual-keyboard repairs; keep B3 and all unresolved holds out.
Record exactly four approved canary debits (6987 meaningful bytes), six Halo admissions and two revocations. Keep vendor ioinit/storage work separate. Full build, 8252-row sweep, 1318 tests, park/admission/fake audits and 621-object binding pass within approved debit bounds.
Do not publish donor research dumps or private assets. README and unrelated user research remain untouched. See frontier_publication_reconciliation_20260927.md for complete evidence limits and accounting.
Independently gate storage + K, OQ-4 P-a/P-b1, four static-local packets and comment-only disclosures. Preserve all 7641 exact owner rows, 71 valid parks and 1161 passing tests; code/data credit unchanged. G and game_engine admission remain held because current canonical loses populate_statistic_buffer. Existing collision static-local repair is not duplicated. No donor tree, held candidate, scorer or private asset imported.
The Xbox game state (0x345000 bytes at 0x80061000) ends exactly where the
map-linked tag cache begins and has 948 bytes free, so a 128-player
session cannot even allocate its player datums. The native builds now
place a 16 MB game state (CPU 0xFC0000, GPU 0x40000) at 0x81A00000, above
the tag cache and below everything the Xbox memory window hands out
top-down, and grow the pools that scale with the number of players:
- objects: 2048 -> 8192 headers, 1 MB -> 8 MB pool; the garbage limits
keep January's proportions (5/10/20 % of the pool, 2.5/5/10 % of the
headers, 75/50/30 active garbage objects per 16 players)
- cluster partition reference lists 2048 -> 8192 (collideable and
noncollideable objects, lights); a full list drops objects out of
rendering, collision and sphere queries
- effects 256 -> 2048, effect locations 512 -> 4096
- particles 1024 -> 8192 (render_particles' visible list, filled without
a bound check, follows), particle systems 64 -> 256, their particles
512 -> 4096
- contrails 256 -> 1024, contrail points 1024 -> 8192
(MAXIMUM_CONTRAIL_POINTS stays the pool size for the same reason)
- lights 896 -> 4096, object looping sounds 1024 -> 4096
- cached object render states and rendered objects 256 -> 1024
- script object-list references 128 -> 1024, objects one explosion can
damage 64 -> 256
The values live in port/linux/include/halo_port_capacity.h, included by
halo_port_limits.h. With 128 player datums the CPU part holds 14,256,908
bytes (2,258,164 free). Saved games and cores grow to 16 MB. Every change
is under HALO_LINUX; the MSVC objects are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Approved packets, no owner ruling needed:
- real_math.h plane3d_negate gets its attested body (negate_vector3d plus
the d term; /Od 0x56d630 and the HCEX_Release line table), together with
the render_objects /Od shadow-volume plane pair and the bipeds genuine
helper calls. _biped_find_nearby_support_surface is now exact (+544). A
467-unit header review lost 0 exact rows. The bipeds park is retired, and
render_cameras _render_camera_build_frustum is refreshed to
3408/112/d42e420f (target unchanged).
- biped_falling_danger, update_airborne, snap_facing, update_moving and
fudge_vectors become file-static, as the Sept-2001 map STATIC list and the
retail private ABI show. Their prototypes leave bipeds.h and symbols.json
marks them static. This is zero credit; bipeds pdb_storage goes to 0. The
parked ai _ai_test_ballistic_line_of_fire is rebaselined for the resulting
declaration-count drift; no exact row is lost.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zero credit; every packet was independently adversarially reviewed (22/22 approved).
- critic_3: 72 renames of placeholder/invented static function names across 20
objects to first-party names. Each rename has Sept-2001 linker-map alignment
(cachebeta xbe / retail cache exe, several also Aug-2001), relocation-masked
body identity and matching callers; cachebeta publics show every row was a
January static. hs's radiosity_hack_{start,save,find_point}_evaluate pairing
is proven by the Sept .rdata hs_function_definition pointers; players'
create_weapon also matches HCEX.pdb. Objects: ai_debug (reviewer-amended: a
dead stub removed, its comment re-attached), transport_endpoint_winsock,
transport_endpoint_set_winsock (+ parked.json key renames), profile,
progress_bar, network_connection, saved_game_files, rasterizer_xbox_profile,
xbox_sound_cache, game_engine_king, players, hs, hs_runtime, main, decals,
rasterizer_lights, rasterizer_xbox_dynavobgeom,
rasterizer_xbox_environment_fog, rasterizer_xbox_hardware_bitmaps,
render_cameras.
- hs_compile: whitespace_characters, eol_characters and hs_type_primitive_parsers
are external (cachebeta publics, HCEX DataIsGlobal); hs_compile_finish is
static with a TU-local prototype (no public; HCEX static function).
- bink_playback: bink_playback_idle -> bink_playback_update__internal
(first-party). The bink_decompress_audio_frame rename is NOT landed: it needs
an added call whose position is unattested, the same class canonical held for
hardware_geometry in 4d1ebf17.
Gate (full ninja, objdiff 3.3.1): objects 383, code 1,577,237, data 2,586,915
(all unchanged); stable diff 0 regressions; parks 83/0/0; admission 11/0/2/0;
fake scan 26; pytest 1161 passed; diff --check clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All packets passed a precedent audit and an independent adversarial review.
No object changes status.
- Storage per cachebeta publics (source static + symbols.json rows):
- bink_playback: four globals;
- weapons: 11 rows + weapon_magazine_finish_reload;
- object_lights: 4 helpers; should_render_lights is the /Od-attested call and
its prototype leaves the public header;
- vehicles: _update_turret_physics;
- weather_particle_systems: one_over_char_max is external (cachebeta public,
HCEX Global); its globals are static;
- rasterizer_xbox_debug: 8 D3DINLINE wrapper rows (already Matching: audit
FAIL(8) -> PASS, pdb 8 -> 0).
- draw_string: the invented external draw_string_globals aggregate (pads, blob,
#define aliases) becomes four HCEX-attested file statics in /Od declaration
order with = { 0 } (a595bbc2 precedent); typed multitexture params.
- render_debug: three rule-6 hand expansions become real point_from_line3d
calls (ruling #1/#2); the opaque vehicle view gives way to struct
vehicle_datum + vehicle_datum_try_and_get; the six debug_* toggles become
tentative definitions (COMMON evidence).
- vehicles: the TU-wide REAL_MATH_EXTERNAL_POINT_FROM_LINE3D define is gone and
the pathfinding hand expansion becomes the genuine call (ruling #1).
- rasterizer_xbox_profile V1R (reviewer-amended): byte-inert /Od parameter
order, the BUG marker comment, detail_objects via the rasterizer_xbox.h API,
and a rejection text that keeps the SDK-table policy question open.
- semantic_data_matches.json: single-section '$'-defect entries with
allow_incomplete_unit for projectiles _projectile_update_section (1,548 B) and
object_lights _lights_section (1,541 B) (leaf_map / editor_flying_camera /
race precedents).
Gate (full ninja, objdiff 3.3.1): objects 384 (unchanged), code unchanged,
data +3,089; stable diff 0 regressions; parks 83/0/0; admission 10/0/2/0; fake
scan 26; pytest 1159 passed; diff --check clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- symbols.json: IDirect3DDevice8_IsBusy/KickPushBuffer and IDirect3DBaseTexture8_IsBusy
are static (D3DINLINE is static __forceinline; none is a cachebeta public).
- Three invented static names replaced by first-party names from the 2001-09-25
cachebeta-xbe linker map (atlas 7eacac85, re-anchored on 20 named symbols):
texture_cache_name_block_proc, compare (also January atlas exact tier) and
texture_cache_initialize_hardware_format.
- bitmap_group.h (shared, 45 includers): struct bitmap_data fields per HCEX
(mipmap_pad, long pixels_offset/pixels_size/tag_index/cache_block_index);
bink_playback.c and bitmaps.c adopt the names. The TU-local bitmap_data view
and raw tag_get('bitm') prefix view in xbox_texture_cache.c are gone.
- texture_cache.h declares texture_cache_debug_render (render_debug.c had no
prototype in scope). The Xbox-only public format mappers get the object's own
header cache/xbox_texture_cache.h. Adding them to texture_cache.h regresses
declaration-count-sensitive consumers (decals); this is disclosed in the header.
- Reviewer amendment: the invented pad member reserved006[2] in the TU-private
texture struct is removed (natural alignment; HCEX texture_datum has no pad).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
objects.h: both bounding-sphere inline assertions report OBJECTS_H_FILE, which
defaults to January's relative "..\objects\objects.h". object_lights defines the
absolute spelling first, as January's string census shows. action_vehicle loses
its NODUP hand copy of object_get_bounding_sphere, so the header inline is the only
definition. render_objects' lighting_storage becomes the static local of
object_get_cached_render_lighting (symbols.json).
path.h: the opaque __unknown140A0[0x5C] span is HCEX's `struct path_result
result`, and path.c stores through the field instead of a punning cast.
Consumer sweep (full ninja, objdiff 3.3.1): stable diff shows 0 regressions and no
moved rows beyond the batch-1/Layer-2 gains. Parks 93/0/0, admission 15/0/7/0,
pytest 1157 passed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Structural lane batch 3: +4,128 padded / +4,101 meaningful bytes strict
exact (3 functions), zero stable-verdict regressions.
- rasterizer_xbox_active_camouflage.c: _rasterizer_active_camouflage_draw.
The debug build (0x7cd9c0) writes each normal/hyper-stealth blend as one
(1-p)*base + p*hyper expression. The texture-animation vertex constants
are a block-scoped aggregate initializer, so both constant arrays share
a slot as in January.
- render_particles.c: _render_particles. The draw pass indexes
group_particle_counts[group_index] with a short loop, and the inner loop
is while (particle_count-- > 0), advancing the particle at the body end
and before the delete-path continue (/Od 0x84f800).
- rasterizer_xbox_shadows.c: __rasterizer_environment_shadow_begin. The
debug build's boolean success = TRUE is returned once, and the
translation terms use dot_product3d (/Od 0x80d870; HCEX array name
vsh_constants__screenproj).
Rule-24 disclosure (owner per-site admission, 2026-09-21): two new
(real_vector3d const *)&shadow_matrix->position casts, one per
dot_product3d call. The /Od build calls dot_product3d at 0x80db50 and
0x80dbc2 with the matrix position. Deleting both casts leaves the
function strict exact, and point/vector share the three-real layout.
parked.json: unpark _render_particles and __rasterizer_environment_shadow_begin.
The owner packet gains the aggregate 3D->2D view-copy question.
Gate: ninja PASS, parks 112/0/0, admission 0 contradicted/0 revoked,
provider link PASS, fake scan unchanged, pytest 1152 passed / 5 skipped
/ 26 subtests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Integrate verified source and data progress; exclude unproven COMMON ownership, held UB/asm forms, and address-named data credit. Stable sweep: 23 exact functions gained, zero lost.
Integrate six accepted exact functions, two whole-object admissions, evidence-backed zero-credit source corrections, owner-header cleanup, and curated campaign records. Preserve zero regressions and exclude generated scratch archives from canonical history.
- _render_debug_add_cache_entry: success-first single exit, string case
if/else, one case body per debug type as January emits them
- _ctf_engine_weapon_update: long return-team locals from the owner team
field (January's 32-bit movsx locals)
- _action_uncover_perform: timeslice-block locals, one evaluation-mode
store (removes HEAD's duplicated arm stores), field-order target stores
- _row_dither: indexed channel loops with PIN clamps replace pointer
cursors and a hand-written ternary clamp
- _lruv_debug_to_file: removes a goto web; MIN(9999, age) and the
NULL-name fallback in the fprintf arguments (integer compare order
disclosed; constant-first MIN is attested in Bungie source)
- _action_guard_perform: short firing-position index matching the
actor_select_firing_position return type
render_debug, game_engine_ctf, action_uncover, bitmaps_quantitize,
lruv_cache and action_guard are now all-function exact.
Stable diff: 0 regressions; active parks 219 -> 213.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reviewed reconstructions, each strict exact in its whole-TU gate with
zero inherited losses, guard passing and no new owners:
- rasterizer_xbox_screen_effect (13/13): complete per-arm shader setups,
load-before-call locals, January assert texts, PIN clamp; screen_flash
projection spelling and the defined inverse-pixel default arm
- hs_compile: _hs_parse_begin (per-branch result type; January's extra
sprintf name argument kept with a BUG comment), _hs_parse_cond_recursive
(single exit; January's always-true negation test kept with a BUG
comment, byte-proven and recorded in HCEA)
- geometry: definitions in January object order (assert lines ascend),
duplicate prototype removed, _get_edge_vertex single exit
- render_cameras: view_to_screen and build_frustum_bounds simplifications
- sound_manager: _sound_dispose_from_old_map loop-exit flag
Rejected in review: _encounter_test_rule (redundant default stores),
_render_camera_mirror (point_from_line3d COMDAT), _sound_set_definition_end
(prototype contradicting its definition).
Stable diff vs 9062b1e96: 0 regressions; parks 255 -> 250.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both admitted by explicit owner rulings on 2026-09-16; each lands as the minimum
hunk after a whole-TU gate, and neither involves undefined behaviour or steering.
render_debug _render_debug_player (+266, park reopened and removed). LAW D, from
the research campaign's frame study, proves January's `sub esp,0x404` cannot come
from a dead local or any other declaration - a dead whole object costs 0 frame -
and only a declared text extent of 1025-1028 yields it. Written in the house
idiom as a named capacity plus its terminator, added to the file's existing
constants enum rather than a new block: `MAXIMUM_RENDER_DEBUG_PLAYER_TEXT_LENGTH =
1024` and `char text[MAXIMUM_RENDER_DEBUG_PLAYER_TEXT_LENGTH + 1]`. The tree
already uses `[X_LENGTH+1]` string buffers 70+ times. This ruling supersedes the
pre-LAW-D park rejection of enlarging the buffer. Whole-TU gate 34 -> 35 with only
this row changing; the sibling park _render_debug_add_cache_entry is unchanged; the
added enumerator shifted no declaration-count-keyed row; fake scan 0 leads.
hud_draw _real_rgb_color_to_pixel32 (+181, previously unwritten). A genuine
bitmaps_inlines.h color-conversion helper, admitted under house rule 10. The owner
ruling rests on affirmative hand-written-assembly evidence in January's bytes -
dword fistp and fmul on non-top x87 stack slots (fmul st(3),st(0)) - not merely on
asm being able to force a match. The permission covers this one body only; it does
not authorize _real_argb_color_to_pixel32, _fast_ftol_C or assembly elsewhere.
Whole-TU gate 20 -> 21 exact, including _hud_draw_meter, which calls it three
times. fake_match_scan: 3 leads, 2 of them pre-existing at HEAD (the naked
get_return_eip); the only new lead is this admitted block.
Full ninja, parks 271 active / 0 stale / 0 invalid, stable diff vs
scratch/opus5-next150-before.json: gained 12 / 8,992 padded, regressions 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wave w1 landing, adversarially verified. exact: _render_object_shadow_end, _object_render_state_refresh. Full build of the combined batch: 54 strict gains / 29,440 padded, 0 regressions, parks 355/0/0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The edge factors are spelled (-inverse_z) inside the MIN/MAX arguments (macro argument duplication) instead of hoisted positive locals. 1 park(s) removed. Adversarially verified (wave D park re-investigation); full build of the combined wave D set: 0 regressions, parks 402/0/0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
+1 strict exact function, 384 padded bytes (previously residual). Adversarial
review accepted; no top-level declaration was added and the other three
render_sprite residuals keep their tags. A proposed spelling for
build_sprite_transform_origin_and_direction that would write a vector over its
own parameter home was not landed (owner/UB ruling required).
render_sprite: 7 exact / 3 residual.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>