Releases: dvcdsys/GeneralsGameCode-macOS
Release list
GeneralsZH Launcher — macOS (Apple Silicon) launcher-v0.1.7
GeneralsZH Launcher (macOS/arm64) — WASD camera controls toggle
Added
- "WASD camera controls" checkbox on the Play tab (persisted, default off).
SetsGEN_WASD_CAMERAfor the engine so W/A/S/D pan the camera in addition to
the arrow keys. The tooltip documents the ⌘ remap of the commands those keys
normally do: ⌘W = select all aircraft, ⌘S = stop, ⌘A = attack-move,
⌘D = build dozer. Nothing is lost from the keyboard.
Needs engine-v0.1.13 or newer (the engine side of the feature). Commit: 8fedb16
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.13
Zero Hour engine (macOS/arm64) — WASD camera controls + macOS Command key-up fix
Added
- WASD camera panning (opt-in). With the launcher's new "WASD camera controls"
toggle (orGEN_WASD_CAMERA=1), W/A/S/D pan the battlefield camera just like the
arrow keys — and the arrow keys keep working. Off by default, so the standard build
is unchanged. The commands those keys normally trigger are not lost: they
relocate to ⌘ (Command) + the same key. The relocation is data-agnostic — it
moves whatever a given install binds to W/A/S/D — so it works on vanilla Zero Hour
and on total-conversion mods (e.g. Cold War Crisis) alike.
Fixed
- W/S ran unit commands instead of panning. Symptom: with WASD mode on, A/D panned
but W and S fired "select all aircraft" / "stop" and never moved the camera. Cause:
the real key bindings live in the localizedData\English\CommandMap.ini(not
the empty genericData\INI\CommandMap.ini), where W = SelectAllAircraft and
S = Stop are meta-commands that the meta translator consumed before the camera
ever saw the key. Fix: in WASD mode the camera owns bare W/A/S/D; the meta translator
passes them through to pan and relocates ⌘W / ⌘S to those commands. - Camera stuck scrolling after ⌘W/⌘S; ⌘A/⌘D never fired. Symptom: ⌘W/⌘S ran their
command but the camera then scrolled up/down endlessly, and ⌘A/⌘D did nothing. Cause:
a macOS input quirk — the OS does not deliver key-up events for a key released
while Command is held, so the engine thought the key was stuck down (endless
auto-repeat) and the command-bar hotkeys (which fire on key-up) never triggered. Fix:
the Metal input layer now synthesizes an immediate key-up for any ⌘+key press (a
Cmd+key can't be held-repeated on macOS anyway). General input fix, not WASD-specific.
Changed
- New env switch
GEN_WASD_CAMERA=1(set by the launcher toggle); unset = original
arrow-only behaviour, byte-for-byte. No graphics or effects changed.
Requires launcher-v0.1.7 for the checkbox. Commit: 8fedb16
GeneralsZH Launcher — macOS (Apple Silicon) launcher-v0.1.6
Native macOS arm64 launcher for Command & Conquer: Generals — Zero Hour.
Fixed
- Always pass an absolute
GEN_USER_DATAto the engine. A relative or empty user-data
path made the engine scatter saves / replays / map-previews into the game folder
instead of~/Documents/…("not from root"). The launcher now resolves the user-data path
to an absolute path (falling back to the~/Documentsdefault) before launching and before
creating theMaps/andSave/subfolders.- Pairs with the engine guard in engine-v0.1.12 (rejects a relative
GEN_USER_DATA).
- Pairs with the engine guard in engine-v0.1.12 (rejects a relative
Install
- Download GeneralsZH-Launcher.dmg, open it, and drag GeneralsZH Launcher.app onto
the Applications folder. - The app is ad-hoc signed (not notarized), so clear the quarantine flag once in Terminal:
xattr -dr com.apple.quarantine "/Applications/GeneralsZH Launcher.app" - Pick the folder with your original Zero Hour data (
.bigfiles) and press Play. The
engine is downloaded automatically from the latestengine-v*release.
Apple Silicon (M-series) only. Checksums in SHA256SUMS.
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.12
Native macOS arm64 build of the Command & Conquer: Generals — Zero Hour engine.
Fixed
- User-data "not from root". A relative
GEN_USER_DATAmade the engine create the
entire user-data tree —Replays/,Save/,MapPreviews/and the root folder —
relative to the game's working directory, i.e. inside the game folder instead of at
~/Documents/….BuildUserDataPathFromRegistryused the env value verbatim, and every
consumer (getReplayDir, save games, theMAP_PREVIEW_DIR_PATHcache, the root
CreateDirectory) prefixesgetPath_UserData(), so one relative value scattered everything.- Fix: honour
GEN_USER_DATAonly when it is an absolute path (leading/);
otherwise ignore it and fall through to the computed~/Documents/<leaf>/path. Windows
path unchanged. - Pairs with the launcher-side guard in launcher-v0.1.6 (always passes an absolute path).
- Fix: honour
The GeneralsZH Launcher downloads this engine automatically. You must own a legitimate
copy of Zero Hour — EA game data is not included.
Apple Silicon (M-series) only. Checksums in SHA256SUMS.
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.11
Native macOS arm64 build of the Command & Conquer: Generals — Zero Hour engine.
Fixed
- Debug logs silently broken on macOS (
\path-separator bug).LogClass/
StatDumpClassbuilt their log-file path with the Windows-only idiom
GetModuleFileName+strrchr(buffer, '\\')+"\\"+fname. On macOS the
GetModuleFileNameshim returns a POSIX path with/separators, so the
backslash search never matched — the exe name was never stripped and the path
resolved inside the binary file (.../generalszh/Perf.txt, wheregeneralszh
is a regular file), sofopen("wt")failed silently.- Symptom (older builds): 0-byte junk files with a literal backslash next to
the binary —generalszh\Perf.txt,\Ping.txt,\QMPerf.txt,\StateChanged.txt. - Symptom (recent builds): the
apple_path::normalizewrapper hid the junk
file, but the Perf / Ping / QMPerf / StateChanged debug logs then never wrote at all. - Cause:
strrchr(buffer, '\\')can never match a POSIX (/) path. - Fix: strip and re-join with the native path separator (
/on Apple,
\on Windows) at all 5 idiom sites —MiniLog.cpp(the live-in-release one via
DEBUG_LOGGING),W3DDisplay.cppStatDumpClass(debug/profile), and
W3DModelDraw.cpp(debug-CRC). Mirrors the existingDebug.cpp__APPLE__fix.
Windows path byte-identical (#else). - Verified live in CWC: clean
Perf/Ping/QMPerf/StateChanged.txtare now written
next to the binary, with no backslash junk created.
- Symptom (older builds): 0-byte junk files with a literal backslash next to
The GeneralsZH Launcher downloads this engine automatically. You must own a
legitimate copy of Zero Hour — EA game data is not included.
Apple Silicon (M-series) only. Checksums in SHA256SUMS.
GeneralsZH Launcher — macOS (Apple Silicon) launcher-v0.1.5
launcher-v0.1.5 — "Disable menu 3D scene" option
Native macOS (Apple Silicon) launcher for Command & Conquer: Generals — Zero Hour.
NEW: "Disable menu 3D scene" checkbox on the Play tab (on by default).
Symptom → cause → fix:
- Symptom: the game's animated 3D menu background (the "shellmap") steadily leaks
memory the whole time the main menu is shown on macOS. - Cause: a macOS AGX-driver behaviour tied to rendering that shellmap scene.
- Fix: the option launches the engine with GEN_NO_SHELLMAP=1, which renders a
static menu background instead, so menu memory stays flat. Uncheck it to restore
the animated scene.
Requires engine-v0.1.9 or newer (the engine hook this option relies on). The
launcher auto-downloads a compatible engine.
Apple Silicon (M-series) only.
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.9
engine-v0.1.9 — memory-leak fixes: in-game plateau + no-leak menu option
Native macOS (Apple Silicon) build of the Zero Hour engine. This release stops the
long-session memory growth, in-game and in the menu.
IN-GAME MEMORY GROWTH — FIXED
Symptom: a session started around 950 MB and ratcheted to 2–4+ GB; units died off
late in a match but memory kept climbing, and leaving to the menu added another
~200 MB. Now it plateaus at the battle working set (~1.2–1.5 GB) and recovers
after the match.
Symptom → cause → fix:
- Pool policy = cap-not-decay. Cause: periodically freeing the renderer's GPU
buffer/texture recycle pools was itself the main leak — on Apple Metal each
release of a churned pooled resource becomes a permanent "zombie" backing in
the driver's own never-shrinking pool, while the next allocation takes fresh
device memory (A/B: freeing ratcheted ~13 MB/min; not-freeing was flat at half
the size). Fix: never free in steady state (the pools plateau at the working
set, as the original game does); bound load bursts with flat 256-per-key caps. - Pool thread-safety. Cause: the background texture loader raced the render
thread on unguarded pool maps; corrupted lookups orphaned textures (29k /
2.5 GB in one session). Fix: guard all pool operations with a mutex. - Audio AudioUnit accumulation. Cause: re-binding a sound file detached a still-
playing node, so the audio engine kept its AudioUnit alive (+559 per 3 min of
battle). Fix: stop the node before detaching, in both the 2D and 3D paths. - Map-load GPU balloon. Cause: hundreds of mipmap generations in a single
command buffer made the driver size its pool at the burst peak (~200 MB) and
never shrink. Fix: chunk mip flushes (≤32 per command buffer) with completion
backpressure. - Bot/External-API AIGroup leak: an AI group was created per bot command and
never destroyed. Fix: RAII releaser on every exit path. - Bot/External-API WebSocket backpressure: a slow /events consumer grew an
unbounded in-process send buffer. Fix: skip clients with >4 MB queued (the
event stream is resumable). - Guard-from-Position use-after-free: leaving a match mid-targeting left a decal
pointing into the torn-down shadow manager. Fix: clear the targeting state on
reset.
MENU 3D SCENE (SHELLMAP) — NEW OPT-OUT
Symptom: sitting in the main menu with the animated 3D background grew memory
~130 MB/min (a macOS AGX-driver behaviour tied to the shellmap scene, invariant to
every render/pool knob we tried). Fix: a new GEN_NO_SHELLMAP hook disables just
that scene (static menu background instead), applied after INI loads so a mod's
ShellMapOn setting can't silently re-enable it. The macOS launcher's "Disable menu
3D scene" option (on by default, launcher-v0.1.5) uses it. Note: the engine's
native -noshellmap command-line flag does NOT work with total-conversion mods —
it is parsed before INI, so the mod re-enables the scene.
Apple Silicon (M-series) only. You must own a legitimate copy of Zero Hour — EA
game data is not included. Checksums in SHA256SUMS.
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.10
engine-v0.1.10 — Save / Load / Replay now work on macOS
Native macOS (Apple Silicon) build of the Command & Conquer: Generals — Zero Hour
engine. This release makes saving, loading, and replays work. Previously Save
did nothing and the Load menu was always empty.
The GeneralsZH Launcher downloads this engine automatically. You must own a
legitimate copy of Zero Hour — EA game data is not included. Apple Silicon
(M-series) only. Checksums in SHA256SUMS.
Fixed
1. Saving did nothing; the Load menu was always empty.
- Symptom: pressing Save showed no error but wrote nothing usable, and the Load
screen was empty even after "saving". - Cause: the engine builds file paths with Windows
\separators (e.g.
…/Save\game.sav). The direct-fopensites already converted\→/, but the
POSIX-backed Win32 filesystem shims (mkdir/chdir/stat/access/unlink/
open) did not — so the game created a directory literally namedSave\
while the save file was opened atSave/…. On a clean profile the write failed
outright; the Load menu also enumerated the wrong (empty) directory. - Fix: every path-taking compat shim now normalises
\→/(with case-correction),
the same way the fopen sites do. Saves write, auto-increment their filenames,
and appear in the Load menu.
2. Loading a save showed "Error loading game".
- Symptom: selecting a save and pressing Load popped an error instead of loading.
- Cause: two stacked pre-existing bugs, only reachable once saving worked —
(a) the engine's path-normaliser first asks Windows for the required buffer size
viaGetFullPathName(path, 0, NULL), which the compat shim always failed; and
(b) the map-path safety check compared paths case-sensitively, but macOS is
case-insensitive and the saved map path is stored lower-cased — so a perfectly
valid map was rejected. - Fix: the shim now answers the size query per the Win32 contract, and path
containment compares case-insensitively on macOS. Saves load correctly.
3. Replays are recorded and play back.
- Cause: the same
\-path-separator class of bug affected the replay writer, so
replays landed in the wrong folder. - Fix: replays now record to
Replays/and play back from the Load Replay menu. - Note (by design, not a bug): recording a replay of a game continued from a
save is intentionally unsupported — a replay needs the full command history
from the start of the match, which a mid-game save snapshot does not contain.
This matches the original game (the "Save Replay" button is greyed for a loaded
game).
Changed
- Hardened the whole macOS filesystem boundary: 21 additional direct-
fopen
sites across the engine (replays, local-file I/O, temp files, debug/crash logs,
stats) now normalise Windows paths too — closing this class of bug for good.
No graphics or effects were removed. In-game memory usage is unchanged (flat).
GeneralsZH Launcher — macOS (Apple Silicon) launcher-v0.1.4
Native macOS arm64 launcher for Command & Conquer: Generals — Zero Hour.
New — "Mods & Extensions" tab
- Extensions: one-click Install / Remove of optional add-ons straight into your game folder. First add-on: Vehicle Dual Guard — the two-click Guard-From-Position order on every Cold War Crisis combat vehicle & aircraft (attacks anything entering a watch zone, returns home when the threat clears).
- Mods: a guided path for third-party mods we don't host — opens the mod's official download page (e.g. Cold War Crisis on ModDB) and registers the file you downloaded so it launches via the mod system.
- The catalog loads live from the repo, so new add-ons appear without a launcher update. Refresh reloads it and re-checks what's installed.
Install
- Download GeneralsZH-Launcher.dmg, open it, and drag GeneralsZH Launcher.app onto the Applications folder.
- The app is ad-hoc signed (not notarized), so macOS blocks it on first launch. Clear the quarantine flag once in Terminal, then open normally:
xattr -dr com.apple.quarantine "/Applications/GeneralsZH Launcher.app" - Pick the folder with your original Zero Hour data (
.bigfiles) and press Play. The engine is downloaded automatically from the latestengine-v*release.
(GeneralsZH-Launcher.app.zip is also attached — it's what the launcher's built-in updater uses.) Apple Silicon (M-series) only. Checksums in SHA256SUMS.
Zero Hour engine — macOS (Apple Silicon) engine-v0.1.8
Native macOS arm64 build of the Command & Conquer: Generals — Zero Hour engine.
Fixed — steady in-game GPU-memory leak
- Symptom: game memory climbed continuously during play (~50–100 MB/s on a large map / long battle), reaching tens of GB of RSS over time.
- Cause: on-screen UI text that changes every frame (money/score, timers, the menu clock, load-screen counters) rebuilds its glyph atlas each frame. The DX8→Metal shim allocated a fresh small texture per frame, and Metal's allocator did not reclaim the churned backings promptly → GPU memory grew without bound. (The textures were freed correctly — the churn defeated the allocator.)
- Fix: a create/release texture recycle pool in the shim reuses small font textures instead of reallocating them every frame. In-game and menu text render identically; memory now plateaus and stays flat.
MTL_NO_TEXPOOL=1reverts.
No graphics or quality changes — this only stops the leak.
The GeneralsZH Launcher downloads this engine automatically. You must own a legitimate copy of Zero Hour — EA game data is not included. Apple Silicon (M-series) only. Checksums in SHA256SUMS.