Commit Graph
373 Commits
Author SHA1 Message Date
Stefan MaierandClaude Opus 5.5 76fbf67334 Merge OpenCE upstream: the high-resolution Xbox HUD completed, pause menu artwork, client-side mods, the resampler setting, unsteered vehicles' netcode
README.md keeps Ringfall's; OpenCE's README is copied to
docs/OPENCE_README.md as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:54:00 +02:00
MrBruh 7059096e1b Merge main into testing, bringing in the pause menu and HUD fixes of #378 2026-10-17 17:43:40 +13:00
chestahh b9e393c00c Apply high-resolution HUD and text settings without reloading maps
Recheck committed font settings before cached font selection, including when
high-resolution text was disabled at first use. At each frame boundary,
invalidate only cached HUD/title bitmaps affected by a changed setting so
both enabling and disabling rebuild the appropriate texture on next use.
Keep decoded replacements, font atlases, world textures and menu Apply/Cancel
semantics intact. This corrects shared cache behavior; it adds no MCC data,
map-family routing or networking/simulation changes.

Validation: Windows portable release build and 370 focused production-code,
HUD, menu and MCC checks passed. Tests cover repeated toggles, disabled text
at startup, font scale/cache reuse, selective bitmap refresh and Apply/Cancel.
Android and Web targets were attempted but are unavailable in this Windows
build graph. Live Custom Edition validation is limited by unavailable maps.

(cherry picked from commit ddeb650d82a73b570e182ff2bfd87e3cc3daa98d)
2026-10-16 21:42:21 +01:00
justinfilip 521c44f862 Keep screen fog on the canopy when the field of view is widened. 2026-10-12 20:50:57 -05:00
Stefan MaierandClaude Opus 5.5 7c6fa07cb5 Merge upstream 2026-10-12: network version 28, map sharing, pregame lobby, body and BSP fixes
Conflicts:
- rasterizer.h: upstream raised the transparent geometry groups to 2048
  as we had (halo_port_capacity.h); theirs.
- d3d8_gl.c: the ES capabilities' log with upstream's base vertex and our
  multiview.
- p2p.c, p2p_internal.h, p2p_signal.c: upstream's several joins and
  reconnect, with our join codes' state and the codes' and public list's
  updates each pass.
- network_server_manager.c: a machine downloading the map is not refused,
  and the bots' room logic stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:23:08 +02:00
MrBruh bbe00a4049 Merge pull request #286 from hkmodd/fix/hires-text-fit 2026-10-12 20:46:49 +13:00
MrBruh 3cd1a6622e Merge pull request #305 from hkmodd/perf/debug-model-vertices-static 2026-10-12 20:46:49 +13:00
hkmoddandClaude Opus 5.5 eea1c3641a Keep the debug model vertices off the stack
rasterizer_debug_model_vertices declares 2048 debug vertices of 64 bytes
on the stack. render_model calls it for each part it draws, and the
release build inlines it there, so render_model's frame was 136,304
bytes, and the Windows build probed it a page at a time (_chkstk, 33
pages) for every model drawn, although the debug display is off. Its
vertices are static now: only the vertices below debug_vertex_count are
read, each written when it is added, and the function runs on the
render thread only, so nothing it draws changes.

