<# build-resources.ps1 - (re)pack the runtime resource packages (resource\*.mw4) from the Content\ source tree, using the in-exe resource compiler. The resource compiler lives INSIDE the game executable and only runs in a LAB_ONLY config (Debug/Armor/Profile) when launched with -build. We use the Profile exe (MW4pro.exe); Release MW4.exe silently ignores -build. See build-env\RESOURCE-BUILD.md for the full writeup. What it does: 1. Overlays the freshly built MW4pro.exe (+ companion DLLs) into the source tree so the build uses CURRENT binaries -> the .mw4 files carry the matching VER_CONTENTVERSION that our freshly built game/editor expect. 2. Runs MW4pro.exe -armorlevel 3 -build -norun -window -nosound -nocd -noeula with the working directory set to the source tree (which holds Content\MechWarrior4.build and where resource\*.mw4 are written). 3. The build is INCREMENTAL (.dep timestamps + content version): only packages whose source changed are rebuilt, so re-runs are fast. A package's whole source set must be present, or the LAB_ONLY exe pops a modal STOP -- the -Timeout guard below kills a hung build and reports it rather than blocking the deploy forever. NOTE: this writes into $Runtime\resource (the canonical dev resources). That is intentional: it keeps the dev tree's compiled packages current, and the editor (which junctions this tree) picks them up automatically. #> param( [string]$Runtime = "c:\VWE\firestorm\Gameleap\mw4", # source tree: Content\ + resource\ [string]$BinDir = "c:\VWE\firestorm\Gameleap\code\rel.bin", # our freshly built MW4pro.exe [int] $TimeoutSec = 1800 # kill a hung (modal-STOP) build ) $ErrorActionPreference = "Stop" Write-Host "== Packing resources (resource\*.mw4) ==" -ForegroundColor Cyan Write-Host " source : $Runtime" Write-Host " builder: $BinDir\MW4pro.exe (Profile / LAB_ONLY)`n" $proExe = Join-Path $BinDir "MW4pro.exe" if (-not (Test-Path $proExe)) { throw "MW4pro.exe not found in $BinDir. Build 'MW4Application - Win32 Profile' first (Release MW4.exe cannot -build)." } $master = Join-Path $Runtime "Content\MechWarrior4.build" if (-not (Test-Path $master)) { throw "Master manifest not found: $master (the full Content\ source tree must be present to pack resources)." } # 1) Overlay the fresh LAB_ONLY builder + companion DLLs so the build's content version matches # the binaries we deploy. (Static libs are linked into the exe; the few runtime DLLs we build # are copied too for consistency.) Write-Host "[pack 1/3] staging fresh builder into source tree ..." -ForegroundColor Yellow foreach ($a in "MW4pro.exe","ctcls.dll","MissionLang.dll","ScriptStrings.dll") { $s = Join-Path $BinDir $a if (Test-Path $s) { Copy-Item $s (Join-Path $Runtime $a) -Force; Write-Host " + $a" } } # 2) DirectDraw 16-bit compat shim for the builder exe path (GameOS still inits even with -norun). $builder = Join-Path $Runtime "MW4pro.exe" $layers = "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" if (-not (Test-Path $layers)) { New-Item -Path $layers -Force | Out-Null } Set-ItemProperty -Path $layers -Name $builder -Value "DWM8And16BitMitigation HIGHDPIAWARE" -Type String # Snapshot resource\ mtimes so we can report what got rebuilt. $resDir = Join-Path $Runtime "resource" $before = @{} if (Test-Path $resDir) { Get-ChildItem $resDir -Recurse -Filter *.mw4 -EA SilentlyContinue | ForEach-Object { $before[$_.FullName] = $_.LastWriteTimeUtc } } $startUtc = (Get-Date).ToUniversalTime() # 3) Run the in-exe resource compiler (build-and-exit), guarded by a timeout. # - FULLSCREEN (no -window): the windowed DirectDraw/D3D7 path fails on Win11 (the editor's # "No 3D acceleration"/"No software rasterizer" problem). The fullscreen-exclusive path # works (it's how the game runs) and the DWM shim applied above covers it. # - /gosnodialogs: makes graphics warnings auto-continue and turns a fatal content STOP into # a clean process EXIT (caught via exit code below) instead of an unattended modal hang. # (CheckOption strips the token, so it does NOT trip the LAB_ONLY "/gos" help-and-exit trap.) Write-Host "[pack 2/3] running resource compiler (this can take a while) ..." -ForegroundColor Yellow # Always run the builder windowed (-window). DDrawCompat's ddraw.dll handles windowed DDraw # on Win10/11 and VMs with generic adapters. Fullscreen requires the DWM16-bit shim which # is unreliable on some machine configs. The builder only needs DDraw to init -- it never # renders a frame with -norun, so windowed mode is always safe. # dgVoodoo2 D3D interceptors (D3D8/D3D9/D3DImm.dll) must not be present during the build; # move them aside if present (defensive -- they should not be in the repo). $dgvDlls = @("D3D8.dll","D3D9.dll","D3DImm.dll") | Where-Object { Test-Path (Join-Path $Runtime $_) } $dgvMoved = @() foreach ($d in $dgvDlls) { $src = Join-Path $Runtime $d; $bak = "$src.buildaside" Move-Item $src $bak -Force; $dgvMoved += $bak Write-Host " (moved $d aside -- dgVoodoo2 interceptors break the builder)" } $code = $null try { $argList = "/gosnodialogs -armorlevel 3 -build -norun -nosound -nocd -noeula -window" $p = Start-Process -FilePath $builder -ArgumentList $argList -WorkingDirectory $Runtime -PassThru $timedOut = $false try { Wait-Process -Id $p.Id -Timeout $TimeoutSec -ErrorAction Stop } catch { $timedOut = $true } if ($timedOut) { try { Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue } catch {} throw ("Resource build did not finish within $TimeoutSec s. The LAB_ONLY exe most likely hit a " + "modal content STOP (a missing/inconsistent source asset in the WIP Content\ tree). " + "Run the builder interactively to see which asset, fix the content, then re-deploy:`n" + " cd `"$Runtime`"; .\MW4pro.exe -armorlevel 3 -build -norun -window -nosound -nocd -noeula") } $p.Refresh() $code = $p.ExitCode if ($code -ne 0) { $log = Join-Path $Runtime "debuglog.txt" $tail = if (Test-Path $log) { (Get-Content $log -Tail 25 -EA SilentlyContinue) -join "`n" } else { "(no debuglog.txt)" } throw ("Resource build exited with code $code -- likely a fatal content STOP on a missing/" + "inconsistent source asset in the WIP Content\ tree (/gosnodialogs turns STOPs into a " + "clean exit). Deploy aborted so partial packages are NOT shipped. Last debuglog.txt:`n" + "$tail`n`nFix the asset and re-run, or run deploy-mw4.ps1 -SkipResourceBuild to ship existing packages.") } } finally { foreach ($bak in $dgvMoved) { $orig = $bak -replace '\.buildaside$','' if (Test-Path $bak) { Move-Item $bak $orig -Force } } } # 4) Report what changed. Write-Host "[pack 3/3] resource build complete (exit $code)." -ForegroundColor Yellow $changed = @() if (Test-Path $resDir) { Get-ChildItem $resDir -Recurse -Filter *.mw4 -EA SilentlyContinue | ForEach-Object { if (-not $before.ContainsKey($_.FullName) -or $_.LastWriteTimeUtc -gt $startUtc) { $changed += $_.FullName.Substring($Runtime.Length).TrimStart('\') } } } if ($changed.Count) { Write-Host (" rebuilt {0} package(s):" -f $changed.Count) -ForegroundColor Green $changed | Sort-Object | ForEach-Object { " $_" } } else { Write-Host " all packages already up to date (nothing rebuilt)." -ForegroundColor Green }