Skip to content

[ZH] Implement Headless Mode #651

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

Merged
merged 73 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
e4b6f18
Make CRC-related commandline arguments work when compiling Release wi…
helmutbuhler Mar 22, 2025
fb4881f
Add comments to Xfer.h
helmutbuhler Mar 22, 2025
10991d6
Add some comments to crc command line arguments
helmutbuhler Mar 22, 2025
320cd7c
Resest Frame Counter earlier in GameLogic::prepareNewGame instead of …
helmutbuhler Mar 23, 2025
2e0a25c
Improved CRC Debugging: Optionally save crc data into a file per fram…
helmutbuhler Mar 29, 2025
adfd721
Improved logging for mismatch debugging.
helmutbuhler Mar 29, 2025
ba13902
Make condition for checking TheCRCFirstFrameToLog consistent.
helmutbuhler Mar 29, 2025
1b2f5a8
Add comment regarding g_keepCRCSaves
helmutbuhler Mar 29, 2025
fb5d977
Remove transform crclogging in Object::crc. This was likely copypaste…
helmutbuhler Mar 29, 2025
46a4ab4
Delete CRC Frame files properly
helmutbuhler Mar 29, 2025
9f7287e
Improve comments
helmutbuhler Apr 10, 2025
4a22c73
Reset framecounter and call CRCDebugStartNewGame in GameLogic::startN…
helmutbuhler Apr 10, 2025
e536826
Fix TEAM_ID_INVALID
helmutbuhler Apr 10, 2025
21b4851
Some code cleanup in CRCDebug
helmutbuhler Apr 10, 2025
88a5b8e
Merge branch 'hb_sh' into improve_crc_logging_ea
helmutbuhler Apr 10, 2025
2be0870
Add define NORMAL_LOG_IN_CRC_LOG to control normal logging in crc logs.
helmutbuhler Apr 10, 2025
3813f09
Add cmake options to control logging
helmutbuhler Apr 10, 2025
83e7ec1
Add m_headless global flag to optionally run the game in headless mode.
helmutbuhler Apr 10, 2025
16aa073
Add some comments where logic-client-separation is broken.
helmutbuhler Apr 10, 2025
4229f1d
Add some more checks for headless
helmutbuhler Apr 10, 2025
c7c8b1d
Add comment about logic-client architecture and headless mode
helmutbuhler Apr 10, 2025
f69e41f
Add -headless commandline option
helmutbuhler Apr 11, 2025
7498de0
Fix headless when shutting down the engine.
helmutbuhler Apr 13, 2025
bf0a2e5
Rename RadarHeadless to RadarDummy
helmutbuhler Apr 13, 2025
7df3c68
Simplify RadarDummy
helmutbuhler Apr 13, 2025
8d325d9
Change TheWindowManager Check in ControlBar::getStarImage
helmutbuhler Apr 13, 2025
741a9a3
Merge branch 'main' into improve_crc_logging_ea
helmutbuhler Apr 13, 2025
bb744e7
Readd logging configuration to cmake files
helmutbuhler Apr 13, 2025
bf19c8c
Merge branch 'improve_crc_logging_ea' into headless_sh
helmutbuhler Apr 13, 2025
dd16528
Merge branch 'main' of https://github.com/TheSuperHackers/GeneralsGam…
helmutbuhler Apr 14, 2025
adfbe8b
Remove config-logging.cmake
helmutbuhler Apr 14, 2025
6fdf9ed
Fix wrong cmake feature names
helmutbuhler Apr 14, 2025
c26a4fa
Add RTS_DEBUG_INCLUDE_DEBUG_LOG_IN_CRC_LOG option (again)
helmutbuhler Apr 14, 2025
4917362
Fix comments
helmutbuhler Apr 15, 2025
40a9407
Merge branch 'improve_crc_logging_ea' into headless_sh
helmutbuhler Apr 15, 2025
5fba809
Merge branch 'main' of https://github.com/TheSuperHackers/GeneralsGam…
helmutbuhler Apr 15, 2025
73adde5
Merge branch 'main' of https://github.com/TheSuperHackers/GeneralsGam…
helmutbuhler Apr 15, 2025
e50eec4
Add null checks for W3DDisplay::m_3DScene
helmutbuhler Apr 17, 2025
232da78
Merge branch 'main' into headless_sh
helmutbuhler Apr 19, 2025
016187a
Merge branch 'main' into headless_sh
helmutbuhler Apr 24, 2025
d6c8339
Move m_headless check for W3DView to GameClient
helmutbuhler Apr 21, 2025
c26971e
Some minor code moving around
helmutbuhler Apr 21, 2025
8eb9730
Add missing headless check for Sizzle Video
helmutbuhler Apr 22, 2025
5951bc8
Add missing headless checks for m_bibBuffer in BaseHeightMapRenderObj…
helmutbuhler Apr 22, 2025
39ae00c
Add DummyGameWindowManager to avoid null checks
helmutbuhler Apr 23, 2025
8759b91
Remove TheWindowManager NULL checks
helmutbuhler Apr 23, 2025
cf8963d
Remove more TheWindowManager NULL checks
helmutbuhler Apr 24, 2025
d371c76
Fix stupid dates in comments
helmutbuhler Apr 24, 2025
9513645
Remove one more TheWindowManager NULL check
helmutbuhler Apr 24, 2025
1cf0c69
Fix some white space stuff
helmutbuhler Apr 24, 2025
d8bcd57
Add comments for DummyGameWindowManager
helmutbuhler Apr 24, 2025
a3c5b19
Fix logic-client-separation in W3DBridgeBuffer: It's needed for maps …
helmutbuhler Apr 26, 2025
194e04a
Merge branch 'main' into headless_sh
jaapdeheer May 15, 2025
9c151d9
Prefix new use of `_DEBUG` & `_INTERNAL` with `RTS`
jaapdeheer May 15, 2025
d938ee0
Add back newline
jaapdeheer May 15, 2025
174ab67
Rename `DummyGameWindow` to `GameWindowDummy`
jaapdeheer May 15, 2025
8cdad71
Rename `DummyGameWindowManager` to `GameWindowManagerDummy`
jaapdeheer May 15, 2025
91e7e3a
Drop commented code
jaapdeheer May 16, 2025
6b4ddde
Move `GameWindowDummy` to `GameWindow.h`
jaapdeheer May 16, 2025
9ea9f0a
Add missing if (TheMouse != NULL) check
helmutbuhler May 9, 2025
dd5eacb
Fix Division by Zero in headless
helmutbuhler May 12, 2025
26eff48
Add AudioManagerDummy for headless mode
helmutbuhler May 17, 2025
6f9e555
Don't override removeAudioEvent and addAudioEvent
helmutbuhler May 17, 2025
fdb453a
Merge branch 'headless_sh' of https://github.com/helmutbuhler/CnC_Gen…
helmutbuhler May 17, 2025
f4c19b6
Fix potential crash in headless mode by ensuring that DummyGameWindow…
helmutbuhler May 12, 2025
a63809e
Add comment for AudioManagerDummy
helmutbuhler May 17, 2025
37ce6f7
Fix comment date formats
helmutbuhler May 17, 2025
3c38c97
Add MouseDummy and remove NULL checks for TheMouse
helmutbuhler May 17, 2025
7401f27
Use RTS_DEBUG and RTS_INTERNAL
helmutbuhler May 17, 2025
097b898
Comment headless-checks that will be removed soon
helmutbuhler May 18, 2025
fa2dbe6
Move headless-check in W3DView::setCameraTransform higher up
helmutbuhler May 18, 2025
6bb77c0
Move headless-check in W3DGhostObject::restoreParentObject higher up
helmutbuhler May 18, 2025
385750e
Resolve minor suggestions
helmutbuhler May 20, 2025
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
51 changes: 51 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GameAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,57 @@ class AudioManager : public SubsystemInterface
Bool m_disallowSpeech : 1;
};

