Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
6488c90
bugfix(asciistring): Fix thread unsafe reference counting of AsciiStr…
xezon Jul 31, 2025
7603545
- Use data dir for crash dumps instead of game dir (Fix for EA client…
x64-dev Aug 1, 2025
2612d13
Merge https://github.com/TheSuperHackers/GeneralsGameCode
x64-dev Aug 1, 2025
e89b48e
ci(build): Ensure runner uses windows-2022 image for build jobs (#1405)
tintinhamans Aug 2, 2025
e06f598
bugfix(gametext): Prevent crashing in WorldBuilder, MapCacheBuilder b…
xezon Aug 2, 2025
31f3a5c
fix(debug): Fix Release debug logging in tools (#1397)
xezon Aug 2, 2025
d042104
fix(cpudetect): Fix version and memory detection (#1393)
OmniBlade Aug 2, 2025
88b545e
bugfix(controls): Fix and improve next idle worker selection with con…
Stubbjax Aug 2, 2025
3b5d298
refactor(specialpower): Clean up ParticleUplinkCannonUpdate::initiate…
Caball009 Aug 2, 2025
4a9bc10
docs(file): Fix incorrect comment in File class flags (#1403)
xezon Aug 2, 2025
1d64feb
- 60hz fixes for nuke cannon and nuke missile
x64-dev Aug 3, 2025
9ff2a80
- Client now sets "client_id" as required by backend
x64-dev Aug 3, 2025
6ad992f
bugfix(controls): Fix double-press group selection logic not reselect…
Stubbjax Aug 3, 2025
3a58ec4
bugfix(object): Fix crash when an object is created with veterancy an…
Mauller Aug 3, 2025
9c27651
bugfix(cpudetect): Fix issues caused by broken memory benchmark value…
xezon Aug 3, 2025
f70794d
fix(contain): Fix compile errors with RETAIL_COMPATIBLE_CRC 0 (#1411)
xezon Aug 3, 2025
45a02a4
tweak(string): Implement functions in AsciiString, UnicodeString to r…
Mauller Aug 3, 2025
abd1b90
chore(script): Add script to help move files to Core (#1398)
xezon Aug 3, 2025
5efeb0e
unify(crc): Move CRC files to Core (#1387)
xezon Aug 3, 2025
3ac1832
feat(file): Implement functions in LocalFile for writing formatted st…
Mauller Aug 3, 2025
aaac77d
unify(common): Move RandomValue files to Core (#1388)
xezon Aug 3, 2025
8c52b6a
unify(debug): Merge GameEngine's Debug code (#1384)
xezon Jul 29, 2025
d2573a7
unify(debug): Move GameEngine's Debug files to Core (#1384)
xezon Jul 29, 2025
9f0a55e
feat(controlbar): Implement full viewport support for 'Control Bar Pr…
xezon Aug 3, 2025
dec4d7d
ci: Implement Replay Checker (#1366)
helmutbuhler Aug 4, 2025
3db9373
ci: Fix up Replay Checker (#1417)
helmutbuhler Aug 4, 2025
287a238
- Latest network tweaks from test branch
x64-dev Aug 4, 2025
9d6ebc7
reduce logging
x64-dev Aug 4, 2025
40afe82
unify(video): Merge Video code (#1410)
xezon Aug 2, 2025
f9913a5
unify(video): Move Video files to Core (#1410)
xezon Aug 2, 2025
b35dd54
docs: Introduce conventional commits to CONTRIBUTING.md (#1361)
xezon Jul 25, 2025
a410605
refactor(comments): Replace 'compile' with 'build' in project code co…
xezon Jul 25, 2025
e6e09e2
- Latest net tweaks from test build
x64-dev Aug 5, 2025
9a5b9ae
Added verbose logging flag
x64-dev Aug 5, 2025
31b9b92
- Increase libcurl header buffer size to match upcoming token changes
x64-dev Aug 5, 2025
9a6ff8a
- Latest networking tweaks from test env
x64-dev Aug 6, 2025
f3ba422
refactor(format): Remove trailing whitespace from game code files (#1…
xezon Aug 6, 2025
02fdf4f
feat(file): Implement character read and write functions for LocalFil…
Mauller Aug 7, 2025
9d58e4e
- Cleanup GS classes
x64-dev Aug 7, 2025
3bcb82e
Merge https://github.com/TheSuperHackers/GeneralsGameCode
x64-dev Aug 8, 2025
7e08cb0
Rls fix
x64-dev Aug 8, 2025
3b1236f
- Cleanup to network signalling
x64-dev Aug 8, 2025
e78948b
- Update color for self
x64-dev Aug 8, 2025
d497d2d
Disable VC6 again
x64-dev Aug 8, 2025
608eba6
More service migration work
x64-dev Aug 8, 2025
c705dbe
Merge branch 'main' of https://github.com/x64-dev/GeneralsGameCode_Ge…
x64-dev Aug 8, 2025
7bee1d1
Remove legacy packet encryption
x64-dev Aug 8, 2025
5fb71ef
- Per player chat color in lobby
x64-dev Aug 8, 2025
8082d34
- Improve handling for WS connections
x64-dev Aug 9, 2025
baa16af
build fix
x64-dev Aug 9, 2025
31e16de
Packet size fix
x64-dev Aug 9, 2025
6a80eec
- Fix shellmap freeze when failing to login
x64-dev Aug 11, 2025
a63e809
- Clientside login changes to match service side
x64-dev Aug 11, 2025
f416f2d
Safety
x64-dev Aug 12, 2025
c8c2de3
- Disabled host migration for now (needs backend tweaks)
x64-dev Aug 12, 2025
21a6911
- Safety & extra logging
x64-dev Aug 12, 2025
89a299a
- Extra safety for p2p signalling
x64-dev Aug 12, 2025
5897e10
restore debug functionality
x64-dev Aug 13, 2025
3511806
- updated API endpoints
x64-dev Aug 13, 2025
1be15fb
- Dont process WS disconnects while in game
x64-dev Aug 15, 2025
295e3ca
Cleanup & safety
x64-dev Aug 15, 2025
660ea14
- Stability and connection improvements
x64-dev Aug 17, 2025
ab3fd07
- Connectivity message now says which players arent connected
x64-dev Aug 17, 2025
bec3c3e
- Improve lobby handling of connection failures
x64-dev Aug 17, 2025
0fa9a69
- Rework network signalling implementation
x64-dev Aug 17, 2025
722cfca
Crash fixes
x64-dev Aug 17, 2025
de392f2
Kick check against lobby list
x64-dev Aug 17, 2025
0cc86f0
- Latest net changes from Mauller
x64-dev Aug 19, 2025
5dd8be9
Network slack tweaks from Mauller
x64-dev Aug 19, 2025
88d89c3
- Add support for retrying connection signalling
x64-dev Aug 19, 2025
f86fc22
Unused
x64-dev Aug 19, 2025
455f113
Initial connection registration
x64-dev Aug 19, 2025
7ccaa24
- Clientside changes to retrieve and utilize the service config
x64-dev Aug 20, 2025
7275a06
- Added flag for signal retries
x64-dev Aug 20, 2025
e79f2e9
Addn fixes for lobby join
x64-dev Aug 21, 2025
a00d9f0
Connection signal request is now single direction
x64-dev Aug 21, 2025
0126c1b
Fix retry signalling not working
x64-dev Aug 21, 2025
194e867
- quickstart in debug
x64-dev Aug 25, 2025
700a982
- Match latest lobby service changes
x64-dev Aug 26, 2025
940fa4a
revert define
x64-dev Aug 26, 2025
168deb6
Scrolling fix from Mauller
x64-dev Aug 27, 2025
108ba17
Fixes for host migration
x64-dev Aug 27, 2025
ddb2c4c
More fixes for host migration
x64-dev Aug 27, 2025
f499ee6
Chat color now matches lan behavior
x64-dev Aug 28, 2025
e80e9ae
Remove old player slots code
x64-dev Aug 28, 2025
7c5ed82
Add host migration flag to service config
x64-dev Aug 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
8 changes: 4 additions & 4 deletions .github/workflows/build-toolchain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ on:

jobs:
build:
name: Preset ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }}
runs-on: windows-latest
timeout-minutes: 40
name: ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }}
runs-on: windows-2022
timeout-minutes: 20
steps:
- name: Checkout Code
uses: actions/checkout@v4
Expand Down Expand Up @@ -66,7 +66,7 @@ jobs:
$fileHash = (Get-FileHash -Path VS6_VisualStudio6.7z -Algorithm SHA256).Hash
Write-Host "Downloaded file SHA256: $fileHash"
Write-Host "Expected file SHA256: $env:EXPECTED_HASH"
if ($hash -ne $env:EXPECTED_HASH) {
if ($fileHash -ne $env:EXPECTED_HASH) {
Write-Error "Hash verification failed! File may be corrupted or tampered with."
exit 1
}
Expand Down
242 changes: 242 additions & 0 deletions .github/workflows/check-replays.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
name: check-replays

permissions:
contents: read
pull-requests: write

on:
workflow_call:
inputs:
game:
required: true
type: string
description: "Game to check (only GeneralsMD for now)"
userdata:
required: true
type: string
description: "Path to folder with replays and maps"
preset:
required: true
type: string
description: "CMake preset"

jobs:
build:
name: ${{ inputs.preset }}
runs-on: windows-latest
timeout-minutes: 15
env:
GAME_PATH: C:\GameData
GENERALS_PATH: C:\GameData\Generals
GENERALSMD_PATH: C:\GameData\GeneralsMD
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
submodules: true

- name: Download Game Artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.game }}-${{ inputs.preset }}
path: build

- name: Cache Game Data
id: cache-gamedata
uses: actions/cache@v4
with:
path: ${{ env.GAME_PATH }}
key: gamedata-permanent-cache-v4

- name: Download Game Data from Cloudflare R2
if: ${{ steps.cache-gamedata.outputs.cache-hit != 'true' }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_ENDPOINT_URL: ${{ secrets.R2_ENDPOINT_URL }}
EXPECTED_HASH_GENERALS: "37A351AA430199D1F05DEB9E404857DCE7B461A6AC272C5D4A0B5652CDB06372"
EXPECTED_HASH_GENERALSMD: "6837FE1E3009A4C239406C39B1598216C0943EE8ED46BB10626767029AC05E21"
shell: pwsh
run: |
# Download trimmed gamedata of both Generals 1.08 and Generals Zero Hour 1.04.
# This data cannot be used for playing because it's
# missing textures, audio and gui files. But it's enough for replay checking.
# It's also encrypted because it's not allowed to distribute these files.

if (-not $env:AWS_ACCESS_KEY_ID -or -not $env:AWS_SECRET_ACCESS_KEY -or -not $env:AWS_ENDPOINT_URL) {
$ok1 = [bool]$env:AWS_ACCESS_KEY_ID
$ok2 = [bool]$env:AWS_SECRET_ACCESS_KEY
$ok3 = [bool]$env:AWS_ENDPOINT_URL
Write-Host "One or more required secrets are not set or are empty. R2_ACCESS_KEY_ID: $ok1, R2_SECRET_ACCESS_KEY: $ok2, R2_ENDPOINT_URL: $ok3"
exit 1
}

# Download Generals Game Files
# The archive contains these files:
# BINKW32.DLL
# English.big
# INI.big
# Maps.big
# mss32.dll
# W3D.big
# Data\Scripts\MultiplayerScripts.scb
# Data\Scripts\SkirmishScripts.scb

Write-Host "Downloading Game Data for Generals" -ForegroundColor Cyan
aws s3 cp s3://github-ci/generals108_gamedata_trimmed.7z generals108_gamedata_trimmed.7z --endpoint-url $env:AWS_ENDPOINT_URL

Write-Host "Verifying File Integrity" -ForegroundColor Cyan
$fileHash = (Get-FileHash -Path generals108_gamedata_trimmed.7z -Algorithm SHA256).Hash
Write-Host "Downloaded file SHA256: $fileHash"
Write-Host "Expected file SHA256: $env:EXPECTED_HASH_GENERALS"
if ($fileHash -ne $env:EXPECTED_HASH_GENERALS) {
Write-Error "Hash verification failed! File may be corrupted or tampered with."
exit 1
}

Write-Host "Extracting Archive" -ForegroundColor Cyan
$extractPath = $env:GENERALS_PATH
& 7z x generals108_gamedata_trimmed.7z -o"$extractPath"
Remove-Item generals108_gamedata_trimmed.7z -Verbose

# Download GeneralsMD (ZH) Game Files
# The archive contains these files:
# BINKW32.DLL
# INIZH.big
# MapsZH.big
# mss32.dll
# W3DZH.big
# Data\Scripts\MultiplayerScripts.scb
# Data\Scripts\Scripts.ini
# Data\Scripts\SkirmishScripts.scb

Write-Host "Downloading Game Data for GeneralsMD" -ForegroundColor Cyan
aws s3 cp s3://github-ci/zerohour104_gamedata_trimmed.7z zerohour104_gamedata_trimmed.7z --endpoint-url $env:AWS_ENDPOINT_URL

Write-Host "Verifying File Integrity" -ForegroundColor Cyan
$fileHash = (Get-FileHash -Path zerohour104_gamedata_trimmed.7z -Algorithm SHA256).Hash
Write-Host "Downloaded file SHA256: $fileHash"
Write-Host "Expected file SHA256: $env:EXPECTED_HASH_GENERALSMD"
if ($fileHash -ne $env:EXPECTED_HASH_GENERALSMD) {
Write-Error "Hash verification failed! File may be corrupted or tampered with."
exit 1
}

Write-Host "Extracting Archive" -ForegroundColor Cyan
$extractPath = $env:GENERALSMD_PATH
& 7z x zerohour104_gamedata_trimmed.7z -o"$extractPath"
Remove-Item zerohour104_gamedata_trimmed.7z -Verbose

- name: Set Up Game Data
shell: pwsh
run: |
$source = "$env:GAME_PATH\${{ inputs.game }}"
$destination = "build"
Copy-Item -Path $source\* -Destination $destination -Recurse -Force

- name: Set Generals InstallPath in Registry
shell: pwsh
run: |
# Zero Hour loads some Generals files and needs this registry key to find the
# Generals data files.

$regPath = "HKCU:\SOFTWARE\Electronic Arts\EA Games\Generals"
$installPath = "$env:GENERALS_PATH\"

# Ensure the key exists
if (-not (Test-Path $regPath)) {
New-Item -Path $regPath -Force | Out-Null
}

# Set the InstallPath value
Set-ItemProperty -Path $regPath -Name InstallPath -Value $installPath -Type String
Write-Host "Registry key set: $regPath -> InstallPath = $installPath"

- name: Move Replays and Maps to User Dir
shell: pwsh
run: |
# These files are expected in the user dir, so we move them here.

$source = "${{ inputs.userdata }}\Replays"
$destination = "$env:USERPROFILE\Documents\Command and Conquer Generals Zero Hour Data\Replays"
Write-Host "Move replays to $destination"
New-Item -ItemType Directory -Path $destination -Force | Out-Null
Move-Item -Path "$source\*" -Destination $destination -Force

$source = "${{ inputs.userdata }}\Maps"
$destination = "$env:USERPROFILE\Documents\Command and Conquer Generals Zero Hour Data\Maps"
Write-Host "Move maps to $destination"
New-Item -ItemType Directory -Path $destination -Force | Out-Null
Move-Item -Path "$source\*" -Destination $destination -Force

- name: Run Replay Compatibility Tests
shell: pwsh
run: |
$exePath = "build/generalszh.exe"
$arguments = "-jobs 4 -headless -replay *.rep"
$timeoutSeconds = 10*60
$stdoutPath = "stdout.log"
$stderrPath = "stderr.log"

if (-not (Test-Path $exePath)) {
Write-Host "ERROR: Executable not found at $exePath"
exit 1
}

# Note that the game is a gui application. That means we need to redirect console output to a file
# in order to retrieve it.
# Clean previous logs
Remove-Item $stdoutPath, $stderrPath -ErrorAction SilentlyContinue

# Start the process
Write-Host "Run $exePath $arguments"
$process = Start-Process -FilePath $exePath `
-ArgumentList $arguments `
-RedirectStandardOutput $stdoutPath `
-RedirectStandardError $stderrPath `
-PassThru

# Wait with timeout
$exited = $process.WaitForExit($timeoutSeconds * 1000)

if (-not $exited) {
Write-Host "ERROR: Process still running after $timeoutSeconds seconds. Killing process..."
Stop-Process -Id $process.Id -Force
}

# Read output
Write-Host "=== STDOUT ==="
Get-Content $stdoutPath

if ((Test-Path $stderrPath) -and (Get-Item $stderrPath).Length -gt 0) {
Write-Host "`n=== STDERR ==="
Get-Content $stderrPath
}

if (-not $exited) {
exit 1
}

# Check exit code
$exitCode = $process.ExitCode

# The above doesn't work on all Windows versions. If not, try this: (see https://stackoverflow.com/a/16018287)
#$process.HasExited | Out-Null # Needs to be called for the command below to work correctly
#$exitCode = $process.GetType().GetField('exitCode', 'NonPublic, Instance').GetValue($process)
#Write-Host "exit code $exitCode"

if ($exitCode -ne 0) {
Write-Host "ERROR: Process failed with exit code $exitCode"
exit $exitCode
}

Write-Host "Success!"

- name: Upload Debug Log
if: always()
uses: actions/upload-artifact@v4
with:
name: Replay-Debug-Log-${{ inputs.preset }}
path: build/DebugLogFile*.txt
retention-days: 30
if-no-files-found: ignore
55 changes: 46 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ jobs:
generalsmd:
- 'GeneralsMD/**'
shared:
- '.github/workflows/build-toolchain.yml'
- '.github/workflows/ci.yml'
- '.github/workflows/**'
- 'CMakeLists.txt'
- 'CMakePresets.json'
- 'cmake/**'
Expand Down Expand Up @@ -100,13 +99,15 @@ jobs:
# extras: ${{ matrix.extras }}
# secrets: inherit

build-generalsmd:
name: Build GeneralsMD${{ matrix.preset && '' }}
needs: detect-changes
if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }}
strategy:
matrix:
include:
# Note build-generalsmd is split into two jobs for vc6 and win32 because replaycheck-generalsmd
# only requires the vc6 build and compiling vc6 is much faster than win32
#build-generalsmd-vc6:
#name: Build GeneralsMD${{ matrix.preset && '' }}
#needs: detect-changes
#if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }}
#strategy:
#matrix:
#include:
# - preset: "vc6"
# tools: true
# extras: true
Expand All @@ -116,6 +117,25 @@ jobs:
# - preset: "vc6-debug"
# tools: true
# extras: true
#- preset: "vc6-releaselog"
#tools: true
#extras: true
#fail-fast: false
#uses: ./.github/workflows/build-toolchain.yml
#with:
#game: "GeneralsMD"
#preset: ${{ matrix.preset }}
#tools: ${{ matrix.tools }}
#extras: ${{ matrix.extras }}
#secrets: inherit

build-generalsmd-win32:
name: Build GeneralsMD${{ matrix.preset && '' }}
needs: detect-changes
if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }}
strategy:
matrix:
include:
- preset: "win32"
tools: false
extras: true
Expand Down Expand Up @@ -143,3 +163,20 @@ jobs:
tools: ${{ matrix.tools }}
extras: ${{ matrix.extras }}
secrets: inherit

#replaycheck-generalsmd:
#name: Replay Check GeneralsMD${{ matrix.preset && '' }}
#needs: build-generalsmd-vc6
#if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }}
#strategy:
#matrix:
#include:
#- preset: "vc6+t+e"
#- preset: "vc6-releaselog+t+e" # optimized build with logging and crashing enabled should be compatible, so we test that here.
#fail-fast: false
#uses: ./.github/workflows/check-replays.yml
#with:
#game: "GeneralsMD"
#userdata: "GeneralsReplays/GeneralsZH/1.04"
#preset: ${{ matrix.preset }}
#secrets: inherit
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
!.gitignore
!.gitattributes
!.github
!.gitmodules

*.user
*.ncb
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "GeneralsReplays"]
path = GeneralsReplays
url = https://github.com/TheSuperHackers/GeneralsReplays
Loading
Loading