抹桥的博客
Language
Theme Color
250

Troubleshooting XCOM: Enemy Within Freezing Two Minutes After Launch

Outline

I only meant to launch XCOM: Enemy Within and play for a bit, but after reaching the main menu, the game froze about two minutes later. After restarting, I could sometimes navigate the menu for a little while before it stopped responding again.

When launching the game, Steam also shows a selector where I can choose Enemy Unknown or Enemy Within. Unknown had startup problems of its own, so I focused on Within first—at least to get the version I wanted to play running.

I did manage to fix the startup freeze, though the process was more involved than I expected. I initially suspected compatibility issues between an old game, a new system, and 4K resolution. In the end, the clue turned out to be an old request to a Firaxis online service. I’m documenting the troubleshooting process and manual steps here so I won’t have to start from scratch the next time I switch computers.

A Few Standard Fixes to Try First

To make testing easier, I had Codex back up the configuration files, saves, and logs, then changed one condition at a time to see how long the game would run. When troubleshooting an old game on Windows, the first things that come to mind are naturally resolution, windowed mode, and overlays.

So I tried a few things:

AttemptResult
Changed bShouldUseMcp to falseDid not reliably prevent the relevant requests; the game still froze
Switched from 4K borderless to 1280×720 windowed modeChanged initial resource usage, but the freeze still occurred
Adjusted Steam and NVIDIA overlaysDid not stop memory usage from continuing to grow; some toggles also did not actually prevent DLL injection
Used DXVK 3.1.1No effect
Changed the online subsystem, switched to English, limited the number of CPU cores, and disabled voice chatNone of these fixed the problem
Added -ONETHREADFailed even sooner
Exited Steam completelyThe game exited after about 40 seconds and could not be used normally

At one point, it looked as though the problem was fixed: I bypassed the selector, set the correct Steam environment variables, and launched Within directly. The main menu was responsive, so I assumed the issue was just the launch method.

But after waiting a little longer, it froze again.

That was the easiest point in the troubleshooting process to misread. Launching the game and being able to play continuously are two different things, especially when the problem doesn’t appear immediately. After that, I stopped looking only at whether the process was still running and started tracking whether the window responded, whether memory usage was increasing, and how CPU time changed.

A Strange Network Request

While checking the logs and network connections, I found that the game was accessing this address:

prod.xcom-ew.firaxis.com

In my environment at the time, it resolved to 192.81.242.201, and the game connected to port 80. When the game froze, it also left behind two CLOSE_WAIT connections.

CLOSE_WAIT means the remote end has closed the connection, but the local program has not finished closing it. That state alone doesn’t tell us much; normal programs can show it briefly, too. But combined with the game being unresponsive and memory usage continuing to rise, it looked suspicious.

So I captured a thread dump while the game was frozen and examined it with the Windows debugger. Thread 19520 used about 51 seconds of CPU over roughly 75 seconds. The relevant part of its call stack was:

ntdll!NtDeviceIoControlFile
mswsock!WSPRecv
ws2_32!WSARecv
wsock32!recv
XComEW+0x2604b5

It was on the network receive path, and the recv call’s length parameter was 1, meaning it was reading one byte at a time.

A single call stack snapshot can’t reconstruct the game’s source code, of course. But a hot thread continuously consuming CPU, an unresponsive window, and steadily increasing memory usage together looked a lot like the client was stuck in abnormal repeated reads while handling a request to this old service.

A later test using a domain substitution also supported this theory.

Why It Eventually Reported Out of Memory

When the original program failed, it displayed this message:

Ran out of virtual memory

The dump then recorded a 0xc0000005 access violation at offset XComEW.exe+0x00e77ce1.

The virtual memory here needs to be considered in the context of the game being a 32-bit program. A process has a limit on the virtual address space it can use. If it keeps allocating memory, it can run out of address space even when the machine still has physical memory and disk space available.