Measured on Windows (7800X3D, RTX 4080, release build, vsync off), b30
co-op with 32 times the enemies and a bot, 75 s a run, five runs of each
build alternated: render_model's frame is 5,360 bytes (the PDB's
S_FRAMEPROC); _chkstk fell from 2.0% to 0.5% of the game thread's
samples; fps over windows with 2000 draws a frame or more, origin/main
128, 141, 139, 134, 107 (median 134), this change 140, 139, 144, 141,
132 (median 140). Linux, Android and the web build do not probe the
stack, so the change only shortens their frame. They were not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:18:12 +02:00
hkmoddandClaude Opus 5.5 2c6c85cf38 Raise the transparent geometry groups a frame from 384 to 2048
Every transparent thing a frame draws takes a group: each transparent
part of a model, each widget (light volumes, antennas, flags, glows),
each batch of dynamic geometry (particles, contrails), each transparent
surface of the structure. The Xbox's 384 were a limit the native builds'
larger pools of objects, widgets, effects and particles could pass: a
frame past it was drawn without the rest, and debug.txt said "too many
transparent geometry groups". A part refused a group has no sort record
(models.c checks the group's index), so nothing else changes.

Checked on Windows in b30 co-op with eight times the enemies and a bot,
75 s a run: origin/main overflowed in 3 runs of 4; a build counting the
groups asked for showed up to 464 in a frame, while the dynamic triangle
and vertex buffers peaked at 123 and 328 of their 1024 and the dynamic
triangles at 10272 of 49152, so they are left as they are. With this
change, the same count showed 391 in a frame and no overflow; two more
runs had none. The pool is 2048 * 160 bytes, malloc'd; the model order
pass keeps 14 bytes a group on the stack (28 KB). Harness: the
transparent_plane_order tests pass at the new size (natively on Windows;
the other 44 failures there are the same on origin/main, POSIX headers).
Android and web builds not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:55:40 +02:00
hkmoddandClaude Opus 5.5 7a6fc70eb9 Fit the high-res text's fonts to the widths of a Custom Edition loc.map's letters
The high-res text sizes Overpass by the font tag's capitals and centres
each glyph on the tag's character width, and Overpass was chosen for the
Xbox maps' widths. A Custom Edition loc.map's fonts are narrower: the
Italian one's large_ui and small_ui are the same font, its capitals 10
units tall and its letters 87% as wide as Overpass's at that height
(against 95 to 98% for the Xbox maps' interstate, large_ui and small_ui),
so the menus' and HUD's letters ran into each other. Each font is now
narrowed until its letters A to Z and a to z are, summed, as wide as the
tag's; the Xbox maps' fonts are narrowed by 2 to 5 hundredths.

The fonts were also remembered by the tag's name, and the Xbox maps and a
loc.map have tags of the same names with other measures, and by the font
tag's address, which the next map's tags may reuse: they are remembered
by their measures too, and forgotten with the map's tags.

Checked: the fonts' widths measured from the Italian loc.map and the Xbox
ui.map against Overpass's advances; the Windows build (clang 23.1.3, full
LTO) without warnings; Extinction from the Italian Custom Edition, whose
large_ui is now drawn 87% wide, its letters apart, and the main menu's
small_ui 98% wide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:16:04 +02:00
Stefan MaierandClaude Opus 5.5 74bdffb957 Merge upstream 2026-10-11: network version 26, first-person legs and shield flare, web port, fixes
Conflicts:
- render_objects.c: upstream's first-person legs and our VR body share one
  node_matrices (ours no longer shadowed it); upstream's legs never in VR
  (first_person_legs_wanted: set back behind a flat view's eye, they would
  stand behind the player; the VR body is vr.body "full").
- AndroidManifest.xml: upstream's ':game' process left out (the Steam
  Frame's Lepton waits for the app's process to end; the headsets have no
  Java heap over the Xbox window); HaloApplication kept, idle without it.
- xinput_sdl.c: the touch controls and the web port's, never in VR; the
  controllers' rumble in VR before the phone's.
- d3d8_gl.c: multiview's uniforms and upstream's blend constant, both.
- build.yml: Android only; upstream's web and pages jobs off.
- README.md: ours; upstream's in docs/OPENCE_README.md.
- menu_tags.c: our VR pause-list fit dropped: upstream now spaces the rows
  30 apart and moves the button hints below them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:04:08 +02:00
