Skip to content

Reimplement native multiplayer command selection and ordering - #221

Open
Krarilotus wants to merge 2 commits into
sourcehold:mainfrom
Krarilotus:reimplement/command-selection
Open

Reimplement native multiplayer command selection and ordering#221
Krarilotus wants to merge 2 commits into
sourcehold:mainfrom
Krarilotus:reimplement/command-selection

Conversation

@Krarilotus

@Krarilotus Krarilotus commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

TL;DR: Reimplements how Crusader chooses and orders queued multiplayer commands, preserving the game's batch limits and player priority. Retains the native ordering for commands from one player and the original unknown-player failure paths.

Implements GameSynchronyState::getCommandIDFromCommandSelectionStuff (0x480440) as C++03 using the existing function and struct resolvers. No generated headers, shared source lists or transport code change.

The implementation preserves:

  • Scanning from the current physical ring entry through entry 199, without wrapping inside the selector, and selecting at most 100 due commands.
  • Signed comparisons for the state byte and command tick, including the original high-bit behavior.
  • Stable ascending logical-player order, retaining ring order for one player's commands.
  • The original unknown-player asymmetry: only a zero player on the right of a compared pair rejects selection. A lone unknown player or one first in order can pass; rejection can leave a partially sorted selection.
  • The selected count, entire selection buffer and last translated protocol actor, including failure paths.

Validation:

  • Built OpenSHC.dll with MSVC 2005 SP1, RelWithDebInfo. The fresh comparison build uses a current Windows SDK manifest tool, so the DLL includes its manifest. No build override is part of the PR and no deploy target ran.
  • 941 original/C++/reference comparisons for Crusader and 941 for Extreme using x86 emulation: empty/full rings, physical-end boundaries, 100-command batches, every state byte, signed time boundaries, duplicate/unknown player handles, SP/MP identity modes, stable ties, descending order and randomized queues. Checks cover the complete receiver memory, return value, stack cleanup, callee-saved registers and permitted writes. Both sides use the original identity translator; the memory-fill helper is stubbed to its checked 800-byte zero-fill contract. Extreme's different field layout is represented explicitly in the fixtures.
  • Linked reccmp comparison at 0x480440: 64.89%, 310 compiled function bytes versus 301 native bytes. The soft status entry records 64.89%; register allocation and loop/return layout still differ.

The validation harness and original game data remain local. This PR does not enable multiplayer replay or claim a completed live multiplayer determinism test.

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.

1 participant