// TheSuperHackers @feature helmutbuhler 17/05/2025
// AudioManager that does nothing. Used for Headless Mode.
class AudioManagerDummy : public AudioManager
{
#if defined(RTS_DEBUG) || defined(RTS_INTERNAL)
virtual void audioDebugDisplay(DebugDisplayInterface* dd, void* userData, FILE* fp) {}
#endif
virtual void stopAudio(AudioAffect which) {}
virtual void pauseAudio(AudioAffect which) {}
virtual void resumeAudio(AudioAffect which) {}
virtual void pauseAmbient(Bool shouldPause) {}
virtual void killAudioEventImmediately(AudioHandle audioEvent) {}
virtual void nextMusicTrack() {}
virtual void prevMusicTrack() {}
virtual Bool isMusicPlaying() const { return false; }
virtual Bool hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const { return false; }
virtual AsciiString getMusicTrackName() const { return ""; }
virtual void openDevice() {}
virtual void closeDevice() {}
virtual void* getDevice() { return NULL; }
virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags) {}
virtual UnsignedInt getProviderCount(void) const { return 0; };
virtual AsciiString getProviderName(UnsignedInt providerNum) const { return ""; }
virtual UnsignedInt getProviderIndex(AsciiString providerName) const { return 0; }
virtual void selectProvider(UnsignedInt providerNdx) {}
virtual void unselectProvider(void) {}
virtual UnsignedInt getSelectedProvider(void) const { return 0; }
virtual void setSpeakerType(UnsignedInt speakerType) {}
virtual UnsignedInt getSpeakerType(void) { return 0; }
virtual UnsignedInt getNum2DSamples(void) const { return 0; }
virtual UnsignedInt getNum3DSamples(void) const { return 0; }
virtual UnsignedInt getNumStreams(void) const { return 0; }
virtual Bool doesViolateLimit(AudioEventRTS* event) const { return false; }
virtual Bool isPlayingLowerPriority(AudioEventRTS* event) const { return false; }
virtual Bool isPlayingAlready(AudioEventRTS* event) const { return false; }
virtual Bool isObjectPlayingVoice(UnsignedInt objID) const { return false; }
virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) {}
virtual void removePlayingAudio(AsciiString eventName) {}
virtual void removeAllDisabledAudio() {}
virtual Bool has3DSensitiveStreamsPlaying(void) const { return false; }
virtual void* getHandleForBink(void) { return NULL; }
virtual void releaseHandleForBink(void) {}
virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) {}
virtual void setPreferredProvider(AsciiString providerNdx) {}
virtual void setPreferredSpeaker(AsciiString speakerType) {}
virtual Real getFileLengthMS(AsciiString strToLoad) const { return -1; }
virtual void closeAnySamplesUsingFile(const void* fileToClose) {}
virtual void setDeviceListenerPosition(void) {}
};