So the sequence I observed was: the game froze, memory usage continued to rise, an allocation failed, and then a subsequent crash occurred. Lowering the resolution can reduce some of the initial memory usage, but it doesn’t stop the abnormal reads, so it doesn’t solve the problem.

Changing Just One Domain

The fix that worked was to create a copy of the original executable called XComEW-Offline.exe and replace just one string in it:

prod.xcom-ew.firaxis.com
             ↓
off.xcom-ew.invalid.test

Both addresses are 23 characters long, and each encodes to 46 bytes in UTF-16LE. Because the replacement is the same length, there’s no need to shift any of the data that follows it in the executable.

The new address uses the reserved .test domain. In my network environment, it did not resolve to a reachable service, so the game no longer followed the original request path. This does not prove that Firaxis’s servers are permanently offline. What I can say is that the old service request was triggering abnormal client behavior at the time, and the startup freeze did not recur after bypassing it.

The original XComEW.exe was left untouched, and I made no permanent changes to Hosts, save files, or resolution settings. Offline is just the name of the copy; the game still requires Steam. This change blocks online features provided through the replaced domain, and I have not tested multiplayer.

I later added a desktop shortcut that ensures Steam is running, sets the environment variables, and launches this copy directly. That way, I don’t have to go through the Unknown / Within selector every time.

What Was Actually Tested

After applying the fix, I ran two observation tests:

TestObservation
Ran the fixed version for about 12 minutes after startupAll 72 samples showed the game responding; private memory was about 966 MB after loading and about 918 MB at the end, with no continued linear increase
Restarted from the desktop shortcut and observed for 152 secondsAll 15 samples showed the game responding; private memory fell from about 802 MB to about 738 MB, and no connection to the old service IP was detected

There’s one more detail worth recording: the 12-minute test summary showed a dump file. After checking the logs, I found that it had been triggered by an exception from 0x406D1388 about 5 seconds after startup. This code is commonly used to name threads in a traditional debugger. The game then continued running until the end of the test, so the presence of a dump does not necessarily mean it crashed again.

ProcDump also exited after reaching its one-dump limit. The subsequent evidence came from process and resource sampling, so I can’t claim that it monitored every exception throughout the test.

At this point, the startup freeze that had been recurring was gone during the observation period. However, the verification mainly covered startup and the main menu; I have not played through a full campaign, tested every mission, or checked online features. The Enemy Unknown issue was also not resolved as part of this troubleshooting.

Manual Steps

The sections above describe the troubleshooting process. Here are the steps that actually need to be performed, collected for future reference and for anyone experiencing the same problem.

Find the Enemy Within Executable

First, exit the game. In your Steam library, right-click the game and select “Manage → Browse local files” to open:

XEW\Binaries\Win32

You should find XComEW.exe there. Make sure this is the Within executable; the steps below do not apply to Unknown.

Back up your saves and keep Steam running. Then open PowerShell and change $gameDirectory below to the actual installation path on your system.

Create a Fixed Copy

The SHA-256 hash of the original executable I verified is:

F8D90411AFA46EBB56E65BBFD71098FEE335549768DB7A3FFDAE5E1DE9CDCB7F

The file is 27,793,464 bytes, and the replacement starts at byte offset 23899942, counting from 0. The code below only works with this version. It will stop if the hash does not match. For other versions, you’ll need to locate the string again. Don’t remove the check and run it anyway.

Paste the entire block into PowerShell and run it. If you don’t have write access to the installation directory, use PowerShell with the necessary permissions.

$ErrorActionPreference = 'Stop'
$gameDirectory = 'D:\SteamLibrary\steamapps\common\XCom-Enemy-Unknown\XEW\Binaries\Win32'
$sourcePath = Join-Path $gameDirectory 'XComEW.exe'
$targetPath = Join-Path $gameDirectory 'XComEW-Offline.exe'
$expectedSourceHash = 'F8D90411AFA46EBB56E65BBFD71098FEE335549768DB7A3FFDAE5E1DE9CDCB7F'
$expectedTargetHash = '74648BF164D249D3E8211F2411681C01B8EDA8148AF978AA86E6B37F5C2B64C9'
$patchOffset = 23899942
$originalBytes = [Text.Encoding]::Unicode.GetBytes('prod.xcom-ew.firaxis.com')
$replacementBytes = [Text.Encoding]::Unicode.GetBytes('off.xcom-ew.invalid.test')