MrBruh a3277d94dc Fewer draws and GL calls
Decals and light volumes batched, web index and vertex array caches, no FULL_ES3. Prisoner, 15 players: 115 to 172 FPS (A/B).
2026-10-11 22:28:34 +13:00
MrBruh 6399ed9d4a Text drawn a string at a time, web immediate draws packed
Scoreboard text on the web: 1.41 to 0.41 ms a frame. The network test's browse joins the fullest game that is not co-op.
2026-10-11 16:16:35 +13:00
MrBruh 01afcb654a First-person shield flare kept close only with display.viewmodel_shield (#254) 2026-10-11 15:13:49 +13:00
MrBruh 3fa1f348a9 Merge pull request #254 from chestahh/codex/opence-viewmodel-shield-fit 2026-10-11 15:05:51 +13:00
chestahh 248210cedb Keep first-person shield flares close to the arms 2026-10-11 01:52:48 +01:00
MrBruh acfa9a2a4d Web build 2026-10-11 12:46:28 +13:00
jcompto95-techandClaude Opus 5.5 8664d2f24b Your energy shield in a multiplayer armor color (display.shield_color)
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
2026-10-10 10:30:19 -04:00
Stefan MaierandClaude Opus 5.5 b6a943f1a6 Merge upstream 2026-10-10: network version 25, touch controls, in-game settings, FOV options, voice chat, votekick
248 OpenCE commits (network version 25): touch controls and touch menus for
phones, single-player in-game Settings, opt-in FOV/viewmodel settings, voice
chat and votes to kick, lens flare culling, memory leak fixes (render
targets, gamepads, the Android audio stream), profiling builds, the
HALO_ANDROID split into HALO_ARM64_GUEST / HALO_GLES / HALO_ANDROID.

Conflicts and how they were resolved:
- README.md: ours kept whole. Upstream's README changes (portable build,
  profiling builds) went into docs/OPENCE_README.md: upstream's new text
  with our header note, links rewritten to ../ and our "made from your own
  copy" wording.
- port/android/README.md: both merged; upstream's touch, WSL and save
  notes taken, with our application id in every adb path; our VR section,
  signing.properties and wording kept; the stale "How it works" list
  dropped as upstream dropped it.
- Launcher icons (mipmap-*/ic_launcher_foreground.png, art/android-icon.png):
  ours (the Ringfall art). Upstream's helmet monochrome layers,
  drawable/ic_launcher_background.xml and its ic_launcher.xml were left out;
  our ic_launcher.xml, values/ic_launcher_background.xml and
  tools/android_icon.py stay. (port/assets/icon and tools/app_icon.py come
  in for the desktop builds' window icon only; do not run app_icon.py, it
  would write the helmet into the Android resources.)
- port/android/host/host_main.c: both config helpers kept, and upstream's
  emulator write tracking (native_bridge_active); upstream's display width
  block dropped in favour of ours (640 in VR) and its display density for
  the touch controls moved into our flat (non-VR) branch.
- port/linux/game/menu_functions.c: platform_text_field(typing, password)
  from upstream; the VR keyboard launch for text fields kept after it.
- port/linux/game/network_distributed.c: upstream's profile_scope wrappers,
  with network_vr_tick and bots_tick kept in their places.
- port/linux/src/dsound_sdl.c: both (our debug.audio_log, upstream's
  audio.output_device).
- port/linux/src/port_config.c: our temp-and-rename config write kept,
  under upstream's HALO_ARM64_GUEST (it is guest file I/O).
- port/linux/src/sdl_platform.c/.h: upstream's (Android menu pointer from
  the touchscreen, Steam keyboard, scoreboard pointer); our quit marker for
  the Steam Frame launcher, clipboard_seen and VR frame hooks kept. Our
  flat-mouse menu pointer (an emulator aid) is replaced by upstream's touch
  pointer, which also drives the menus on the emulator.
- port/linux/src/d3d8_gl.c: halo_ui_pointer_update is upstream's, with the
  VR controller ray taking over while VR is active (the touchscreen then
  is not the pointer); our persistent-buffer writes kept for stream and
  index uploads, now writing upstream's exact length and under HALO_GLES
  like the code around them (stream_reserve, index_upload, mirror_refresh
  too); multiview uniforms stay under HALO_ANDROID, the counter binding
  under HALO_GLES. Visibility counters: ours kept (the snapshot ring with
  multiview views, host_gl_counters_snapshot) over upstream's per-frame
  glCopyBufferSubData into counter_snapshots: ours reads finished frames
  without stalling and counts both eyes' samples once; upstream's
  desktop query batches come in unchanged.
- port/linux/src/xinput_sdl.c: both (VR controllers and touch controls).
  In VR the touch controls neither show nor act (touch_input_gamepad,
  touch_input_controls, touch move/look skipped); rumble goes to the
  controllers in VR, to the phone otherwise.
- source/interface/first_person_weapons.c: both (VR scope pass check and
  display.viewmodel_visible).
- source/interface/ui_widget.c: upstream's reworked menu targets taken
  (ui_mouse_fit_button_targets, merged rows, widened values), which do
  what our icon_x0 key picking and the 12-unit value arrows did; our VR
  label distance (25) kept, and a VR ray counts as a coarse pointer, so it
  gets the taller legend areas and the widened values (not the merged
  rows: a row's label still presses A). Our join code and VR options
  panels kept; their early return now forgets the frame's targets too.
  The on-screen keyboard: upstream's virtual_keyboard_click for taps and
  the mouse, ours (hover highlights the key) for the VR ray only.
- source/main/main.c: both (VR phases around upstream's profile scopes).

VR guards for new upstream features:
- view_fov.c: display.fov, display.viewmodel_fov and
  display.viewmodel_visible do nothing while VR is active (the headset
  gives each eye's frustum; the weapon is in the hand).
- Touch controls: off in VR (xinput_sdl.c), the menus' touch pointer too
  (d3d8_gl.c); the overlay stays hidden as the game never reports a scene.
- Lens flare culling (744040c8, b1a71709) uses global_window_parameters'
  frustum, which in VR is each eye's (per-eye passes) or the union frustum
  of the multiview centre camera: no change needed.
- In-game Settings: VR options still open with Y on the main and pause
  menus (checked flat with debug.vr_options).
- The back button change (enableOnBackInvokedCallback=false) keeps the
  legacy KEYCODE_BACK path, which targetSdk 35 already had: no change on
  Quest or Frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:51:46 +02:00
MrBruh b1a71709ef FOV and viewmodel settings: one unit, port marks, the lens flare cull (#234)
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.
2026-10-10 16:24:04 +13:00
MrBruh a8178af24a Merge pull request #234 from innerhat-dev/fov-viewmodel-controls
Add opt-in FOV and viewmodel controls to Video Setup
2026-10-10 15:52:26 +13:00
MrBruh 400d62bb76 Merge pull request #123 from startupfoundry/split-halo-android
Split HALO_ANDROID into HALO_ARM64_GUEST, HALO_GLES and HALO_ANDROID

Conflict resolved: main's render-target eviction and mip composites are kept, with the PR's HALO_GLES guard on the ES blit fallback after them.
2026-10-10 15:41:32 +13:00
MrBruh 30771b1b2c Structure triangle limit: port comments (#232)
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.
2026-10-10 15:20:36 +13:00
MrBruh f2cb0916dc Merge pull request #232 from innerhat-dev/structure-triangle-limit
Let a frame draw 32768 structure triangles
2026-10-10 15:00:00 +13:00
MrBruh 7124534a4b Memory leaks: render targets, gamepads, Android audio stream 2026-10-10 14:42:05 +13:00
xshxdex98 5d5b5dd35e Custom Edition maps: HUD sounds, dialogue variants and camouflage on odd tag data
Three engine checks no longer stop the game on data Halo PC tolerated:
HUD sounds with no tag, dialogue variants with no dialogue, and non-model
shaders under camouflage (an environment shader on a first-person weapon:
not drawn while camouflaged rather than misread as a model shader).

These three only: OpenCE already had the commit's other repairs (protected
maps, node trees, scripts that fail to load, HUD meters and digits, object
functions, collision edges, weapon lists, more than 16 dialogue variants),
some made another way, and has no 64-bit build for its script stacks.

(cherry picked from commit d15b6ca913266b984966897e1be4e24c69a75b30)
2026-10-10 13:59:04 +13:00
lantos1618 f815e1ccba Zoom effect: no ghosting at high resolutions
The scope's screen effect (a warp: copies of the screen scaled a little
from the center, blended outside the scope's mask) spreads its copies by a
radius in the Xbox's pixels. At 640x480 the few copies blended into a
radial blur; at several screen pixels to the Xbox's one they stood apart as
sharp ghosts. The native builds keep the spread and split it into that
many times the passes (halo_screen_scale), each a step of it.

(cherry picked from commit b7fa7f742a72924514eef69d50daf31ef7f7f836)
(cherry picked from commit d1b40a6fc74ab46641313a6e0095e596494a1e7b)

Without its #ifdef HALO_LINUX, which OpenCE's builds never define (it compiled to nothing), and with the copied parameters declared with the others (gnu89).

(cherry picked from commit 763567dcc7ad8e6a851fec6bb5cb9f9e10452579)
2026-10-10 13:59:03 +13:00
xshxdex98 7df9be7785 Give unset locals values, and drop the decompiler's dated audit notes
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)
2026-10-10 12:53:22 +13:00
xshxdex98 60cd1254d6 Fix the decompiled code's latent bugs, and say plainly what is kept
Uninitialised locals get values (debug vertex, datastore result, index
buffer, map tool direction, AI entry points, escape alignment, grenade aim
from a vehicle, game options descriptions, unreachable switch arms), the
AI's squad and platoon records move whole, a speech cause point is read,
the geosphere's out-of-memory path frees itself, a console cond clause
without a result is refused, and the crash reporter rejects truncated map
files. Gameplay the original game has, kept so it plays the same, is noted
in a line rather than a page.

(cherry picked from commit 75afc4a1e57af2ba697e8be0e33b2afeee7639f8)
2026-10-10 12:53:22 +13:00
xshxdex98 65e690321d Log and error messages print what their formats ask for
Arguments a format never read are dropped, missing ones passed (the
migration speech type, DirectSound's result), a real printed as %f, a
target AI's name printed for it rather than the source's twice, and two
messages built from saved-game names printed through %s.

(cherry picked from commit dbcf4ab91c2e42c19f57ca436f1d4f2b41964582)
2026-10-10 12:53:22 +13:00
xshxdex98 744040c870 Lens flares out of view are not tested or drawn
A structure BSP's lens flare markers are submitted for every visible
cluster, and each gets an occlusion test every frame, including those
behind the camera or off the screen, whose tests count no pixels (so
they are never drawn). On the Xbox a test was nearly free; here each is
a draw and a query of its own, and a level of many lights (Medical
Block) tested about 460 a frame (debug.gpu_trace_heavy). A flare whose
test could not reach the screen, by the frustum and a sphere taking in
the test's offset point and size, is no longer submitted.

(cherry picked from commit e020bbc58dd08b4bcd609d8cf561c94b87cf4580)
2026-10-10 12:53:22 +13:00
justinfilip b980207235 Let a frame draw 32768 structure triangles.
Retail stops the list at 16384. The count is a long so it can hold 32768, and the dynamic triangle buffer keeps room for the rest of the frame.
2026-10-09 11:38:27 -05:00
Paul Hontz fb9f03cf2c Split HALO_ANDROID into the guest's ABI, the ES renderer and the app
HALO_ANDROID meant three things at once. The port's code now names each:
HALO_ARM64_GUEST for the ILP32 AArch64 guest's code paths (the inline
assembly's C, the bss pragmas, the CRT's), HALO_GLES for the OpenGL ES
renderer (its GL header and function list, shaders and capabilities), and
HALO_ANDROID for the app alone (its display, input, files and lifecycle).

The Android build defines all three, so nothing changes for it, nor for
Linux and Windows, which define none. A build for another platform can
then take one part without the others: the ES renderer, or the guest's
ABI, without the Android app.

port/android/README.md also no longer says that the widescreen changes are
in #ifdef HALO_ANDROID: none have been since 50eae19b.
2026-10-09 09:05:44 -04:00
eltanschauung cc41b768bb Add opt-in FOV and viewmodel settings 2026-10-09 08:18:29 -04:00
MrBruh 4505a43e53 Overshield links' comments and lines as the files', part 0 checked (#116)
render_model_parts now follows a link whose previous part is 0, which retail did not: of the 10862 parts of the 24 stock maps' models none has one (the needler's 2 and 3 are their only links), so it changes nothing there. The comments say what the links are for, and the long conditions are wrapped.
2026-10-09 22:34:33 +13:00
MrBruh 801d2e72db Merge pull request #116 from eltanschauung/fix/overshield-glass-compositing
Fix overshield brightness changes caused by transparent draw order
2026-10-09 22:24:40 +13:00
Stefan MaierandClaude Opus 5.5 a167de3873 Merge upstream 2026-10-08: network version 24, Custom Edition maps, positional stereo sound, fixes
Conflicts:
- d3d8_gl.c, xgpu.h: upstream's own snapshot ring for the visibility
  counters left out for ours (host_gl_counters_snapshot, the same idea,
  tried on both headsets, which also halves multiview's counts; its copy
  already has the memory barrier upstream added); both declarations kept.
- rasterizer_xbox.c: the mirrored skinning's winding and upstream's
  many-node matrices, both.
- main.c, network_server_manager.c: both (bots' machines and a lone host
  may count down).
- android_build.py: the OpenXR loader and upstream's SDL mouse patch
  (another SDL file than ours), both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:01:08 +02:00
eltanschauung b3a6490f39 Order transparent models next to planar BSP glass 2026-10-08 00:11:54 -04:00
eltanschauung c7c4feab41 Use native transparent part links for enclosed energy at map load 2026-10-07 23:49:07 -04:00
Stefan MaierandClaude Opus 5.5 448a5d5353 Merge upstream 2026-10-07: network version 21, co-op and netcode fixes, renderer speed-ups, hardening
Conflicts: port_config.c (both sides' debug settings), hud_weapon.c (the
VR crosshair filter before upstream's state index check),
first_person_weapons.c (the VR arms kept; upstream's animation node check
added, and its node count limit applied to the VR arms too).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:42:13 +02:00
MrBruh f823a18d59 Load, check and run Halo Custom Edition and OpenSauce maps 2026-10-07 19:02:01 +13:00
MrBruh 43dc11f224 Skip a cloaked model's skinned draw without node matrices
From TwistedFlog's PR #104: with the rasterizer's memory pool full, a partially cloaked model was skinned from NULL node matrices.
2026-10-07 15:27:17 +13:00
MrBruh d7efd3934a Validate map tags before loading 2026-10-07 12:01:09 +13:00
Stefan MaierandClaude Opus 5.5 68135a712d Transparent geometry: room for 2048 groups a window (was the Xbox's 384)
Every transparent thing a window draws is a group of its own: a model's
transparent part (shields, plasma, glass), each particle system, contrail
and light volume, a window's or water's surface. The Xbox had room for 384
(rasterizer_transparent_geometry_new_group); past that new_group returns
NULL and the submitter drops the geometry, logging "### ERROR too many
transparent geometry groups" once (rasterizer_xbox_models.c,
rasterizer_xbox_widgets.c; environment and dynavobgeom drop it silently).
render_window submits the objects first, then the structure's transparent
geometry, weather, particles, particle systems and contrails, so in games
of 30 and more players the late ones vanish: water and glass surfaces,
explosions, muzzle flashes, smoke, plasma glows, contrails.

The groups are a heap array (0xA0 each), a short array of sorted indices
and a bit vector of pending flags, all sized by the constant; indices are
shorts (sorted_index, presorted indices, the draw loop), good to 32767.
Nothing else depends on the number (the debug view's "all groups" index
1000 only colours groups in a debug mode). Upstream (halo-ce-universal)
still has 384.

2048 groups take 320 KB (61 KB before). A one-line log tells when a window
passes 384 and every 128 beyond, for checking big games in the headset.
In the emulator, a 36-player bot game on Blood Gulch had up to 134 groups
a window from a standing player, using under 8 KB of the rasterizer's
768 KB memory pool (the models' queued matrices and lighting), so the
pool is not the next limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:47:22 +02:00
Stefan MaierandClaude Opus 5.5 8022a0b4a1 VR left-handed: the assault rifle's ammo counter reads the right way round
The mirrored first-person model leaves its geometry mirrored; a numeric
display drawn mirrored (rasterizer_set_model_skinning's winding flag) now
shows each digit's bitmap turned over in u (1-u on the first map's texture
transform) and swaps the digits' order across the display (the quad of the
n-th digit from the right shows the n-th from the left; digit count from
the counter limit, the compass's single digit unchanged). Only for 2d,
non-screen-space first maps of numeric chicago/generic shaders, only when
mirrored: right-handed and flat output unchanged.

debug.mirror_first_person (Android, default false): off the headset the
first-person weapon is mirrored across the camera's forward/up plane as
the left hand's is in VR, for checking such things in the emulator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:33:11 +02:00
Stefan Maier f04c8c4045 Revert "VR left-handed: a part is drawn mirrored only where all its nodes are"
This reverts commit 1a6061b932e7f293cc40351f90f4d0d68edb2bd2.
2026-10-06 20:01:18 +02:00
Stefan MaierandClaude Opus 5.5 b026590824 VR left-handed: a part is drawn mirrored only where all its nodes are
The assault rifle's ammo display, mirrored back, vanished: its part's
winding was judged by its first node alone, which may be the mirrored gun,
so its triangles were turned over and culled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:54:01 +02:00
Stefan MaierandClaude Opus 5.5 d97de6d499 VR: left-handed mode, the weapon in the left hand
vr.handedness = "left" puts the weapon in the left hand: aim, muzzle,
laser, crosshair, scope and turret aim follow the left controller; the
grenade, the foregrip and the fingers' closing round a grenade move to
the right hand, the grip's melee to the left. The first-person model is
posed as the right hand's in a mirror image of the room ("model space":
vr.c mirrors the controllers into it, first_person_weapons.c the body)
and the posed skeleton mirrored back, after HaloCE-Quest-VR (CC0); a
model whose node matrices mirror has its triangles' winding turned over
(rasterizer_set_model_skinning -> d3d8_gl.c, ended with the model and
each transparent group). halo_vr_left_hand is now halo_vr_free_hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:20:59 +02:00
Stefan MaierandClaude Opus 5.5 a6350d207a VR arms 3a.0: time the first-person pose, log the hands' skin
- vr.log_performance reports how long the first-person pose takes a frame
  (its animation and the arms), how often it is built, and the arms' part
  of it (halo_vr_timing_start/_end).
- Once per hands model it logs how many triangles hang from each node and
  how many of those from the skeleton's root ('frame bone24'), read from
  the part's own buffers (rasterizer_model_buffer_data, after
  HaloCE-Quest-VR, CC0). In the emulator the cyborg's hands have none on
  the root: the ribbons of e377e4dc did not come from root skin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:22:08 +02:00
Stefan MaierandClaude Opus 5.5 9d6b980ba6 Merge upstream (OpenCE 9e4f8a2d): performance with many enemies, co-op fixes, anti-aliasing, per-pixel lighting, shadow resolution, reverb, password lobbies, network version 20
Conflicts: d3d8_gl.c (multiview variants kept beside the per-pixel lit
shaders: shader[4] and lit_shader[4], vertex_shader_get takes both;
multiview targets before multisampling; the picture read resolves both),
nv2a_vsh.c/xgpu.h (lighting and multiview parameters), render.c (no
anti-aliasing pass on VR eye passes), dsound_sdl.c, p2p.h.
VR: anti-aliasing off (the eyes go to the headset from their textures);
the VR online list skips password games (the server browser asks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 09:29:14 +02:00