extern AudioManager *TheAudio;

#endif // __COMMON_GAMEAUDIO_H_
5 changes: 5 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class GlobalData : public SubsystemInterface
Bool m_dumpAssetUsage;
Int m_framesPerSecondLimit;
Int m_chipSetType; ///<See W3DShaderManager::ChipsetType for options

// TheSuperHackers @feature helmutbuhler 11/04/2025
// Run game without graphics, input or audio.
Bool m_headless;

Bool m_windowed;
Int m_xResolution;
Int m_yResolution;
Expand Down
10 changes: 10 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/Radar.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,16 @@ class Radar : public Snapshot,
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern Radar *TheRadar; ///< the radar singleton extern

// TheSuperHackers @feature helmutbuhler 10/04/2025
// Radar that does nothing. Used for Headless Mode.
class RadarDummy : public Radar
{
public:
virtual void draw(Int pixelX, Int pixelY, Int width, Int height) { }
virtual void clearShroud() { }
virtual void setShroudLevel(Int x, Int y, CellShroudStatus setting) { }
};

#endif // __RADAR_H_


Expand Down
43 changes: 43 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,47 @@ inline Drawable* GameClient::findDrawableByID( const DrawableID id )
// the singleton
extern GameClient *TheGameClient;


// TheSuperHackers @logic-client-separation helmutbuhler 11/04/2025
// Some information about the architecture and headless mode:
// The game is structurally separated into GameLogic and GameClient.
// The Logic is responsible for everything that affects the game mechanic and what is synchronized over
// the network. The Client is responsible for rendering, input, audio and similar stuff.
//
// Unfortunately there are some places in the code that make the Logic depend on the Client.
// (Search for @logic-client-separation)
// That means if we want to run the game headless, we cannot just disable the Client. We need to disable
// the parts in the Client that don't work in headless mode and need to keep the parts that are needed
// to run the Logic.
// The following describes which parts we disable in headless mode:
//
// GameEngine:
// TheGameClient is partially disabled:
// TheKeyboard = NULL
// TheMouse = NULL
// TheDisplay is partially disabled:
// m_3DInterfaceScene = NULL
// m_2DScene = NULL
// m_3DScene = NULL
// (m_assetManager remains!)
// TheWindowManager = GameWindowManagerDummy
// TheIMEManager = NULL
// TheTerrainVisual is partially disabled:
// TheTerrainTracksRenderObjClassSystem = NULL
// TheW3DShadowManager = NULL
// TheWaterRenderObj = NULL
// TheSmudgeManager = NULL
// TheTerrainRenderObject is partially disabled:
// m_treeBuffer = NULL
// m_propBuffer = NULL
// m_bibBuffer = NULL
// m_bridgeBuffer is partially disabled:
// m_vertexBridge = NULL
// m_indexBridge = NULL
// m_vertexMaterial = NULL
// m_waypointBuffer = NULL
// m_roadBuffer = NULL
// m_shroud = NULL
// TheRadar = RadarDummy