$sourceHash = (Get-FileHash -LiteralPath $sourcePath -Algorithm SHA256).Hash
if ($sourceHash -ne $expectedSourceHash) {
    throw 'Original executable version does not match. Stop and inspect this version separately.'
}
if (Test-Path -LiteralPath $targetPath) {
    throw 'XComEW-Offline.exe already exists. Verify it or back it up before creating another copy.'
}

$bytes = [IO.File]::ReadAllBytes($sourcePath)
if ($bytes.Length -ne 27793464 -or $originalBytes.Length -ne $replacementBytes.Length) {
    throw 'Executable size or replacement length does not match.'
}
for ($byteIndex = 0; $byteIndex -lt $originalBytes.Length; $byteIndex++) {
    if ($bytes[$patchOffset + $byteIndex] -ne $originalBytes[$byteIndex]) {
        throw 'Original hostname was not found at the verified offset.'
    }
}

[Array]::Copy($replacementBytes, 0, $bytes, $patchOffset, $replacementBytes.Length)
$hasher = [Security.Cryptography.SHA256]::Create()
try {
    $patchedHash = [BitConverter]::ToString($hasher.ComputeHash($bytes)).Replace('-', '')
} finally {
    $hasher.Dispose()
}
if ($patchedHash -ne $expectedTargetHash) {
    throw 'Patched data did not match the verified result.'
}

$outputStream = [IO.File]::Open($targetPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write)
try {
    $outputStream.Write($bytes, 0, $bytes.Length)
} finally {
    $outputStream.Dispose()
}
if ((Get-FileHash -LiteralPath $targetPath -Algorithm SHA256).Hash -ne $expectedTargetHash) {
    throw 'Written copy verification failed. Do not launch this copy.'
}
if ((Get-FileHash -LiteralPath $sourcePath -Algorithm SHA256).Hash -ne $sourceHash) {
    throw 'Original executable hash changed. Inspect the original before continuing.'
}
Get-FileHash -LiteralPath $sourcePath, $targetPath -Algorithm SHA256

Afterward, the copy should have this SHA-256 hash:

74648BF164D249D3E8211F2411681C01B8EDA8148AF978AA86E6B37F5C2B64C9

If the copy already exists, use the last line of the code to verify its hash. If it matches, there’s no need to generate it again. The original file is always kept, making it easy to roll back later.

Try Launching It Once

Continue in the same PowerShell window by running:

$env:SteamAppId = '200510'
$env:SteamGameId = '200510'
Start-Process -FilePath (Join-Path $gameDirectory 'XComEW-Offline.exe') -ArgumentList '-FROMLAUNCHER', '-LANGUAGE=CHT' -WorkingDirectory $gameDirectory

-LANGUAGE=CHT selects Traditional Chinese, which I used for this test. For English, change it to -LANGUAGE=INT. The Steam environment variables and working directory are also part of the launch method, so double-clicking the EXE may not produce the same result.

Once you reach the menu, wait at least 10–15 minutes, then try navigating the menus, loading a save, and starting a mission. These are additional gameplay checks you’ll need to do yourself; the tests recorded above did not cover a full campaign.

Create a Desktop Shortcut

Exit the game you just launched, then run the following in the same PowerShell window. Reuse the $gameDirectory variable from earlier, and change $steamPath to match your Steam installation location.

