Skip to content

Commit f6eea97

Browse files
committed
Implement multiple resolution font size methods
1 parent 4c50112 commit f6eea97

File tree

7 files changed

+154
-38
lines changed

7 files changed

+154
-38
lines changed

Core/GameEngine/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(GAMEENGINE_SRC
22
# Include/Common/AcademyStats.h
33
# Include/Common/ActionManager.h
4+
Include/Common/AddonCompat.h
45
Include/Common/ArchiveFile.h
56
Include/Common/ArchiveFileSystem.h
67
Include/Common/AsciiString.h
@@ -554,6 +555,7 @@ set(GAMEENGINE_SRC
554555
# Include/GameNetwork/WOLBrowser/FEBDispatch.h
555556
# Include/GameNetwork/WOLBrowser/WebBrowser.h
556557
# Include/Precompiled/PreRTS.h
558+
Source/Common/AddonCompat.cpp
557559
Source/Common/Audio/AudioEventRTS.cpp
558560
Source/Common/Audio/AudioRequest.cpp
559561
Source/Common/Audio/DynamicAudioEventInfo.cpp
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#pragma once
20+
21+
namespace addon
22+
{
23+
extern Bool HasFullviewportDat();
24+
25+
} // namespace addon
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#include "PreRTS.h"
20+
21+
#include "Common/AddonCompat.h"
22+
#include "Common/FileSystem.h"
23+
24+
namespace addon
25+
{
26+
Bool HasFullviewportDat()
27+
{
28+
Char value = '0';
29+
if (File* file = TheFileSystem->openFile("GenTool/fullviewport.dat", File::READ | File::BINARY))
30+
{
31+
file->read(&value, 1);
32+
}
33+
return value != '0';
34+
}
35+
36+
} // namespace addon

GeneralsMD/Code/GameEngine/Include/GameClient/GlobalLanguage.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ class AsciiString;
6565
//-----------------------------------------------------------------------------
6666
class GlobalLanguage : public SubsystemInterface
6767
{
68+
public:
69+
70+
enum ResolutionFontSizeMethod
71+
{
72+
ResolutionFontSizeMethod_Classic, // Uses the original scaling method. Scales poorly on wide screens and large resolutions.
73+
ResolutionFontSizeMethod_Strict, // Uses a strict scaling method. Width and height are strictly bounded on upscales. Works well for accurate UI layouts and with large resolutions.
74+
ResolutionFontSizeMethod_Balanced, // Uses a balanced scaling method. Width and height are evenly weighted for upscales. Works well for the original Game UI and with large resolutions.
75+
};
76+
6877
public:
6978

7079
GlobalLanguage();
@@ -96,15 +105,15 @@ class GlobalLanguage : public SubsystemInterface
96105
FontDesc m_creditsTitleFont;
97106
FontDesc m_creditsPositionFont;
98107
FontDesc m_creditsNormalFont;
99-
100108
Real m_resolutionFontSizeAdjustment;
101109
Real m_userResolutionFontSizeAdjustment;
102-
103-
//UnicodeString m_unicodeFontNameUStr;
110+
ResolutionFontSizeMethod m_resolutionFontSizeMethod;
104111

105112
float getResolutionFontSizeAdjustment() const;
106113
Int adjustFontSize(Int theFontSize); // Adjusts font size for resolution. jba.
107114

115+
void parseCustomDefinition();
116+
108117
typedef std::list<AsciiString> StringList; // Used for our font file names that we want to load
109118
typedef StringList::iterator StringListIt;
110119

GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ void GameEngine::init()
520520
initSubsystem(TheTerrainTypes,"TheTerrainTypes", MSGNEW("GameEngineSubsystem") TerrainTypeCollection(), &xferCRC, "Data\\INI\\Default\\Terrain", "Data\\INI\\Terrain");
521521
initSubsystem(TheTerrainRoads,"TheTerrainRoads", MSGNEW("GameEngineSubsystem") TerrainRoadCollection(), &xferCRC, "Data\\INI\\Default\\Roads", "Data\\INI\\Roads");
522522
initSubsystem(TheGlobalLanguageData,"TheGlobalLanguageData",MSGNEW("GameEngineSubsystem") GlobalLanguage, NULL); // must be before the game text
523+
TheGlobalLanguageData->parseCustomDefinition();
523524
initSubsystem(TheCDManager,"TheCDManager", CreateCDManager(), NULL);
524525
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
525526
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////

GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,15 @@
3232
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
3333
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
3434

35+
#include "Common/GlobalData.h"
36+
3537
#define DEFINE_TERRAIN_LOD_NAMES
3638
#define DEFINE_TIME_OF_DAY_NAMES
3739
#define DEFINE_WEATHER_NAMES
3840
#define DEFINE_BODYDAMAGETYPE_NAMES
3941
#define DEFINE_PANNING_NAMES
4042

43+
#include "Common/AddonCompat.h"
4144
#include "Common/crc.h"
4245
#include "Common/file.h"
4346
#include "Common/FileSystem.h"
@@ -1246,18 +1249,10 @@ void GlobalData::parseGameDataDefinition( INI* ini )
12461249

12471250
void GlobalData::parseCustomDefinition()
12481251
{
1252+
if (addon::HasFullviewportDat())
12491253
{
1250-
// TheSuperHackers @feature xezon 03/08/2025 Force full viewport for 'Control Bar Pro' Addons like GenTool did it.
1251-
File* file = TheFileSystem->openFile("GenTool/fullviewport.dat", File::READ | File::BINARY);
1252-
if (file != NULL)
1253-
{
1254-
Char value = '0';
1255-
file->read(&value, 1);
1256-
if (value != '0')
1257-
{
1258-
m_viewportHeightScale = 1.0f;
1259-
}
1260-
}
1254+
// TheSuperHackers @tweak xezon 03/08/2025 Force full viewport for 'Control Bar Pro' Addons like GenTool did it.
1255+
m_viewportHeightScale = 1.0f;
12611256
}
12621257
}
12631258

GeneralsMD/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
//-----------------------------------------------------------------------------
5353
#include "PreRTS.h"
5454

55+
#include "Common/AddonCompat.h"
5556
#include "Common/INI.h"
5657
#include "Common/Registry.h"
5758
#include "Common/FileSystem.h"
@@ -65,6 +66,14 @@
6566
//-----------------------------------------------------------------------------
6667
GlobalLanguage *TheGlobalLanguageData = NULL; ///< The global language singalton
6768

69+
static const LookupListRec ResolutionFontSizeMethodNames[] =
70+
{
71+
{ "CLASSIC", GlobalLanguage::ResolutionFontSizeMethod_Classic },
72+
{ "STRICT", GlobalLanguage::ResolutionFontSizeMethod_Strict },
73+
{ "BALANCED", GlobalLanguage::ResolutionFontSizeMethod_Balanced },
74+
{ NULL, 0 }
75+
};
76+
6877
static const FieldParse TheGlobalLanguageDataFieldParseTable[] =
6978
{
7079
{ "UnicodeFontName", INI::parseAsciiString,NULL, offsetof( GlobalLanguage, m_unicodeFontName ) },
@@ -73,7 +82,7 @@ static const FieldParse TheGlobalLanguageDataFieldParseTable[] =
7382
{ "MilitaryCaptionSpeed", INI::parseInt, NULL, offsetof( GlobalLanguage, m_militaryCaptionSpeed ) },
7483
{ "UseHardWordWrap", INI::parseBool, NULL, offsetof( GlobalLanguage, m_useHardWrap) },
7584
{ "ResolutionFontAdjustment", INI::parseReal, NULL, offsetof( GlobalLanguage, m_resolutionFontSizeAdjustment) },
76-
85+
{ "ResolutionFontSizeMethod", INI::parseLookupList, ResolutionFontSizeMethodNames, offsetof( GlobalLanguage, m_resolutionFontSizeMethod) },
7786
{ "CopyrightFont", GlobalLanguage::parseFontDesc, NULL, offsetof( GlobalLanguage, m_copyrightFont ) },
7887
{ "MessageFont", GlobalLanguage::parseFontDesc, NULL, offsetof( GlobalLanguage, m_messageFont) },
7988
{ "MilitaryCaptionTitleFont", GlobalLanguage::parseFontDesc, NULL, offsetof( GlobalLanguage, m_militaryCaptionTitleFont) },
@@ -120,6 +129,7 @@ GlobalLanguage::GlobalLanguage()
120129
m_militaryCaptionSpeed = 0;
121130
m_useHardWrap = FALSE;
122131
m_resolutionFontSizeAdjustment = 0.7f;
132+
m_resolutionFontSizeMethod = ResolutionFontSizeMethod_Balanced;
123133
m_militaryCaptionDelayMS = 750;
124134
//End Add
125135

@@ -196,38 +206,76 @@ float GlobalLanguage::getResolutionFontSizeAdjustment( void ) const
196206

197207
Int GlobalLanguage::adjustFontSize(Int theFontSize)
198208
{
199-
// TheSuperHackers @tweak xezon 16/08/2025 The size adjustment now also weighs in
200-
// the display height for a balanced rescale on non 4:3 resolutions.
201-
// The aspect ratio scaling is clamped between 1 and 2 to avoid oversizing.
202-
// The scaler no longer clamps at max 2, which makes it work properly for
203-
// 4k Resolutions and beyond.
204-
205-
Real w = TheDisplay->getWidth();
206-
Real h = TheDisplay->getHeight();
207-
const Real aspect = w / h;
208-
Real wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
209-
Real hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
210-
211-
if (aspect > 2.0f)
209+
Real adjustFactor;
210+
211+
switch (m_resolutionFontSizeMethod)
212212
{
213-
// Recompute width at aspect=2
214-
w = 2.0f * h;
215-
wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
213+
default:
214+
case ResolutionFontSizeMethod_Classic:
215+
{
216+
// TheSuperHackers @info The original font scaling for this game.
217+
// Can be useful for not breaking legacy Addons and Mods but scales poorly.
218+
adjustFactor = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
219+
adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
220+
if (adjustFactor > 2.0f)
221+
adjustFactor = 2.0f;
222+
break;
216223
}
217-
else if (aspect < 1.0f)
224+
case ResolutionFontSizeMethod_Strict:
218225
{
219-
// Recompute height at aspect=1
220-
h = 1.0f * w;
221-
hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
226+
// TheSuperHackers @feature The strict method scales fonts based on the smallest screen
227+
// dimension so they scale independent of aspect ratio.
228+
const Real wScale = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
229+
const Real hScale = TheDisplay->getHeight() / (Real)DEFAULT_DISPLAY_HEIGHT;
230+
adjustFactor = min(wScale, hScale);
231+
adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
232+
break;
222233
}
234+
case ResolutionFontSizeMethod_Balanced:
235+
{
236+
// TheSuperHackers @feature The balanced method evenly weighs the display width and height
237+
// for a balanced rescale on non 4:3 resolutions. The aspect ratio scaling is clamped
238+
// between 1 and 2 to avoid oversizing.
239+
Real w = TheDisplay->getWidth();
240+
Real h = TheDisplay->getHeight();
241+
const Real aspect = w / h;
242+
Real wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
243+
Real hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
223244

224-
Real adjustFactor = (wScale + hScale) * 0.5f;
225-
adjustFactor = 1.0f + (adjustFactor-1.0f) * getResolutionFontSizeAdjustment();
226-
if (adjustFactor < 1.0f) adjustFactor = 1.0f;
245+
if (aspect > 2.0f)
246+
{
247+
// Recompute width at aspect=2
248+
w = 2.0f * h;
249+
wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
250+
}
251+
else if (aspect < 1.0f)
252+
{
253+
// Recompute height at aspect=1
254+
h = 1.0f * w;
255+
hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
256+
}
257+
adjustFactor = (wScale + hScale) * 0.5f;
258+
adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
259+
break;
260+
}
261+
}
262+
263+
if (adjustFactor < 1.0f)
264+
adjustFactor = 1.0f;
227265
Int pointSize = REAL_TO_INT_FLOOR(theFontSize*adjustFactor);
228266
return pointSize;
229267
}
230268

269+
void GlobalLanguage::parseCustomDefinition()
270+
{
271+
if (addon::HasFullviewportDat())
272+
{
273+
// TheSuperHackers @tweak xezon 19/08/2025 Force the classic font size adjustment for the old
274+
// 'Control Bar Pro' Addons because they use manual font upscaling in higher resolution packages.
275+
m_resolutionFontSizeMethod = ResolutionFontSizeMethod_Classic;
276+
}
277+
}
278+
231279
FontDesc::FontDesc(void)
232280
{
233281
name = "Arial Unicode MS"; ///<name of font

0 commit comments

Comments
 (0)