A busy multiplayer fight fills the Xbox's per-frame lists of what a view
draws: 512 particle runs and 128 dynamic lights. Past them plasma bolts,
charge glows and flashlights stop drawing. The desktop builds now draw
2048 and 512. These lists are rebuilt every frame, outside the game state,
and nothing of them reaches the network. Android's and the web build keep
the Xbox's.
(cherry picked from commit f1abebdd6e89de292569ea466496fa0484476e0e; OpenCE already drew
2048 transparent geometry groups on every build, so only the particle runs
and lights are taken, with OpenCE's guards for the builds that keep the
Xbox's sizes)
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.
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)
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>
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>