Skip to content
Merged
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
4 changes: 3 additions & 1 deletion Core/GameEngine/Source/Common/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,10 @@ Int parseLoadSave(char *args[], int num)
TheWritableGlobalData->m_shellMapOn = FALSE;
TheWritableGlobalData->m_playIntro = FALSE;
TheWritableGlobalData->m_playSizzle = FALSE;

return 2;
}
return 2;
return 1;
}

//=============================================================================
Expand Down
32 changes: 32 additions & 0 deletions Core/Libraries/Include/Lib/PathUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,38 @@
#include "BaseType.h"
#include <string.h>

inline bool isPathSeparator(char ch)
{
#ifdef _WIN32
return ch == '\\' || ch == '/';
#else
return ch == '/';
#endif
}

inline bool isAbsolutePath(const char* path)
{
if (path == nullptr)
{
return false;
}

if (isPathSeparator(path[0]))
{
return true;
}

#ifdef _WIN32
const bool hasDriveLetter = (path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z');
if (hasDriveLetter && path[1] == ':' && isPathSeparator(path[2]))
{
return true;
}
#endif

return false;
}

inline const char* getExtension(const char* path)
{
const char* lastDot = strrchr(path, '.');
Expand Down
1 change: 1 addition & 0 deletions Generals/Code/GameEngine/Include/Common/GameState.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class GameState : public SubsystemInterface,

AsciiString getSaveDirectory() const;
AsciiString getFilePathInSaveDirectory(const AsciiString& leaf) const;
AsciiString getSaveGamePathForRead(const AsciiString& filenameOrPath) const;
Bool isInSaveDirectory(const AsciiString& path) const;

AsciiString realMapPathToPortableMapPath(const AsciiString& in) const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "GameClient/GameClient.h"
#include "GameClient/GameText.h"
#include "GameClient/MapUtil.h"
#include "GameClient/MessageBox.h"
#include "GameClient/InGameUI.h"
#include "GameClient/ParticleSys.h"
#include "GameClient/TerrainVisual.h"
Expand All @@ -57,6 +58,7 @@
#include "GameLogic/ScriptEngine.h"
#include "GameLogic/SidesList.h"
#include "GameLogic/TerrainLogic.h"
#include "Lib/PathUtil.h"


// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -656,8 +658,7 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo )
//
TheGameStateMap->clearScratchPadMaps();

// construct path to file
AsciiString filepath = getFilePathInSaveDirectory(gameInfo.filename);
AsciiString filepath = getSaveGamePathForRead(gameInfo.filename);

// open the save file
XferLoad xferLoad;
Expand Down Expand Up @@ -740,6 +741,15 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo )

}

//-------------------------------------------------------------------------------------------------
static void showQueuedSaveGameLoadFailure( void )
{
UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailedTitle", L"CANNOT LOAD SAVE");
UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailed", L"The saved game file could not be opened or is invalid.");

MessageBoxOk(title, body, nullptr);
}

// ------------------------------------------------------------------------------------------------
/** Load the save game requested on startup, after the shell has been initialized */
// ------------------------------------------------------------------------------------------------
Expand All @@ -752,24 +762,30 @@ void GameState::loadQueuedSaveGame()

TheWritableGlobalData->m_loadSaveGame.clear();

if( gameInfo.filename.endsWithNoCase( SAVE_GAME_EXTENSION ) == FALSE )
{
DEBUG_LOG(("Save game '%s' is not a save game file", gameInfo.filename.str()));
showQueuedSaveGameLoadFailure();
return;
}

// getSaveGameInfoFromFile throws when the file is missing, so check before reading it
if( doesSaveGameExist( gameInfo.filename ) == FALSE )
{
DEBUG_LOG(("Save game '%s' was not found", gameInfo.filename.str()));
TheGameEngine->setQuitting( TRUE );
showQueuedSaveGameLoadFailure();
return;
}

// getSaveGameInfoFromFile throws on a malformed file instead of returning a SaveCode
try
{
AsciiString filepath = getFilePathInSaveDirectory( gameInfo.filename );
getSaveGameInfoFromFile( filepath, &gameInfo.saveGameInfo );
getSaveGameInfoFromFile( gameInfo.filename, &gameInfo.saveGameInfo );
}
catch( ... )
{
DEBUG_LOG(("Save game '%s' could not be read", gameInfo.filename.str()));
TheGameEngine->setQuitting( TRUE );
showQueuedSaveGameLoadFailure();
return;
}

Expand Down Expand Up @@ -802,6 +818,17 @@ AsciiString GameState::getFilePathInSaveDirectory(const AsciiString& leaf) const
return tmp;
}

//-------------------------------------------------------------------------------------------------
AsciiString GameState::getSaveGamePathForRead(const AsciiString& filenameOrPath) const
{
if (isAbsolutePath(filenameOrPath.str()))
{
return filenameOrPath;
}

return getFilePathInSaveDirectory(filenameOrPath);
}

