Skip to content

[GEN][ZH] Generate git version information and print it in the Game Window title, Options Menu (and Main Menu) #1219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ target_include_directories(corei_libraries_source_wwvegas_wwlib INTERFACE "Libra
target_link_libraries(corei_always INTERFACE
core_utility
corei_libraries_include
resources
)

# Set where the build results will end up
Expand Down
46 changes: 36 additions & 10 deletions GeneralsMD/Code/GameEngine/Include/Common/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#ifndef __VERSION_H__
#define __VERSION_H__

#include <time.h>

/**
* The Version class formats the version number into integer and string
* values for different parts of the game.
Expand All @@ -40,16 +42,26 @@ class Version
{
public:
Version();
UnsignedInt getVersionNumber( void ); ///< Return a 4-byte integer suitable for WOLAPI
AsciiString getAsciiVersion( void ); ///< Return a human-readable version number
UnicodeString getUnicodeVersion( void ); ///< Return a human-readable version number
UnicodeString getFullUnicodeVersion( void ); ///< Return a human-readable version number
AsciiString getAsciiBuildTime( void ); ///< Return a formated date/time string for build time
UnicodeString getUnicodeBuildTime( void ); ///< Return a formated date/time string for build time
AsciiString getAsciiBuildLocation( void ); ///< Return a string with the build location
UnicodeString getUnicodeBuildLocation( void ); ///< Return a string with the build location
AsciiString getAsciiBuildUser( void ); ///< Return a string with the build user
UnicodeString getUnicodeBuildUser( void ); ///< Return a string with the build user

UnsignedInt getVersionNumber( void ) const; ///< Return a 4-byte integer suitable for WOLAPI
AsciiString getAsciiVersion( void ) const; ///< Return a human-readable version number
UnicodeString getUnicodeVersion( void ) const; ///< Return a human-readable version number
AsciiString getAsciiBuildTime( void ) const; ///< Return a formated date/time string for build time
UnicodeString getUnicodeBuildTime( void ) const; ///< Return a formated date/time string for build time
AsciiString getAsciiBuildLocation( void ) const; ///< Return a string with the build location
UnicodeString getUnicodeBuildLocation( void ) const; ///< Return a string with the build location
AsciiString getAsciiBuildUser( void ) const; ///< Return a string with the build user
UnicodeString getUnicodeBuildUser( void ) const; ///< Return a string with the build user

static Int getGitRevision();
static time_t getGitCommitTime();
AsciiString getAsciiGitRevision( void ) const { return m_asciiGitRevision; }
AsciiString getAsciiGitVersion( void ) const { return m_asciiGitVersion; }
AsciiString getAsciiGitCommitTime( void ) const { return m_asciiGitCommitTime; }
UnicodeString getUnicodeGitRevision( void ) const { return m_unicodeGitRevision; }
UnicodeString getUnicodeGitVersion( void ) const { return m_unicodeGitVersion; }
UnicodeString getUnicodeGitCommitTime( void ) const { return m_unicodeGitCommitTime; }
UnicodeString getUnicodeGameAndGitVersion( void ) const;

Bool showFullVersion( void ) { return m_showFullVersion; }
void setShowFullVersion( Bool val ) { m_showFullVersion = val; }
Expand All @@ -58,6 +70,14 @@ class Version
Int localBuildNum, AsciiString user, AsciiString location,
AsciiString buildTime, AsciiString buildDate); ///< Set version info

private:
static AsciiString buildAsciiGitRevision();
static AsciiString buildAsciiGitVersion();
static AsciiString buildAsciiGitCommitTime();
static UnicodeString buildUnicodeGitRevision();
static UnicodeString buildUnicodeGitVersion();
static UnicodeString buildUnicodeGitCommitTime();

private:
Int m_major;
Int m_minor;
Expand All @@ -67,6 +87,12 @@ class Version
AsciiString m_buildUser;
AsciiString m_buildTime;
AsciiString m_buildDate;
AsciiString m_asciiGitRevision;
AsciiString m_asciiGitVersion;
AsciiString m_asciiGitCommitTime;
UnicodeString m_unicodeGitRevision;
UnicodeString m_unicodeGitVersion;
UnicodeString m_unicodeGitCommitTime;
Bool m_showFullVersion;
};

Expand Down
161 changes: 117 additions & 44 deletions GeneralsMD/Code/GameEngine/Source/Common/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "GameClient/GameText.h"
#include "Common/version.h"

#include "gitinfo.h"

Version *TheVersion = NULL; ///< The Version singleton

Version::Version()
Expand All @@ -39,8 +41,14 @@ Version::Version()
m_minor = 0;
m_buildNum = 0;
m_localBuildNum = 0;
m_buildUser = AsciiString("somebody");
m_buildLocation = AsciiString("somewhere");
m_buildUser = "somebody";
m_buildLocation = "somewhere";
m_asciiGitRevision = buildAsciiGitRevision();
m_asciiGitVersion = buildAsciiGitVersion();
m_asciiGitCommitTime = buildAsciiGitCommitTime();
m_unicodeGitRevision = buildUnicodeGitRevision();
m_unicodeGitVersion = buildUnicodeGitVersion();
m_unicodeGitCommitTime = buildUnicodeGitCommitTime();
#if defined RTS_DEBUG || defined RTS_INTERNAL
m_showFullVersion = TRUE;
#else
Expand All @@ -62,12 +70,12 @@ void Version::setVersion(Int major, Int minor, Int buildNum,
m_buildDate = buildDate;
}

UnsignedInt Version::getVersionNumber( void )
UnsignedInt Version::getVersionNumber( void ) const
{
return m_major << 16 | m_minor;
}

AsciiString Version::getAsciiVersion( void )
AsciiString Version::getAsciiVersion( void ) const
{
AsciiString version;
#if defined RTS_DEBUG || defined RTS_INTERNAL
Expand All @@ -83,19 +91,22 @@ AsciiString Version::getAsciiVersion( void )
return version;
}

UnicodeString Version::getUnicodeVersion( void )
UnicodeString Version::getUnicodeVersion( void ) const
{
UnicodeString version;

#if defined RTS_DEBUG || defined RTS_INTERNAL
if (!m_localBuildNum)
version.format(TheGameText->fetch("Version:Format3").str(), m_major, m_minor, m_buildNum);
if (m_showFullVersion)
{
if (!m_localBuildNum)
version.format(TheGameText->fetch("Version:Format3").str(), m_major, m_minor, m_buildNum);
else
version.format(TheGameText->fetch("Version:Format4").str(), m_major, m_minor, m_buildNum, m_localBuildNum,
m_buildUser.getCharAt(0), m_buildUser.getCharAt(1));

Choose a reason for hiding this comment

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

I'd be inclined to change this to use the git commit author. You hard code this elsewhere to be "SuperHackers" which I assume is intended to be like a nintendo seal of approval, but anyone forking the repo and building it without changing that will also make a SuperHackers stamped binary.

Copy link
Author

Choose a reason for hiding this comment

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

Yes this Build User thing needs more work, because as you say, it is not really unique to us publishing it, if it is embedded as a plain string. I do not know what to do with it at this time.

Using Git Commit Author does not work, because that name is not stable. At least not for the CI builds. For local builds it probably would be fine.

We can use Git Commit Author, and override that with the build user if that is set (from CI).

Choose a reason for hiding this comment

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

In the original game, it seems that the build user was effectively the username of whoever authored the final build which the commit author is kind of an analog to. I like the idea of passing something from the CI which will differ if built on someone elses such as the repo owner and then falling back to commit author for local builds.

Copy link
Author

Choose a reason for hiding this comment

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

Improved. Now, VERSION_BUILDUSER (and VERSION_BUILDLOC) are empty strings, so build user will default to last git commit author name.

I do not yet know how we generate VERSION_BUILDUSER and VERSION_BUILDLOC, but that can be another change in the future.

}
else
version.format(TheGameText->fetch("Version:Format4").str(), m_major, m_minor, m_buildNum, m_localBuildNum,
m_buildUser.getCharAt(0), m_buildUser.getCharAt(1));
#else // defined RTS_DEBUG || defined RTS_INTERNAL
version.format(TheGameText->fetch("Version:Format2").str(), m_major, m_minor);
#endif // defined RTS_DEBUG || defined RTS_INTERNAL
{
version.format(TheGameText->fetch("Version:Format2").str(), m_major, m_minor);
}

#ifdef RTS_DEBUG
version.concat(UnicodeString(L" Debug"));
Expand All @@ -108,36 +119,15 @@ UnicodeString Version::getUnicodeVersion( void )
return version;
}

UnicodeString Version::getFullUnicodeVersion( void )
Copy link
Author

Choose a reason for hiding this comment

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

I removed this function because it was almost a duplicate of the one above. I combined what it does with the function above.

{
UnicodeString version;

if (!m_localBuildNum)
version.format(TheGameText->fetch("Version:Format3").str(), m_major, m_minor, m_buildNum);
else
version.format(TheGameText->fetch("Version:Format4").str(), m_major, m_minor, m_buildNum, m_localBuildNum,
m_buildUser.getCharAt(0), m_buildUser.getCharAt(1));

#ifdef RTS_DEBUG
version.concat(UnicodeString(L" Debug"));
#endif

#ifdef RTS_INTERNAL
version.concat(UnicodeString(L" Internal"));
#endif

return version;
}

AsciiString Version::getAsciiBuildTime( void )
AsciiString Version::getAsciiBuildTime( void ) const
{
AsciiString timeStr;
timeStr.format("%s %s", m_buildDate.str(), m_buildTime.str());

return timeStr;
}

UnicodeString Version::getUnicodeBuildTime( void )
UnicodeString Version::getUnicodeBuildTime( void ) const
{
UnicodeString build;
UnicodeString dateStr;
Expand All @@ -150,34 +140,117 @@ UnicodeString Version::getUnicodeBuildTime( void )
return build;
}

AsciiString Version::getAsciiBuildLocation( void )
AsciiString Version::getAsciiBuildLocation( void ) const
{
return AsciiString(m_buildLocation);
return m_buildLocation;
}

UnicodeString Version::getUnicodeBuildLocation( void )
UnicodeString Version::getUnicodeBuildLocation( void ) const
{
UnicodeString build;
UnicodeString machine;

machine.translate(AsciiString(m_buildLocation));
machine.translate(m_buildLocation);
build.format(TheGameText->fetch("Version:BuildMachine").str(), machine.str());

return build;
}

AsciiString Version::getAsciiBuildUser( void )
AsciiString Version::getAsciiBuildUser( void ) const
{
return AsciiString(m_buildUser);
return m_buildUser;
}

UnicodeString Version::getUnicodeBuildUser( void )
UnicodeString Version::getUnicodeBuildUser( void ) const
{
UnicodeString build;
UnicodeString user;

user.translate(AsciiString(m_buildUser));
user.translate(m_buildUser);
build.format(TheGameText->fetch("Version:BuildUser").str(), user.str());

return build;
}

Int Version::getGitRevision()
{
return GitRevision;
}

time_t Version::getGitCommitTime()
{
return GitCommitTimeStamp;
}

UnicodeString Version::getUnicodeGameAndGitVersion( void ) const
{
UnicodeString str;
if (m_showFullVersion)
{
str.format(L"%s %s %s",
getUnicodeVersion().str(),
getUnicodeGitRevision().str(),
getUnicodeGitVersion().str());
}
else
{
str.format(L"%s %s",
getUnicodeVersion().str(),
getUnicodeGitRevision().str());
}
return str;
}

AsciiString Version::buildAsciiGitRevision()
{
AsciiString str;
str.format("R %s%d",
GitUncommittedChanges ? "~" : "",
GitRevision);
return str;
}

AsciiString Version::buildAsciiGitVersion()
{
AsciiString str;
str.format("%s%s",
GitUncommittedChanges ? "~" : "",
GitTag[0] ? GitTag : GitShortSHA1);
return str;
}

AsciiString Version::buildAsciiGitCommitTime()
{
const Int len = 19;
AsciiString str;
Char* buf = str.getBufferForRead(len);
tm* time = gmtime(&GitCommitTimeStamp);
strftime(buf, len+1, "%Y-%m-%d %H:%M:%S", time);
return str;
}

UnicodeString Version::buildUnicodeGitRevision()
{
UnicodeString str;
str.format(L"R %s%d",
GitUncommittedChanges ? L"~" : L"",
GitRevision);
return str;
}

UnicodeString Version::buildUnicodeGitVersion()
{
UnicodeString str;
str.translate(buildAsciiGitVersion());
return str;
}

UnicodeString Version::buildUnicodeGitCommitTime()
{
const Int len = 19;
UnicodeString str;
WideChar* buf = str.getBufferForRead(len);
tm* time = gmtime(&GitCommitTimeStamp);
wcsftime(buf, len+1, L"%Y-%m-%d %H:%M:%S", time);
return str;
}
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,36 @@ GameWindow *win = NULL;
win->winHide(TRUE);

}

// TheSuperHackers @tweak Now prints version information in an optional version label.
// Originally this label does not exist in the Main Menu. It can be copied from the Options Menu.
static void initLabelVersion()
{
NameKeyType versionID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:LabelVersion") );
GameWindow *labelVersion = TheWindowManager->winGetWindowFromId( NULL, versionID );

if (labelVersion)
{
if (TheVersion && TheGlobalData)
{
UnicodeString version;
version.format(
L"%s %s exe:%08X ini:%08X %s",
TheVersion->getUnicodeGameAndGitVersion().str(),
TheVersion->getUnicodeGitCommitTime().str(),
TheGlobalData->m_exeCRC,
TheGlobalData->m_iniCRC,
TheVersion->getUnicodeBuildUser().str()
);
GadgetStaticTextSetText( labelVersion, version );
}
else
{
labelVersion->winHide( TRUE );
}
}
}

//-------------------------------------------------------------------------------------------------
/** Initialize the main menu */
//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -476,7 +506,6 @@ void MainMenuInit( WindowLayout *layout, void *userData )
exitID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonExit") );
motdID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonMOTD") );
worldBuilderID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonWorldBuilder") );
// NameKeyType versionID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:LabelVersion") );
getUpdateID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonGetUpdate") );
// buttonTRAININGID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonTRAINING") );
buttonChallengeID = TheNameKeyGenerator->nameToKey( AsciiString("MainMenu.wnd:ButtonChallenge") );
Expand Down Expand Up @@ -526,9 +555,6 @@ void MainMenuInit( WindowLayout *layout, void *userData )
buttonHard = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonHardID );
buttonDiffBack = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonDiffBackID );


