Skip to content

Merge parity tooling and RA retail fixes - #234

Merged
hughobrien merged 320 commits into
mainfrom
worktree-cleanup-parity-fixes
Jun 29, 2026
Merged

Merge parity tooling and RA retail fixes#234
hughobrien merged 320 commits into
mainfrom
worktree-cleanup-parity-fixes

Conversation

@hughobrien

Copy link
Copy Markdown
Owner

Summary

  • merge the parity tooling and root-of-trust capture work from the dirty worktree
  • fix RA retail movement parity behavior and document the divergence status
  • fix Nix app toolchain PATH so clang is available for canonical build/test apps
  • fix Emscripten strlwr/strupr shim compatibility

Verification

  • nix run .#build
  • python3 scripts/lint-lp64.py --errors-only
  • targeted RA behavior and RA95 patcher/capture tooling tests

hughobrien and others added 30 commits May 18, 2026 18:33
Port wisdom from wine-cnc-capture.sh into drivers/wine.py docstring.
Update docs to point to capture-checkpoint / parity instead.
No programmatic callers. Only suggested in echo error messages.
Update error messages to point to script headers instead.
tgautil.py was an unused EA CnC Remastered TGA utility. The scripts/archive/
directory and its references were leftover from a prior archival that was
never completed. Clean up all docs references to the archived scripts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move RA-specific scripts to scripts/ra/, TD-specific to scripts/td/,
and regression scripts into game-specific subdirs. Update all active
references across docs and test runners. Remove empty scripts/regression/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Single entry point replacing first-run-pass-94.sh, T6-ra-native-smoke.sh,
and T11-ra-native-m2-smoke.sh. Supports three modes:
- boot: 30s quick check (>=100 frames, no crash)
- release: 120s CI gate (>=1 win, >=1000 frames, no crash, FPS)
- m2: 120s mission-specific (RA_SCENE=SCG02EA.INI, >=200 frames, no crash)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace first-run-pass-94.sh, T6-ra-native-smoke.sh, and
T11-ra-native-m2-smoke.sh with scripts/ra/ra-native-smoke.sh
supporting boot/release/m2 modes. Remove the stale manual clang++
build step (handled by build-native.sh/cmake) and clean up regression/
directory. Update all documentation references.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
No callers — the WASM test flow goes through test-runner.sh instead.
Update all documentation references to point at test-runner.sh.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the manual g++ compilation loop in packages.redalert with
a cmake invocation identical to packages.tiberiandawn's approach.
Eliminates the duplicate build description — cmake is now the single
source of truth for both Nix package builds and script-based builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nocd-patch.py, ddscl-patch.py, focus-skip-patch.py,
game-in-focus-patch.py, and vqa-skip-patch.py are all RA95.EXE-specific
patches (TD has its own for C&C95.EXE). Move them from scripts/ root
into scripts/ra/ with consistent ra- naming, matching the existing
ra-autostart-patch.py and ra-scenario-patch.py convention.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
No callers — every script that needs Xvfb does inline pkill+Xvfb+sleep.
Remove the script and update all documentation references.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove duplicate entries (build-native.sh, test, vqa-decode.py),
add missing entries (ra-vqa-skip-patch.py, parity.sh, test-runner.sh),
remove dead entry (ci-local.sh), fix proper alphabetical ordering,
and update stale "first-run-pass" reference.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Merge wine-ra.sh capabilities into drivers/wine.py and add
title/menu capture types to capture-checkpoint.py.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…kpoint)

Each WineCapture run now gets a fresh prefix via tempfile.mkdtemp,
matching wine-ra.sh's ephemeral approach. Auto-cleaned in _cleanup.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Set DirectDrawRenderer=gdi and virtual desktop 640x480 via Wine reg,
and write REDALERT.INI with PlayIntro=no. These were gaps identified
between wine.py and wine-ra.sh.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Launches RA95 under Wine without scenario patches, dismisses the
DirectSound dialog, and captures a screenshot at a fixed delay
(10s for title, 22s for menu). Uses 640x480 resolution throughout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Support capture-checkpoint.py title and capture-checkpoint.py menu,
dispatching to WineCapture.capture_boot(). Early-return before the
mission/vqa flow since boot captures don't need scenario resolution
or cross-target comparison.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All Wine capture scenarios (title, menu, mission, VQA) are now
handled by capture-checkpoint.py via drivers/wine.py. The new
capture_boot() method covers title/menu with the same ephemeral
prefix, GDI config, and REDALERT.INI that wine-ra.sh used.