#endif // _GAME_INTERFACE_H_
12 changes: 11 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameClient/GameWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ friend class GameWindowManager;
// window instance data
Int winSetInstanceData( WinInstanceData *data ); ///< copy over instance data
WinInstanceData *winGetInstanceData( void ); ///< get instance data
void *winGetUserData( void ); ///< get the window user data
virtual void *winGetUserData( void ); ///< get the window user data
void winSetUserData( void *userData ); ///< set the user data

// heirarchy methods
Expand Down Expand Up @@ -426,6 +426,16 @@ friend class GameWindowManager;

}; // end class GameWindow

// TheSuperHackers @feature helmutbuhler 24/04/2025
// GameWindow that does nothing. Used for Headless Mode.
class GameWindowDummy : public GameWindow
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameWindowDummy, "GameWindowDummy")
public:
virtual void winDrawBorder() {}
virtual void* winGetUserData(void) { return NULL; }
};

// ModalWindow ----------------------------------------------------------------
//-----------------------------------------------------------------------------
class ModalWindow : public MemoryPoolObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,39 @@ extern WindowMsgHandledType PassMessagesToParentSystem( GameWindow *window,
WindowMsgData mData1,
WindowMsgData mData2 );


// TheSuperHackers @feature helmutbuhler 24/04/2025
// GameWindowManager that does nothing. Used for Headless Mode.
class GameWindowManagerDummy : public GameWindowManager
{
public:
virtual GameWindow *winGetWindowFromId(GameWindow *window, Int id);
virtual GameWindow *winCreateFromScript(AsciiString filenameString, WindowLayoutInfo *info);

virtual GameWindow *allocateNewWindow() { return newInstance(GameWindowDummy); }

virtual GameWinDrawFunc getPushButtonImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getPushButtonDrawFunc() { return NULL; }
virtual GameWinDrawFunc getCheckBoxImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getCheckBoxDrawFunc() { return NULL; }
virtual GameWinDrawFunc getRadioButtonImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getRadioButtonDrawFunc() { return NULL; }
virtual GameWinDrawFunc getTabControlImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getTabControlDrawFunc() { return NULL; }
virtual GameWinDrawFunc getListBoxImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getListBoxDrawFunc() { return NULL; }
virtual GameWinDrawFunc getComboBoxImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getComboBoxDrawFunc() { return NULL; }
virtual GameWinDrawFunc getHorizontalSliderImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getHorizontalSliderDrawFunc() { return NULL; }
virtual GameWinDrawFunc getVerticalSliderImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getVerticalSliderDrawFunc() { return NULL; }
virtual GameWinDrawFunc getProgressBarImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getProgressBarDrawFunc() { return NULL; }
virtual GameWinDrawFunc getStaticTextImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getStaticTextDrawFunc() { return NULL; }
virtual GameWinDrawFunc getTextEntryImageDrawFunc() { return NULL; }
virtual GameWinDrawFunc getTextEntryDrawFunc() { return NULL; }
};

#endif // __GAMEWINDOWMANAGER_H_

15 changes: 14 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameClient/Mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,20 @@ class Mouse : public SubsystemInterface

}; // end class Mouse

// INLINING ///////////////////////////////////////////////////////////////////
// TheSuperHackers @feature helmutbuhler 17/05/2025
// Mouse that does nothing. Used for Headless Mode.
class MouseDummy : public Mouse
{
virtual void parseIni() {}
virtual void update() {}
virtual void initCursorResources() {}
virtual void createStreamMessages() {}
virtual void setCursor(MouseCursor cursor) {}
virtual void capture() {}
virtual void releaseCapture() {}
virtual UnsignedByte getMouseEvent(MouseIO *result, Bool flush) { return MOUSE_NONE; }
};


// EXTERNALS //////////////////////////////////////////////////////////////////
extern Mouse *TheMouse; ///< extern mouse singleton definition
Expand Down
13 changes: 13 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,15 @@ Int parseQuickStart( char *args[], int num )
return 1;
}

Int parseHeadless( char *args[], int num )
{
if (TheWritableGlobalData)
{
TheWritableGlobalData->m_headless = TRUE;
}
return 1;
}