//-------------------------------------------------------------------------------------------------
Bool GameState::isInSaveDirectory(const AsciiString& path) const
{
Expand Down Expand Up @@ -959,8 +986,7 @@ AsciiString GameState::portableMapPathToRealMapPath(const AsciiString& in) const
Bool GameState::doesSaveGameExist( AsciiString filename )
{

// construct full path to file
AsciiString filepath = getFilePathInSaveDirectory(filename);
AsciiString filepath = getSaveGamePathForRead(filename);

// open file
XferLoad xfer;
Expand Down Expand Up @@ -1005,6 +1031,8 @@ void GameState::getSaveGameInfoFromFile( AsciiString filename, SaveGameInfo *sav

}

filename = getSaveGamePathForRead( filename );

// open file for partial loading
XferLoad xferLoad;
xferLoad.open( filename );
Expand Down
1 change: 1 addition & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GameState.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class GameState : public SubsystemInterface,

AsciiString getSaveDirectory() const;
AsciiString getFilePathInSaveDirectory(const AsciiString& leaf) const;
AsciiString getSaveGamePathForRead(const AsciiString& filenameOrPath) const;
Bool isInSaveDirectory(const AsciiString& path) const;

AsciiString realMapPathToPortableMapPath(const AsciiString& in) const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "GameClient/GameClient.h"
#include "GameClient/GameText.h"
#include "GameClient/MapUtil.h"
#include "GameClient/MessageBox.h"
#include "GameClient/InGameUI.h"
#include "GameClient/ParticleSys.h"
#include "GameClient/TerrainVisual.h"
Expand All @@ -57,6 +58,7 @@
#include "GameLogic/ScriptEngine.h"
#include "GameLogic/SidesList.h"
#include "GameLogic/TerrainLogic.h"
#include "Lib/PathUtil.h"


// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -656,8 +658,7 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo )
//
TheGameStateMap->clearScratchPadMaps();

// construct path to file
AsciiString filepath = getFilePathInSaveDirectory(gameInfo.filename);
AsciiString filepath = getSaveGamePathForRead(gameInfo.filename);

// open the save file
XferLoad xferLoad;
Expand Down Expand Up @@ -740,6 +741,15 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo )

}

//-------------------------------------------------------------------------------------------------
static void showQueuedSaveGameLoadFailure( void )
{
UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailedTitle", L"CANNOT LOAD SAVE");
UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailed", L"The saved game file could not be opened or is invalid.");

MessageBoxOk(title, body, nullptr);
}

// ------------------------------------------------------------------------------------------------
/** Load the save game requested on startup, after the shell has been initialized */
// ------------------------------------------------------------------------------------------------
Expand All @@ -752,24 +762,30 @@ void GameState::loadQueuedSaveGame()

TheWritableGlobalData->m_loadSaveGame.clear();

if( gameInfo.filename.endsWithNoCase( SAVE_GAME_EXTENSION ) == FALSE )
{
DEBUG_LOG(("Save game '%s' is not a save game file", gameInfo.filename.str()));
showQueuedSaveGameLoadFailure();
return;
}

// getSaveGameInfoFromFile throws when the file is missing, so check before reading it
if( doesSaveGameExist( gameInfo.filename ) == FALSE )
{
DEBUG_LOG(("Save game '%s' was not found", gameInfo.filename.str()));
TheGameEngine->setQuitting( TRUE );
Comment thread
xezon marked this conversation as resolved.
showQueuedSaveGameLoadFailure();
return;
}

// getSaveGameInfoFromFile throws on a malformed file instead of returning a SaveCode
try
{
AsciiString filepath = getFilePathInSaveDirectory( gameInfo.filename );
getSaveGameInfoFromFile( filepath, &gameInfo.saveGameInfo );
getSaveGameInfoFromFile( gameInfo.filename, &gameInfo.saveGameInfo );
}
catch( ... )
{
DEBUG_LOG(("Save game '%s' could not be read", gameInfo.filename.str()));
TheGameEngine->setQuitting( TRUE );
showQueuedSaveGameLoadFailure();
return;
}

Expand Down Expand Up @@ -802,6 +818,17 @@ AsciiString GameState::getFilePathInSaveDirectory(const AsciiString& leaf) const
return tmp;
}

//-------------------------------------------------------------------------------------------------
AsciiString GameState::getSaveGamePathForRead(const AsciiString& filenameOrPath) const
{
if (isAbsolutePath(filenameOrPath.str()))
{
return filenameOrPath;
}

return getFilePathInSaveDirectory(filenameOrPath);
}

//-------------------------------------------------------------------------------------------------
Bool GameState::isInSaveDirectory(const AsciiString& path) const
{
Expand Down Expand Up @@ -959,8 +986,7 @@ AsciiString GameState::portableMapPathToRealMapPath(const AsciiString& in) const
Bool GameState::doesSaveGameExist( AsciiString filename )
{

// construct full path to file
AsciiString filepath = getFilePathInSaveDirectory(filename);
AsciiString filepath = getSaveGamePathForRead(filename);

// open file
XferLoad xfer;
Expand Down Expand Up @@ -1005,6 +1031,8 @@ void GameState::getSaveGameInfoFromFile( AsciiString filename, SaveGameInfo *sav

}

filename = getSaveGamePathForRead( filename );

// open file for partial loading
XferLoad xferLoad;
xferLoad.open( filename );
Expand Down
Loading