- SDL 3.4 holds an audio stream's lock through its callback, and the
game's data was put into the stream from the thread that runs the
game's callback, which then waited for that lock for ever: the first
callback never returned and nothing was heard. The data is now
gathered and put in by SDL's own thread once the game is done.
- debug.audio_log logs the level of the mixed sound.
- In VR a player's unit sees what its head points at within 15 degrees,
or what the weapon's laser points at, since the head only points
roughly where the eyes look (the training's flashing lights ask for
5 degrees).
- vr.log_performance also logs the unit's looking vector.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scripts test where the player looks (unit_can_see_point, the unit's
looking vector), and the head only set it while the game let the player
turn; the training's "target each of the flashing lights" never passed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The training at the start of the campaign waits for the look input
(player_control.c's action tests, from facing_delta), which the head
never produced. The view's turning since the last test counts too, once
past a few degrees.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With vr.aim_with = "controller" (the default), on foot:
- the unit's aiming vector comes from the right controller, while its
facing (the body, the view and the movement) keeps following the head;
- shots start at the muzzle of the weapon in the hand, kept inside the
level from the camera as before;
- the first-person weapon and hands are posed from the controller
(vr.weapon_forward/right/down place the model in the hand);
- the HUD's crosshair, which marks where the head looks, is left out, and
a laser runs from the weapon to what it aims at (vr.laser).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Android port gets an OpenXR session in the host (Khronos loader, core
OpenXR plus XR_KHR_opengl_es_enable): on a headset the game keeps its
640x480 layout drawn at the eye images' resolution, renders the player's
view once per eye from the tracked eye poses through asymmetric frusta,
and shows the HUD and menus as a head-locked or room-fixed quad layer.
The head aims the player; the right stick turns; the Touch controllers
map onto the Xbox pad; rumble goes to the controllers. Frames without a
player view (menus, loading, cinematics) go onto a screen in the room.
A marker file, xr_test, runs a self-test of the session, layers, colour
path and controllers without game data.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use the NDK's prebuilt toolchain for the build host instead of assuming
linux-x86_64, and make the StdDef.h wrapper use #include_next so that it
does not include itself on case-insensitive file systems.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
The Xbox game allows 16 players on 4 machines (4 split screen players
each). The native builds raise both limits to 128, keeping 4 players per
machine, and leave the byte-matching build unchanged: every change is
under HALO_LINUX (the MSVC objects compare identical).
- Limits: every local copy of the player and machine limits, and the
bare 4s and 16s that stood for them, follow halo_port_limits.h. The
player data array, the machine-to-player table (and its reset) and the
per-tick update arrays grow with them.
- Records: the copies of struct network_game agree on the larger layout
and check it against halo_port_limits.h; maximum_player_count becomes
a byte (128 does not fit a signed char); network_player_is_valid
checks the machine against the machine limit, not the split screen
one; a machine's input carries MAXIMUM_LOCAL_PLAYERS actions (16/4
would have become 128/128).
- Protocol: a message holds at most 4095 bytes (its header has a 12-bit
length), so the 13 KB game settings record is sent in 3.5 KB pieces
that clients reassemble; the per-tick update of 128 players (3,857
bytes) fits. Buffers and the packet codec's limits grow to match, and
the game search uses protocol version 2 so these builds and the Xbox
game never see each other's games.
- Connections: the host accepts a client connection per machine (the
split screen count stood in for it), FD_SETSIZE is 256, stream writes
send all of a message or drop a peer that stops reading instead of
corrupting the stream, and the input and update queues are larger.
- Host: lobby changes are sent at most every 250 ms instead of on every
change (a full lobby would otherwise send ~650 MB), in-game joins wait
in a queue instead of being dropped, the random name and colour
pickers stop looping forever once names or colours run out, machines
get 60 s to load a map, and the debug dump lists only the slots in
use (128 empty slots took seconds to log).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
halo_port_limits.h (force-included by the Linux and Windows prefix
headers) defines the native builds' multiplayer limits, 128 players on up
to 128 machines, and the struct network_game layout that follows from
them. Game sources use it only under HALO_LINUX, so the matching build
keeps the Xbox limits (16 players, 4 machines).
xnet.c gains two settings: HALO_NET_ADDRESS binds the game's sockets to
one local address and reports it as the machine's system link address,
so several instances can share one computer on different loopback
addresses; HALO_NET_BROADCAST sends the game's broadcasts to a list of
addresses instead, for machines broadcasts do not reach.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>