Int parseConstantDebug( char *args[], int num )
{
if (TheWritableGlobalData)
Expand Down Expand Up @@ -1206,6 +1215,10 @@ static CommandLineParam params[] =
{ "-quickstart", parseQuickStart },
{ "-useWaveEditor", parseUseWaveEditor },

// TheSuperHackers @feature helmutbuhler 11/04/2025
// This runs the game without a window, graphics, input and audio. Used for testing.
{ "-headless", parseHeadless },

#if (defined(RTS_DEBUG) || defined(RTS_INTERNAL))
{ "-noaudio", parseNoAudio },
{ "-map", parseMapName },
Expand Down
4 changes: 2 additions & 2 deletions GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ void GameEngine::init( int argc, char *argv[] )
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
#endif/////////////////////////////////////////////////////////////////////////////////////////////
initSubsystem(TheAudio,"TheAudio", createAudioManager(), NULL);
initSubsystem(TheAudio,"TheAudio", TheGlobalData->m_headless ? NEW AudioManagerDummy : createAudioManager(), NULL);
if (!TheAudio->isMusicAlreadyLoaded())
setQuitting(TRUE);

Expand Down Expand Up @@ -507,7 +507,7 @@ void GameEngine::init( int argc, char *argv[] )
initSubsystem(TheCrateSystem,"TheCrateSystem", MSGNEW("GameEngineSubsystem") CrateSystem(), &xferCRC, "Data\\INI\\Default\\Crate.ini", "Data\\INI\\Crate.ini");
initSubsystem(ThePlayerList,"ThePlayerList", MSGNEW("GameEngineSubsystem") PlayerList(), NULL);
initSubsystem(TheRecorder,"TheRecorder", createRecorder(), NULL);
initSubsystem(TheRadar,"TheRadar", createRadar(), NULL);
initSubsystem(TheRadar,"TheRadar", TheGlobalData->m_headless ? NEW RadarDummy : createRadar(), NULL);
initSubsystem(TheVictoryConditions,"TheVictoryConditions", createVictoryConditions(), NULL);


Expand Down
1 change: 1 addition & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ GlobalData::GlobalData()
m_dumpAssetUsage = FALSE;
m_framesPerSecondLimit = 0;
m_chipSetType = 0;
m_headless = FALSE;
m_windowed = 0;
m_xResolution = 800;
m_yResolution = 600;
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Source/Common/RandomValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ Int GetGameClientRandomValue( int lo, int hi, const char *file, int line )
/**/
#ifdef DEBUG_RANDOM_CLIENT
DEBUG_LOG(( "%d: GetGameClientRandomValue = %d (%d - %d), %s line %d\n",
TheGameLogic->getFrame(), rval, lo, hi, file, line ));
TheGameLogic ? TheGameLogic->getFrame() : -1, rval, lo, hi, file, line ));
#endif
/**/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ static PoolSizeRec sizes[] =
{ "Overridable", 32, 32 },

{ "W3DGameWindow", 700, 256 },
{ "GameWindowDummy", 700, 256 },
{ "SuccessState", 32, 32 },
{ "FailureState", 32, 32 },
{ "ContinueState", 32, 32 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,8 @@ void ControlBar::reset( void )
//-------------------------------------------------------------------------------------------------
void ControlBar::update( void )
{
if (TheGlobalData->m_headless)
return;
getStarImage();
updateRadarAttackGlow();
if(m_controlBarSchemeManager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,8 @@ Int GadgetListBoxAddEntryText( GameWindow *listbox,
addInfo.width = -1;

ListboxData *listData = (ListboxData *)listbox->winGetUserData();
if (listData == NULL)
return -1;
Bool wasFull = (listData->listLength <= listData->endPos);
Int newEntryOffset = (wasFull)?0:1;
Int oldBottomIndex = GadgetListBoxGetBottomVisibleEntry(listbox);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4097,3 +4097,36 @@ void GameWindowManager::clearTabList( void )
{
m_tabList.clear();
}


GameWindow *GameWindowManagerDummy::winGetWindowFromId(GameWindow *window, Int id)
{
window = GameWindowManager::winGetWindowFromId(window, id);
if (window != NULL)
return window;

// Just return any window, callers expect this to be non-null
return m_windowList;
}

WindowMsgHandledType DummyWindowSystem(GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2)
{
return MSG_IGNORED;
}

GameWindow *GameWindowManagerDummy::winCreateFromScript(AsciiString filenameString, WindowLayoutInfo *info)
{
WindowLayoutInfo scriptInfo;
GameWindow* dummyWindow = winCreate(NULL, 0, 0, 0, 100, 100, DummyWindowSystem, NULL);
scriptInfo.windows.push_back(dummyWindow);
if (info)
*info = scriptInfo;
return dummyWindow;
}

GameWindowDummy::~GameWindowDummy()
{
}



Loading
Loading