// GameWindow *labelVersion = TheWindowManager->winGetWindowFromId( parentMainMenu, versionID );

getUpdate = TheWindowManager->winGetWindowFromId( parentMainMenu, getUpdateID );
// buttonTRAINING = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonTRAININGID );
buttonChallenge = TheWindowManager->winGetWindowFromId( parentMainMenu, buttonChallengeID );
Expand Down Expand Up @@ -578,22 +604,10 @@ void MainMenuInit( WindowLayout *layout, void *userData )
25, 54,
180, 26,
&instData, NULL, TRUE );

// if (TheVersion)
// {
// UnicodeString version;
// version.format(L"%s\n%s", TheVersion->getUnicodeVersion().str(), TheVersion->getUnicodeBuildTime().str());
// GadgetStaticTextSetText( labelVersion, version );
// }
// else
// {
// labelVersion->winHide( TRUE );
// }
//#else

// GadgetStaticTextSetText( labelVersion, TheVersion->getUnicodeVersion() );
#endif

initLabelVersion();

//TheShell->registerWithAnimateManager(buttonCampaign, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800);
//TheShell->registerWithAnimateManager(buttonSkirmish, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600);
// TheShell->registerWithAnimateManager(buttonSinglePlayer, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400);
Expand Down
Loading
Loading