Closes the wine-ra.sh → capture-checkpoint.py migration gap.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Design doc for wiring RA_AUTOSTART_SCENARIO env var in INIT.CPP
and fixing the native driver to set cwd to data directory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add getenv("RA_AUTOSTART_SCENARIO") check in INIT.CPP alongside the
existing RA_AUTOSTART_SCENARIO.FLAG file check. Flag file still wins
if both are set (more specific override).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
RA binary finds MIX files relative to CWD, not via DATA_DIR env var.
Add cwd=data_dir to Popen call and fallback to DATA_DIR env var for
the data directory when not passed explicitly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Default output root changed to /tmp/battlecontrol with <timestamp>-<type>-<id> session dirs
- Capture and diff files flattened into session dir (no nested subdirs)
- Driver logs prefixed with target name to avoid overwrites
- HTTP server auto-starts on port 1234 if not already running

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
No utility — just prints the manifest and exits.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Exit silently instead of printing "CLEAN — no hazards found."
Also suppress the header in lint.sh when there are no findings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The wine allied-l1 capture was producing half-width, palette-mangled output
because ra-ddscl-patch.py was stubbing IDirectDraw::SetDisplayMode. That stub
was correct under wined3d (Wine forwards the call to NtUserChangeDisplaySettings
which Xvfb refuses), but the pipeline now loads cnc-ddraw via
WINEDLLOVERRIDES=ddraw=n — and cnc-ddraw needs to see SetDisplayMode to size
its X11-backed surface. With the stub it kept the surface at a default smaller
size and the 640x480 framebuffer overflowed it.

Fix is at the root: drop the SDM-stub bytes from ra-ddscl-patch.py (keep the
DDSCL_NORMAL coop-level change), re-vendor the TIM-740 scanline_double patch
that was silently dropped when the local cnc-ddraw fork moved to a flake input,
and narrow each downstream patch's accepted-SHA set to a single canonical
chain anchored on the new .#ra-patched-exe output.

Also adds a primer (docs/wine-rendering-explainer.md) covering DirectDraw
concepts, Wine internals, cnc-ddraw, Xvfb, and every binary patch — aimed at
readers who haven't worked with 1996-era graphics code before.

Flagged but not changed: scripts/td/td-ddmode-patch.py has the same SDM-stub
pattern. TD pipeline also uses cnc-ddraw, so the stub is likely harmful there
too. Docstring updated with a TIM-1100 follow-up note; TD parity verification
needed before flipping.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hughobrien and others added 22 commits May 22, 2026 14:11
…ader.js

Item 1: Expose _saveToIDBFS() and _loadFromIDBFS() on Module for C++ EM_ASM
calls — force IDBFS sync after save / populate before load.

Item 2: Progress bar already wired via shell.html Module.setStatus and
monitorRunDependencies for WASM download; preloader.js setProgress() for
MIX loading. Both use same DOM elements — no changes needed.

Item 3: Add _validateGameData() on Module, called from mountAndLaunch()
after MIX files are mounted into MEMFS. Shows error overlay with list
of missing essential files when game data is invalid.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@hughobrien
hughobrien enabled auto-merge May 24, 2026 19:20
@hughobrien
hughobrien force-pushed the worktree-cleanup-parity-fixes branch from a380b3b to edb0722 Compare June 29, 2026 04:47
@hughobrien
hughobrien merged commit e52403d into main Jun 29, 2026
1 of 2 checks passed
@hughobrien
hughobrien deleted the worktree-cleanup-parity-fixes branch June 29, 2026 05:06
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