$steamPath = 'C:\Program Files (x86)\Steam\steam.exe'
$gamePath = Join-Path $gameDirectory 'XComEW-Offline.exe'
$desktopPath = [Environment]::GetFolderPath('Desktop')
$shortcutPath = Join-Path $desktopPath 'XCOM Enemy Within 修复版.lnk'
if (-not (Test-Path -LiteralPath $steamPath)) { throw 'Steam executable was not found.' }
if (-not (Test-Path -LiteralPath $gamePath)) { throw 'Patched game executable was not found.' }
if (Test-Path -LiteralPath $shortcutPath) { throw 'Shortcut already exists. Use a different name.' }

$quotedSteam = $steamPath.Replace("'", "''")
$quotedGame = $gamePath.Replace("'", "''")
$quotedDirectory = $gameDirectory.Replace("'", "''")
$launchCommand = "if (-not (Get-Process -Name steam -ErrorAction SilentlyContinue)) { Start-Process -FilePath '$quotedSteam'; Start-Sleep -Seconds 12 }; "
$launchCommand += "`$env:SteamAppId='200510'; `$env:SteamGameId='200510'; "
$launchCommand += "Start-Process -FilePath '$quotedGame' -ArgumentList '-FROMLAUNCHER','-LANGUAGE=CHT' -WorkingDirectory '$quotedDirectory'"
$encodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($launchCommand))
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($shortcutPath)
$shortcut.TargetPath = Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\powershell.exe'
$shortcut.Arguments = "-NoProfile -NonInteractive -WindowStyle Hidden -EncodedCommand $encodedCommand"
$shortcut.WorkingDirectory = $gameDirectory
$shortcut.IconLocation = "$gamePath,0"
$shortcut.WindowStyle = 7
$shortcut.Description = 'XCOM Enemy Within: bypass the legacy Firaxis service request'
$shortcut.Save()
Get-Item -LiteralPath $shortcutPath

Use this shortcut to launch the game from now on. It first makes sure Steam is running, then launches the fixed copy, bypassing the version selector. Launching the original executable from the Steam library may still trigger the same problem.

If you’ve just signed in to Steam, it’s updating, or it’s taking a while to start, wait until it’s fully ready before using the shortcut. The 12-second delay here is just a startup wait; it does not guarantee that Steam will be ready that quickly on every machine.

Check Whether It Worked and How to Roll Back

While the game is running, open another PowerShell window and check:

Get-Process -Name XComEW-Offline | Select-Object Id, Responding, @{Name='PrivateMB'; Expression={[math]::Round($_.PrivateMemorySize64 / 1MB, 1)}}
$gameProcess = Get-Process -Name XComEW-Offline | Select-Object -First 1
Get-NetTCPConnection -OwningProcess $gameProcess.Id -ErrorAction SilentlyContinue | Where-Object RemoteAddress -eq '192.81.242.201'

After the initial loading, memory usage should no longer keep increasing in one direction. The second check did not return a connection to the old service in my test. However, responsiveness and the absence of that connection are only supporting indicators; actually using the game is the final test.

The logs are usually under My Games\XCOM - Enemy Within\XComGame\Logs\Launch.log in your Windows Documents folder. If you have OneDrive folder redirection enabled for Documents, the actual path may be inside OneDrive. The log should show a DNS query for the replacement domain.

To restore the original, exit the game, delete the copy and shortcut you created, and launch it from Steam. After a Steam update, verify the original executable’s hash again; an old copy may not work with the other game files after they’ve been updated.

Final Thoughts

It’s a little frustrating to end up debugging for half the day when I just wanted to play for a while. But at least this time I didn’t stop at “restarting seemed to fix it.” I captured the network receive path and memory growth, then verified the theory with a small change.

For problems that appear after a delay, the main thing to remember is to wait a little longer. Reaching the main menu only means that you reached the main menu. The next time something similar happens, recording responsiveness, CPU, and memory before and after the failure should help avoid a few wrong turns.

Troubleshooting XCOM: Enemy Within Freezing Two Minutes After Launch
https://blog.kisnows.com/en-US/2026/09/27/xcom-enemy-within-startup-freeze/
Author
Kisnows
Published at
2026-09-27