Skip to content

bugfix(namekey): Remove hardcoded NameKeyIDs from dummy strings to work with modded files#2349

Merged
xezon merged 8 commits intoTheSuperHackers:mainfrom
Caball009:fix_retail_namekey_ids
Mar 11, 2026
Merged

bugfix(namekey): Remove hardcoded NameKeyIDs from dummy strings to work with modded files#2349
xezon merged 8 commits intoTheSuperHackers:mainfrom
Caball009:fix_retail_namekey_ids

Conversation

@Caball009
Copy link

@Caball009 Caball009 commented Feb 24, 2026

Perhaps it's best to keep the issue open because it touches on a larger issue that this PR does not fix.

#1516 adds three strings with hardcoded name key IDs. This PR fixes the following issue:

Unfortunately, hardcoding the IDs doesn't work for modded files. This became apparent after this replay started to mismatch after #1516 at 4:00: TEOD_0986_P11.zip mod files This mod expects the three strings to have IDs 265 - 267.

I've added a second commit with debug assertions for the correct name key ID with unmodded files to help us detect undesirable additions or removals of name keys.

TODO:

  • Check hash and name key ID values for Generals.
  • Replicate in Generals.

@Caball009 Caball009 added Bug Something is not working right, typically is user facing Major Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour ThisProject The issue was introduced by this project, or this task is specific to this project labels Feb 24, 2026
@Caball009 Caball009 changed the title Fix retail namekey ids bugfix(namekeys): Remove hardcoded NameKeyIDs from dummy strings for modded files Feb 24, 2026
@Caball009 Caball009 marked this pull request as ready for review February 28, 2026 15:26
@greptile-apps
Copy link

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR fixes a CRC compatibility issue with modded files by replacing the old hardcoded name key ID reservation mechanism (addReservedKey() with a switch on m_nextID) with a simpler, mod-friendly approach that registers the three dummy strings at whatever sequential IDs they naturally fall into during engine initialization.

Key changes:

  • Removes addReservedKey(): The old switch-statement-based approach forced the three dummy strings into IDs 97–99 regardless of how many name keys a mod had already registered, causing replay mismatches in modded environments (e.g., TEOD mod expected IDs 265–267).
  • Adds syncNameKeyID(): A new method (ZH-only, RETAIL_COMPATIBLE_CRC) that simply calls nameToLowercaseKey() for the three dummy strings at the appropriate point in GameEngine::init(), after TheAudio is initialized. For unmodded files the natural assignment still lands at IDs 97–99; for modded files the IDs adjust automatically.
  • Adds verifyNameKeyID(): A debug assertion (wrapping DEBUG_ASSERTCRASH) placed at two checkpoints in GameEngine::init() — before TheScienceStore and before TheUpgradeCenter — that only fires when the live CRC matches the unmodded game CRC. This helps catch undesired key additions/removals in vanilla builds without penalizing mods.
  • Removes private *Impl() methods: The nameToKeyImpl/nameToLowercaseKeyImpl split was only needed to prevent recursive addReservedKey() calls; removing that mechanism makes the public methods self-contained.
  • The Generals CRC and name key ID constants (0x2E876341, 0xD9A74E13, 1586) are noted as unverified in the PR TODO and warrant a follow-up before the assertions in Generals debug builds are trusted.

Confidence Score: 4/5

  • Safe to merge; only debug assertion values for vanilla Generals are unverified but do not affect release builds.
  • The core logic fix (replacing hardcoded ID reservation with natural sequential assignment via syncNameKeyID) is sound, well-commented, and correctly guarded by preprocessor macros. The verifyNameKeyID assertions are debug-only and CRC-gated, so incorrect values in Generals cause no release-build risk. The one open TODO — verifying the Generals CRC/ID constants — is the only reason this isn't a 5.
  • Generals/Code/GameEngine/Source/Common/GameEngine.cpp — the CRC values and expected ID for the Generals (non-ZH) verifyNameKeyID calls are marked unverified in the PR TODO.

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Include/Common/NameKeyGenerator.h Adds public syncNameKeyID() (ZH-only) and verifyNameKeyID() under RETAIL_COMPATIBLE_CRC guard; removes private addReservedKey() and *Impl() method declarations. Clean restructuring.
GeneralsMD/Code/GameEngine/Include/Common/NameKeyGenerator.h Mirrors Generals header changes: adds public syncNameKeyID() (ZH-only) and verifyNameKeyID(), removes private addReservedKey() and *Impl() declarations.
Generals/Code/GameEngine/Source/Common/NameKeyGenerator.cpp Replaces addReservedKey()/while-loop mechanism with direct syncNameKeyID() call; nameToKeyImpl/nameToLowercaseKeyImpl renamed to nameToKey/nameToLowercaseKey (removing the split). verifyNameKeyID() added as a DEBUG_ASSERTCRASH check.
GeneralsMD/Code/GameEngine/Source/Common/NameKeyGenerator.cpp Identical structural changes to Generals counterpart. syncNameKeyID() and verifyNameKeyID() correctly introduced under appropriate preprocessor guards.
Generals/Code/GameEngine/Source/Common/GameEngine.cpp Adds verifyNameKeyID() assertions at two checkpoints and a (dead-code) syncNameKeyID() call under RTS_ZEROHOUR guard. CRC/ID values for Generals are explicitly marked TODO-unverified by the author.
GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp Adds verifyNameKeyID() assertions at two checkpoints and syncNameKeyID() call after TheAudio init. CRC/ID values appear correct for unmodded Zero Hour.

Sequence Diagram

sequenceDiagram
    participant GE as GameEngine::init()
    participant NKG as NameKeyGenerator
    participant CRC as xferCRC

    GE->>NKG: (subsystems initialized, no CRC keys registered)
    GE->>CRC: getCRC()
    Note over GE,CRC: RETAIL_COMPATIBLE_CRC only
    GE->>NKG: verifyNameKeyID(1) [if CRC matches]
    GE->>GE: initSubsystem(TheScienceStore)
    GE->>GE: initSubsystem(TheMultiplayerSettings)
    GE->>GE: initSubsystem(TheTerrainTypes)
    GE->>GE: initSubsystem(TheTerrainRoads)
    GE->>GE: initSubsystem(TheGlobalLanguageData)
    GE->>GE: initSubsystem(TheAudio)
    GE->>NKG: syncNameKeyID() [RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC]
    Note over NKG: nameToLowercaseKey("Data\\English\\Language9x.ini") → ID 97
    Note over NKG: nameToLowercaseKey("Data\\Audio\\Tracks\\English\\GLA_02.mp3") → ID 98
    Note over NKG: nameToLowercaseKey("Data\\Audio\\Tracks\\GLA_02.mp3") → ID 99
    GE->>GE: initSubsystem(TheFunctionLexicon, ..., TheThingFactory)
    GE->>CRC: getCRC()
    Note over GE,CRC: RETAIL_COMPATIBLE_CRC only
    GE->>NKG: verifyNameKeyID(1586/2265) [if CRC matches]
    GE->>GE: initSubsystem(TheUpgradeCenter)
    GE->>GE: initSubsystem(TheGameClient)
Loading

Last reviewed commit: ede0456

Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks plausible. Needs to be replicated to Generals.

@Caball009
Copy link
Author

Caball009 commented Mar 11, 2026

Replicated in Generals, manually resolved merge conflicts.

Hash and name key ID values still need to be verified for Generals.
Hash and name key ID values updated for Generals.

@github-actions
Copy link

⚠️ Title/Commit Validation Failed

Invalid commit messages:

  • Fixed incorrect hash and name key ID values for Generals.
  • Replicated in Generals, manually resolved merge conflicts.
  • Removed implementation functions.
  • Restored use of 'nameToLowercase' for dummy strings.
  • Addressed feedback (part 1).
  • Added assertions for name key IDs.
  • Fixed dummy string logic.
    PR titles and commit messages must follow conventional commits format:
type: Description
type(scope): Description

Allowed types: bugfix, build, chore, ci, docs, fix, feat, perf, refactor, revert, style, test, tweak, unify

See CONTRIBUTING.md for details.

@xezon xezon changed the title bugfix(namekeys): Remove hardcoded NameKeyIDs from dummy strings for modded files bugfix(namekey): Remove hardcoded NameKeyIDs from dummy strings for modded files Mar 11, 2026
@xezon xezon changed the title bugfix(namekey): Remove hardcoded NameKeyIDs from dummy strings for modded files bugfix(namekey): Remove hardcoded NameKeyIDs from dummy strings to work with modded files Mar 11, 2026
@xezon xezon merged commit d195e3b into TheSuperHackers:main Mar 11, 2026
23 of 25 checks passed
@Caball009 Caball009 deleted the fix_retail_namekey_ids branch March 11, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker ThisProject The issue was introduced by this project, or this task is specific to this project ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants