Skip to content

Merge Testing - #462

Merged
bnunu merged 25 commits into
mainfrom
testing
Oct 23, 2026
Merged

bnunu merged 25 commits into
mainfrom
testing

Conversation

@cybersecurity

Copy link
Copy Markdown
Collaborator

No description provided.

chestahh and others added 19 commits October 19, 2026 20:21
Affected Android players report that the cache-bypass APK resolves stretched
and missing geometry, with some also reporting better performance. Decline
persistent vertex/index mirror requests on Android so draws use the existing
streaming fallback and current CPU index extents. No settings are needed.
The exact cache failure mechanism remains unconfirmed.

Keep streaming uploads, frame fences, shaders, texture caching and CPU write
tracking unchanged. Desktop and web retain their existing cache paths.
Xbox and Custom Edition loaders are unchanged. No simulation or network
protocol change is involved.

Carry the focused fix onto OpenCE main without fork history. Resolve the CI
entry against upstream's existing test list and omit fork-only documentation.
Add real-source Android, GLES, desktop and web regression controls, including
large/reused ranges, counter rollover and negative controls. All 33 focused
checks passed locally; the resolved files match the tested adaptation.
Local configure cannot fetch SDL3 and has no Android/web targets; CI must
perform full builds. Device evidence is player feedback on the bypass APK,
not a new on-device or cross-platform multiplayer run of this revision.

Player-Note: Prevent stretched or missing geometry on Android by streaming geometry directly.

(cherry picked from commit ea85578)
Keep synchronous cached CE pixels and hardware headers at stable addresses
outside the fixed Xbox arena, bounded to 128 MiB and 8192 entries. Only
older-frame textures can be evicted; unregister bindings, GPU copies and
channel annotations before freeing, including map/bitmap teardown and flush.
Preserve the original readers, conversion, normal GPU caching and HUD
replacement behavior. Refresh Android GL shadow state before each draw.

Keep the player-tested Android streaming geometry bypass and its regression
tests, since current upstream main does not contain that fix yet. Desktop
and web preserve their cache, upload and draw-state behavior. No fullscreen,
simulation, networking or map-format changes are included.

The engine-owned bitmap getter and teardown require small source hooks,
each marked port:. The renderer admits heap pixels only through a registered
header and validates the resource extent against its allocation. Diagnostics
are limited to unload summaries and the first allocation warning per lifetime.

Device evidence: the tester reports correct rendering and stable FPS, with
zero allocation failures, fallback substitutions or evictions across four CE
visits on Mali-G615 and 87.5 MiB peak residency. Local tests cover stable
uploads, bounds, OOM, frame locks, eviction, cleanup, HUD residency, reduced
diagnostics, normal write tracking, Android-only state refresh and geometry
streaming. All 30 upstream-focused checks passed before final CI validation.
Full Android/web builds require CI because local targets are unavailable.
No fork packaging, branding, map adapters or unrelated changes are included.

Player-Note: Fix Android Custom Edition texture corruption and repeated cache upload hitches.
Player-Note: Prevent stretched or missing geometry on Android by streaming geometry directly.

(cherry picked from commit 4ac4685)
Fix Android geometry & graphics corruption by bypassing the persistent geometry cache
# Conflicts:
#	.github/workflows/build.yml
Fix Android rendering bugs on Custom Edition maps
Server Setup's Co-op Options has ALLY FRIENDLY FIRE
(network.coop_ally_friendly_fire), ON by default as in the campaign. OFF,
the players' weapons, grenades, melee and vehicles do their AI allies no
damage, so that no player can kill Captain Keyes on Truth and
Reconciliation, the Marines, or the other allies a level needs. The AI's
own hits of its allies, the enemies' damage, and FRIENDLY FIRE between
players are unchanged. A hit is the players' when its owner is a player
and the victim is a friendly unit that is no player's, so friendly-team
vehicles are immune to the players too, splatter included. An ally that
cannot die cannot raise an allegiance incident, so the players cannot turn
the Marines hostile either.

