Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions GeneralsMD/Code/GameEngine/Include/Common/NameKeyGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class NameKeyGenerator : public SubsystemInterface
// Get a string out of the INI. Store it into a NameKeyType
static void parseStringAsNameKeyType( INI *ini, void *instance, void *store, const void* userData );

#if RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR
void syncNameKeyID();
#endif
void verifyNameKeyID(UnsignedInt expectedNextID) const;
#endif

private:

enum
Expand All @@ -114,10 +121,6 @@ class NameKeyGenerator : public SubsystemInterface
SOCKET_COUNT = 45007
};

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
Bool addReservedKey();
#endif

NameKeyType nameToKeyImpl(const AsciiString& name);
NameKeyType nameToLowercaseKeyImpl(const AsciiString& name);
NameKeyType nameToKeyImpl(const char* name);
Expand Down
12 changes: 12 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,10 @@ void GameEngine::init()
#endif/////////////////////////////////////////////////////////////////////////////////////////////


#if RETAIL_COMPATIBLE_CRC
if (xferCRC.getCRC() == 0xA1E7F8E6) TheNameKeyGenerator->verifyNameKeyID(1);
Copy link

Choose a reason for hiding this comment

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

Use new line.

Multiple times.

#endif

initSubsystem(TheScienceStore,"TheScienceStore", MSGNEW("GameEngineSubsystem") ScienceStore(), &xferCRC, "Data\\INI\\Default\\Science", "Data\\INI\\Science");
initSubsystem(TheMultiplayerSettings,"TheMultiplayerSettings", MSGNEW("GameEngineSubsystem") MultiplayerSettings(), &xferCRC, "Data\\INI\\Default\\Multiplayer", "Data\\INI\\Multiplayer");
initSubsystem(TheTerrainTypes,"TheTerrainTypes", MSGNEW("GameEngineSubsystem") TerrainTypeCollection(), &xferCRC, "Data\\INI\\Default\\Terrain", "Data\\INI\\Terrain");
Expand All @@ -524,6 +528,10 @@ void GameEngine::init()
if (!TheAudio->isMusicAlreadyLoaded())
setQuitting(TRUE);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
TheNameKeyGenerator->syncNameKeyID();
Copy link

Choose a reason for hiding this comment

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

Instead of adding the syncNameKeyID function, how about just calling nameToKey 3 times here?

Copy link
Author

Choose a reason for hiding this comment

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

I wanted a better place for a TSH comment that's not in the middle of an enormous function that's not really related.

#endif

#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
sprintf(Buf,"----------------------------------------------------------------------------After TheAudio = %f seconds",((double)(endTime64-startTime64)/(double)(freq64)));
Expand Down Expand Up @@ -578,6 +586,10 @@ void GameEngine::init()
#endif/////////////////////////////////////////////////////////////////////////////////////////////


#if RETAIL_COMPATIBLE_CRC
if (xferCRC.getCRC() == 0x6209AF6E) TheNameKeyGenerator->verifyNameKeyID(2265);
#endif

initSubsystem(TheUpgradeCenter,"TheUpgradeCenter", MSGNEW("GameEngineSubsystem") UpgradeCenter, &xferCRC, "Data\\INI\\Default\\Upgrade", "Data\\INI\\Upgrade");
initSubsystem(TheGameClient,"TheGameClient", createGameClient(), nullptr);

Expand Down
61 changes: 21 additions & 40 deletions GeneralsMD/Code/GameEngine/Source/Common/NameKeyGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,68 +123,49 @@ AsciiString NameKeyGenerator::keyToName(NameKeyType key)
}

//-------------------------------------------------------------------------------------------------
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
// TheSuperHackers @info xezon 04/09/2025 This key reservation is required for CRC compatibility,
// because the name keys are somehow CRC relevant. It was originally used by the file exist cache
// of the file system in Zero Hour.
Bool NameKeyGenerator::addReservedKey()
#if RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR
// TheSuperHackers @bugfix Caball009 24/02/2026 Originally the game would hash three files
// for the file exist cache of the file system in Zero Hour.
// TheScienceStore and TheUpgradeCenter rely on having the exact same name key IDs across all clients.
// That means that we still need to hash 3 dummy strings to keep the name key IDs synchronized with retail.
void NameKeyGenerator::syncNameKeyID()
{
switch (m_nextID)
{
case 97: nameToLowercaseKeyImpl("Data\\English\\Language9x.ini"); return true;
case 98: nameToLowercaseKeyImpl("Data\\Audio\\Tracks\\English\\GLA_02.mp3"); return true;
case 99: nameToLowercaseKeyImpl("Data\\Audio\\Tracks\\GLA_02.mp3"); return true;
}
return false;
nameToKey("TSH_dummy_string_1");
nameToKey("TSH_dummy_string_2");
nameToKey("TSH_dummy_string_3");
Copy link

Choose a reason for hiding this comment

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

I suggest to preserve the original strings for context

Copy link
Author

@Caball009 Caball009 Feb 28, 2026

Choose a reason for hiding this comment

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

Yeah, I can use the strings that were added in #1516.

Those strings depend either on registry language and / or use sound track names that can be changed by mods, though.

Copy link

Choose a reason for hiding this comment

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

It is mainly about preserving the context for what these strings are for the next person to look at it.

Copy link
Author

Choose a reason for hiding this comment

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

That's fair.

}
#endif
void NameKeyGenerator::verifyNameKeyID(UnsignedInt expectedNextID) const
{
// this should only be called before the initialization of TheScienceStore and TheUpgradeCenter in GameEngine::init
DEBUG_ASSERTCRASH(expectedNextID == m_nextID,
("Retail client expects items to start with name key ID %d for unmodded files, but starts with %d", expectedNextID, m_nextID));
}
#endif

//-------------------------------------------------------------------------------------------------
NameKeyType NameKeyGenerator::nameToKey(const AsciiString& name)
{
const NameKeyType key = nameToKeyImpl(name);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
while (addReservedKey());
#endif

return key;
return nameToKeyImpl(name);
}

//-------------------------------------------------------------------------------------------------
NameKeyType NameKeyGenerator::nameToLowercaseKey(const AsciiString& name)
{
const NameKeyType key = nameToLowercaseKeyImpl(name);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
while (addReservedKey());
#endif

return key;
return nameToLowercaseKeyImpl(name);
}

//-------------------------------------------------------------------------------------------------
NameKeyType NameKeyGenerator::nameToKey(const char* name)
{
const NameKeyType key = nameToKeyImpl(name);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
while (addReservedKey());
#endif

return key;
return nameToKeyImpl(name);
}

//-------------------------------------------------------------------------------------------------
NameKeyType NameKeyGenerator::nameToLowercaseKey(const char *name)
{
const NameKeyType key = nameToLowercaseKeyImpl(name);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
while (addReservedKey());
#endif

return key;
return nameToLowercaseKeyImpl(name);
Copy link

Choose a reason for hiding this comment

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

This means you can merge nameToLowercaseKeyImpl into nameToLowercaseKey entirely as it was originally.

Four times.

}

//-------------------------------------------------------------------------------------------------
Expand Down
Loading