The rule is in game_engine_friendly_damage (game_engine.c), which only the
host's damage reaches: a client's hits are the host's to deal. The host
sends the choice with the game's settings, as bit 1 of network_game's
cooperative_flags beside PLAYER COLLISIONS', so network version 33: a
client of version 32 would play the game's settings without it. NETCODE.md
says so, and network_format.txt is recorded for 33.

The menu row is tools/port_settings.py's (COOP_SETUP_SCREENS); only the
server settings screen was written again. Its 8 rows fit above the help
area.

Checked: the Windows build; the harness tests, the new
test_coop_ally_friendly_fire (a player's hit of an ally ON and OFF, the
AI's own hit, players' friendly fire in every mode, no unit, the campaign
without co-op, and four negative controls) and test_coop_scaling_menu with
the eighth row; network_format.py; the Co-op Options screen drawn with the
row; and in play as the host on a10 and a50 (Keyes and the Marines
unharmed with OFF) and b30 (no splatter). Not yet: a client's hits online,
d20's ending, c20's Sentinels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fire

Co-op hosts can make the players' AI allies immune to their fire
A scenery or device whose shield is all damage can break (Rat Race's
energy shields, the tripmines of Altis94's Bigass) was no static target
of the netcode, which took only those with a body to destroy
(network_damage.c's static_target). So a client's hits on it were never
reported to the host and the host never sent its damage: clients could
not break the shields, and when the host broke one, clients still saw it
and stood on it while the host saw them floating.

static_target now takes those with a shield too. The host sends its
damage to them, as to destructible scenery, and takes clients' hits on
them. Clients, which otherwise run no object's shields but take the
host's state of them, run these objects' shield stun and recharge
themselves (damage.c's objects_update_shields), since the host sends no
state of the map's scenery: each machine deals the same damage and
recharges the same way, so the shield's regions go and come back on
every machine.

Network version 34: a host and a client must agree on which objects'
damage is shared. NETCODE.md says so and network_format.txt is recorded
for 34.

Checked: the Windows build; the new harness test test_static_target (a
body, a shield only on scenery and on a device, neither, a unit, no
object, and three negative controls, one the old rule); the whole harness
on Windows fails the same 245 environment-bound tests as testing does,
no others; network_format.py. Not yet checked in a game: a client
breaking Rat Race's shields and Bigass's tripmines, and seeing the host's
broken and recharged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tripmine a client's player throws (Altis94's Bigass) is scenery the
grenade's effect creates, owned by the thrower, so the explosion of its
shield breaking is theirs too. The host deals no damage of a connected
client's player's but what that client reports, and this explosion went
off where the host had it, its vehicle running over the tripmine, so no
client had a hit of it to report: the host's vehicle drove over a client's
tripmine unharmed, though a host's tripmine hurt clients.

What a static target deals itself (network_damage.c's
static_target_damage: the damage's owner object scenery or a device that
damage can break) the host now deals whoever owns it, and a client does
not report it, so that it is dealt once. Part of network version 34 with
the shields' sharing before it; NETCODE.md says so.

Checked: the Windows build; network_format.py; test_static_target with a
case of a tripmine's own damage, a destructible scenery's, a unit's or
projectile's, and none, and a negative control. Not yet checked in a game:
a client's tripmine under the host's vehicle, and whether the client sees
its own copy of that tripmine go off (a tripmine is made in the game, so
it need not be at the host's index on the client).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tripmine (Altis94's Bigass) is scenery a grenade's effect makes, so each
machine makes its own copy, at an index of its own: the map's scenery is at
the same index everywhere, but such an object need not be. A client's hit
on its copy named an index at which the host had no such object, and was
refused: clients could not shoot their own tripmines to set them off. And
the host's damage to its copy named an index the client had none at, so the
client's copy did not break or go off on its screen.

A machine given another's index of a static target it has no object at
now takes its own nearest static target where the other had it
(network_damage.c's static_target_near): the host, for a client's hit, its
nearest to where the client had the target, within the target's size and
STATIC_TARGET_MATCH_TOLERANCE (a world unit), and then checks the hit as
any other; a client, for the host's damage, its nearest to the damage,
within REPORT_IMPACT_TOLERANCE and an explosion's radius. The map's
scenery, at the same index everywhere, is found by its index as before.
Part of network version 34 (no message changes); NETCODE.md says so.

Checked: the Windows build; network_format.py; test_static_target with
cases of the nearest static target where another machine had one, none
out of reach, no unit or unbreakable scenery, and the nearer of two, and
two negative controls. Not yet checked in a game: a client shooting its
own tripmine, and seeing the host's go off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_stale_player_damage compiles network_damage_deals from the sources,
which now asks static_target_damage whether damage is a static target's
own; its world had static_target but not that, so the test no longer
compiled (the Linux job's failure since the tripmine commit). Its world has
no static targets, so no damage is one's own.

Checked: test_stale_player_damage and test_static_target pass (33); the
whole harness on Windows fails the same 245 environment-bound tests as
testing, no others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-network

Scenery shields break, and tripmines go off, for clients as for the host
Match stock CE resource sheets by pixel identity and translate stock meter
redraws to CE layouts. Preserve custom artwork, correct mixed-use meter
channels and warning placement, and draw aligned controller glyphs with
High-Res HUD enabled or disabled. Scope Bigass Open v1.1 ammo changes to
its known map name and checksum.

Based on OpenCE testing 4cb621c. Keep upstream Android texture ownership,
eviction and validation unchanged; use its residency helper in the new
stock CE upscale lookup. No unrelated main-branch commits, networking
changes, regression test files or investigation documents are included.

Validation: Windows portable release build passed; 175 local CE HUD and
Android regression checks passed, 4 asset-dependent checks skipped.
Additional residency checks cover Android-managed pixels, desktop cache
entries, identity rejection and map reset. git diff --check passed.
Android/Web targets are unavailable in this Windows build graph; no new
runtime gameplay validation was performed for this rebase.

Player-Note: Fix Custom Edition HUDs, ammo counters and prompts while preserving custom artwork.
Fix Custom Edition custom HUD placements, textures and bitmap rendering
Vehicle Options' VEHICLE SET spinner indexes its strings as the sets 0
to 7, then PC (8) and CUSTOM (9) (menu_functions.c's VEHICLE_PRESET_PC
and VEHICLE_PRESET_CUSTOM), but its list had no PC: a side whose set is
CUSTOM showed "<missing string>", and one whose set is PC showed CUSTOM.

6b1d81c added the PC string to strings.xml by hand, and f97b333 made
strings.xml again with tools/ce_menus.py, which wrote only what
port_settings.py says, so it went. It is now one of port_settings.py's
STRING_INSERTS, where making strings.xml again keeps it, and so is its
help: the helps are the rows' values' in turn (gametype_option_help),
so without one, PC showed CUSTOM's help, CUSTOM the first vehicle
count's, and every count the one before its own.

tools/harness/tests/test_vehicle_set_strings.py checks that the list has
the code's sets, that each value has its help, and that strings.xml has
port_settings.py's inserts. On testing, all three fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ir own OPENCE bank of Select Gametype, with an OPENCE OPTIONS screen in the gametype editor.
Show the PC vehicle set's name and help instead of <missing string>
On Android GPUs without S3TC (Mali), DXT textures are decoded on the CPU
and uploaded as 32-bit texels, 8 times DXT1's 4 bits. A DXT1 block is two
565 colors and a 2-bit index per texel, which an ASTC 4x4 block holds
nearly as it is, so where the driver has KHR_texture_compression_astc_ldr
each DXT1 block is now rewritten as an ASTC block (dxt1_astc_block):
8 bits a texel on the GPU, with no encoder, no search and no threads.
- Four colors (c0 > c1): RGB direct endpoints of 8 bits, weights of 0,
  21, 43 and 64 sixty-fourths for DXT's thirds.
- Three colors, none transparent: weights of 0, 32 and 64 (exact).
- Three colors with transparent texels: two planes (alpha's weights of
  its own) and RGBA endpoints of 7 bits, as many as fit; a transparent
  texel takes the darker color where DXT's is black.
- The endpoints are ordered so that the decoder does not swap them and
  blend blue into the others.

DXT3 and DXT5, whose alpha does not fit beside full colors, are decoded as
before, as are volume textures, the web, and GPUs with S3TC or without
ASTC. display.dxt1_astc (Android only, true) turns it off.

On the four maps measured for the earlier encoder (928 of 1,469 DXT
textures DXT1), DXT1's GPU memory goes from 287 MiB to 72 MiB, all
textures' from 439 MiB to about 224 MiB.

Checked: a one-off check, not
kept, decoded 65,536 blocks with astcenc 5.7.0's decoder: no invalid
blocks, colors within 2 of the
game's DXT1 decode, alpha exact. ninja android builds; the CI test suite
passes. Not run on a device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cybersecurity

Copy link
Copy Markdown
Collaborator Author

Do NOT merge yet. Testing / reviewng

bnunu and others added 6 commits October 23, 2026 08:08
Give Android GPUs without S3TC DXT1 textures as ASTC 4x4, by moving bits (no encoder)
The shield glow (display.shield_glow and its Light Show intensity) and the
overshield effect (display.overshield_effect) were each player's own, in
network games too. The glow lights what is around a shield as it flares,
so a player who had it saw enemies a player without it did not, and the
overshield effect keeps an overshielded player lit: anyone who did not
turn them on was at a disadvantage.

Now a network game's are the host's, for every machine: SHIELD EFFECTS in
Server Setup > Player Options (network.shield_effects): STOCK (the
default), GLOW, LIGHT SHOW, OVERSHIELD, GLOW+OVERSHIELD or
SHOW+OVERSHIELD. Each player's own settings apply offline only (the
campaign, split screen), and Video Setup's helps say so.

- network_shield_effects.c: the host sends its choice to each client
  reliably when it is ready (distributed message 91) and to them all when
  it changes, as the aim assist policy is sent; a client takes it only
  from the host's stream, whole and valid, and draws stock until it has it.
  shield_glow.c and overshield_effect.c draw what it says in a network
  game.
- Network version 36: a build that would draw its player's own cannot
  join. network_format.txt recorded.
- Player Options' rows 27 apart in place of 30 (ce_menus.py's
  CHILD_OFFSETS), so that the tenth fits above the help, which keeps its
  three lines, and the screen's divider and buttons stay where they were;
  test_aim_assist.py's layout check follows.

Checked: ninja android builds, the changed files compile for the web, and
CI's tests pass (936). On the Android emulator, Player Options shows the
row and steps through its values with each value's help, and Extra
Effects shows its new helps. Not played as a network game.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Make the shield effects the host's choice in network games
After 343 Guilty Spark's flood cutscene (x50) with three or more players, a
client could stay on its own screen where the cutscene had parked its
player (at player0_int_base or player1_int_base) while the host had it in
the room. That client saw everyone but itself in the first Flood fight.

A client keeps its own player where it is while the host's position for it
is outside the client's loaded BSP (a BSP switch still on its way). That
was tested at the unit's feet. A teleport can leave the feet a few
millionths below the floor's plane (z -3.1e-6 on the control room's floor
at 0), which bsp3d_test_point counts as solid, so the client never took the
host's position. In a two-player game the only client is player0, whose
spot happens to test inside.

The test now uses the unit's middle: the host's position plus the client's
own feet-to-bounding-sphere offset, against its own bounding sphere center.

Checked on Windows: a hidden c10 host, two joining copies and a system link
bot, the cutscene played and skipped. Before, both clients stayed at the
parking spot; after, every machine has all four players in the room, and
each client still waited at the cutscene's two BSP switches until it had
loaded the BSP. test_elevator_correction passes (its fake object gains
bounding_sphere_center). No network version change: nothing the machines
send or agree on changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r-plane

Co-op clients take a teleport that leaves their feet on a floor's plane
@bnunu
bnunu self-requested a review October 23, 2026 18:02
@bnunu
bnunu merged commit dedb375 into main Oct 23, 2026
7 checks passed
FractumSeraph pushed a commit to FractumSeraph/OpenCE that referenced this pull request Oct 28, 2026
…rver-control-hardening

Server control panel hardening
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants