Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

1229 lines
43 KiB
C++

// #if __PPU
// #include <cell/rtc.h>
// #endif
// Rage headers
#include "rline/rl.h"
// Game headers
#include "control/replay/file/ReplayFileManager.h"
#include "frontend/PauseMenu.h"
#include "frontend/ProfileSettings.h"
#include "Peds/PlayerInfo.h"
#include "SaveLoad/GenericGameStorage.h"
#include "SaveLoad/savegame_channel.h"
#include "SaveLoad/savegame_initial_checks.h"
#include "SaveLoad/savegame_list.h"
#include "SaveLoad/savegame_messages.h"
#include "SaveLoad/savegame_save.h"
#include "SaveLoad/savegame_users_and_devices.h"
#include "script/script.h"
#include "stats/StatsMgr.h"
#include "system/controlMgr.h"
#include "text/TextFile.h"
SAVEGAME_OPTIMISATIONS()
eGenericSaveState CSavegameSave::ms_GenericSaveStatus = GENERIC_SAVE_DO_NOTHING;
char *CSavegameSave::ms_pSaveGameIcon = NULL;
u32 CSavegameSave::ms_SizeOfSaveGameIcon = 0;
s32 CSavegameSave::ms_SlotNumber = -1;
bool CSavegameSave::ms_bAutosave = false;
bool CSavegameSave::ms_bSaveHasJustOccurred = false;
#if RSG_ORBIS
bool CSavegameSave::ms_bAllowBackupSave = false;
bool CSavegameSave::ms_bSavingABackupOnly = false;
bool CSavegameSave::ms_savingBackupSave = false;
#endif
#if RSG_PC
char CSavegameSave::ms_CloudSaveMetadataString[cMaxLengthOfCloudSaveMetadataString];
#endif // RSG_PC
eTypeOfSavegame CSavegameSave::ms_SaveGameType = SAVEGAME_SINGLE_PLAYER;
const u32 disableInputsDurationForAutoSave = 750;
void CSavegameSave::Init(unsigned initMode)
{
if(initMode == INIT_CORE)
{
ms_pSaveGameIcon = NULL;
ms_SizeOfSaveGameIcon = 0;
FileHandle fIdThumbNail = CFileMgr::OpenFile("platform:/DATA/icon.PNG");
Assert(CFileMgr::IsValidFileHandle(fIdThumbNail) );
if (CFileMgr::IsValidFileHandle(fIdThumbNail))
{
u32 size = CFileMgr::GetTotalSize(fIdThumbNail);
ms_pSaveGameIcon = rage_new char[size];
Assertf(ms_pSaveGameIcon, "Failed to allocate memory for savegame icon");
ms_SizeOfSaveGameIcon = size;
if (ms_pSaveGameIcon)
{
CFileMgr::Read(fIdThumbNail, ms_pSaveGameIcon, ms_SizeOfSaveGameIcon);
SAVEGAME.SetIcon(ms_pSaveGameIcon, ms_SizeOfSaveGameIcon);
}
CFileMgr::CloseFile(fIdThumbNail);
}
// #if __PPU
// we need to init / set the icon for saved content, for bug 561 (GTA E1 PS3 database)
// If the player fires up the ELC disc for the first time but exits back to XMB before selecting an episode
// the profile is saved with a broken icon. This fix ensures that the icon is set to the ELC icon by default.
// InitDefaultIcon();
// #endif
}
else if(initMode == INIT_AFTER_MAP_LOADED)
{
ms_GenericSaveStatus = GENERIC_SAVE_DO_NOTHING;
ms_bSaveHasJustOccurred = false;
}
}
void CSavegameSave::Shutdown(unsigned shutdownMode)
{
if(shutdownMode == SHUTDOWN_CORE)
{
if (ms_pSaveGameIcon)
{
delete[] ms_pSaveGameIcon;
ms_pSaveGameIcon = NULL;
}
ms_SizeOfSaveGameIcon = 0;
}
else if(shutdownMode == SHUTDOWN_WITH_MAP_LOADED)
{
}
}
MemoryCardError CSavegameSave::BeginGameSave(int SlotNumber, eTypeOfSavegame savegameType)
{
if ( (SlotNumber < 0) && (!CPauseMenu::GetMenuPreference(PREF_AUTOSAVE)) )
{ // autosave has been disabled so return immediately
return MEM_CARD_COMPLETE;
}
if (!savegameVerifyf(CGenericGameStorage::GetSaveOperation() == OPERATION_NONE, "CSavegameSave::BeginGameSave - operation is not OPERATION_NONE"))
{
return MEM_CARD_ERROR;
}
Assertf(ms_GenericSaveStatus == GENERIC_SAVE_DO_NOTHING, "CSavegameSave::BeginGameSave - ");
if (ms_GenericSaveStatus == GENERIC_SAVE_DO_NOTHING)
{
ms_SaveGameType = savegameType;
#if RSG_ORBIS
ms_bAllowBackupSave = false;
ms_bSavingABackupOnly = false;
#endif // RSG_ORBIS
ms_SlotNumber = SlotNumber;
ms_bAutosave = false;
if (SlotNumber < 0)
{
savegameAssertf( (ms_SaveGameType == SAVEGAME_SINGLE_PLAYER), "CSavegameSave::BeginGameSave - savegameType should be SINGLE_PLAYER for an autosave");
#if RSG_ORBIS
CSavegameList::SetSlotToUpdateOnceSaveHasCompleted(CSavegameList::GetAutosaveSlotNumberForCurrentEpisode());
#if !USE_SAVE_DATA_MEMORY || USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
ms_bAllowBackupSave = true; // Allow backup saves for autosaves
#endif // !USE_SAVE_DATA_MEMORY || USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
#endif
ms_SlotNumber = CSavegameList::GetAutosaveSlotNumberForCurrentEpisode();
ms_bAutosave = true;
CGenericGameStorage::SetSaveOperation(OPERATION_AUTOSAVING);
}
else
{
CSavegameFilenames::MakeValidSaveNameForLocalFile(SlotNumber);
#if RSG_ORBIS
// I'm not sure if I need to set this for OPERATION_SAVING_MPSTATS_SAVEGAME_TO_CONSOLE
CSavegameList::SetSlotToUpdateOnceSaveHasCompleted(SlotNumber);
#endif
eSavegameFileType savegameFileType = CSavegameList::FindSavegameFileTypeForThisSlot(SlotNumber);
#if RSG_ORBIS
if (savegameFileType == SG_FILE_TYPE_SAVEGAME)
{ // Don't make backup saves for SG_FILE_TYPE_MISSION_REPEAT or SG_FILE_TYPE_REPLAY
ms_bAllowBackupSave = true;
}
else if (savegameFileType == SG_FILE_TYPE_SAVEGAME_BACKUP)
{
ms_bSavingABackupOnly = true;
ms_bAllowBackupSave = true; // I don't think this is essential when saving only a backup but I might as well set it anyway
}
#endif // RSG_ORBIS
switch (savegameFileType)
{
case SG_FILE_TYPE_MISSION_REPEAT :
savegameAssertf( (ms_SaveGameType == SAVEGAME_SINGLE_PLAYER), "CSavegameSave::BeginGameSave - savegameType should be SINGLE_PLAYER for a repeat save");
CGenericGameStorage::SetSaveOperation(OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE);
break;
#if GTA_REPLAY
case SG_FILE_TYPE_REPLAY :
savegameAssertf( (ms_SaveGameType == SAVEGAME_SINGLE_PLAYER), "CSavegameSave::BeginGameSave - savegameType should be SINGLE_PLAYER for a replay save");
CGenericGameStorage::SetSaveOperation(OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE);
break;
#endif // GTA_REPLAY
#if __ALLOW_LOCAL_MP_STATS_SAVES
case SG_FILE_TYPE_MULTIPLAYER_STATS :
savegameAssertf( (ms_SaveGameType == SAVEGAME_MULTIPLAYER_CHARACTER) || (ms_SaveGameType == SAVEGAME_MULTIPLAYER_COMMON), "CSavegameSave::BeginGameSave - savegameType should be CHARACTER or COMMON for an MP save");
CGenericGameStorage::SetSaveOperation(OPERATION_SAVING_MPSTATS_SAVEGAME_TO_CONSOLE);
break;
#endif // __ALLOW_LOCAL_MP_STATS_SAVES
default :
savegameAssertf( (ms_SaveGameType == SAVEGAME_SINGLE_PLAYER), "CSavegameSave::BeginGameSave - savegameType should be SINGLE_PLAYER for a single player save");
CGenericGameStorage::SetSaveOperation(OPERATION_SAVING_SAVEGAME_TO_CONSOLE);
break;
}
}
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_IF_THIS_IS_AN_AUTOSAVE;
return MEM_CARD_COMPLETE;
}
return MEM_CARD_ERROR;
}
void CSavegameSave::EndGenericSave()
{
ms_GenericSaveStatus = GENERIC_SAVE_DO_NOTHING;
#if __ALLOW_LOCAL_MP_STATS_SAVES
savegameAssertf( (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MPSTATS_SAVEGAME_TO_CONSOLE), "CSavegameSave::EndGenericSave - Operation should be OPERATION_SAVING_SAVEGAME_TO_CONSOLE, OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE, OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE, OPERATION_AUTOSAVING or OPERATION_SAVING_MPSTATS_SAVEGAME_TO_CONSOLE but it's %d", (s32) CGenericGameStorage::GetSaveOperation());
#else // __ALLOW_LOCAL_MP_STATS_SAVES
savegameAssertf( (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING), "CSavegameSave::EndGenericSave - Operation should be OPERATION_SAVING_SAVEGAME_TO_CONSOLE, OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE, OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE or OPERATION_AUTOSAVING but it's %d", (s32) CGenericGameStorage::GetSaveOperation());
#endif // __ALLOW_LOCAL_MP_STATS_SAVES
CGenericGameStorage::SetSaveOperation(OPERATION_NONE);
}
MemoryCardError CSavegameSave::GenericSave(bool bDisplayErrors)
{
bool ReturnSelection = false;
MemoryCardError ReturnValue = MEM_CARD_BUSY;
switch (ms_GenericSaveStatus)
{
case GENERIC_SAVE_DO_NOTHING :
return MEM_CARD_COMPLETE;
case GENERIC_SAVE_CHECK_IF_THIS_IS_AN_AUTOSAVE :
{
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
// If device is valid then just use the autosave slot for the current episode
CSavegameFilenames::MakeValidSaveNameForLocalFile(CSavegameList::GetAutosaveSlotNumberForCurrentEpisode());
}
CSavegameInitialChecks::BeginInitialChecks(false);
ms_GenericSaveStatus = GENERIC_SAVE_INITIAL_CHECKS;
}
// break;
case GENERIC_SAVE_INITIAL_CHECKS :
{
// This gets displayed over the top of dialog messages in autosave so I've commented it out
// Graeme - now that the message has moved to the top-right corner of the screen, I'll try putting this back in
CSavingMessage::BeginDisplaying(CSavingMessage::STORAGE_DEVICE_MESSAGE_SAVING);
MemoryCardError SelectionState = CSavegameInitialChecks::InitialChecks();
if (SelectionState == MEM_CARD_ERROR)
{
if (SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT == CSavegameDialogScreens::GetMostRecentErrorCode())
{
ReturnValue = MEM_CARD_ERROR;
}
else
{
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
ms_GenericSaveStatus = GENERIC_SAVE_AUTOSAVE_FAILED_TIDY_UP;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
}
}
}
else if (SelectionState == MEM_CARD_COMPLETE)
{
#if RSG_ORBIS
if (ms_bSavingABackupOnly)
{
ms_GenericSaveStatus = GENERIC_SAVE_BEGIN_SAVE;
}
else
#endif // RSG_ORBIS
{
ms_GenericSaveStatus = GENERIC_SAVE_CREATE_SAVE_BUFFER;
}
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
// If device is valid then just use the autosave slot for the current episode
CSavegameFilenames::MakeValidSaveNameForLocalFile(CSavegameList::GetAutosaveSlotNumberForCurrentEpisode());
if (CGenericGameStorage::ShouldWeDisplayTheMessageAboutOverwritingTheAutosaveSlot())
{
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_IF_THE_AUTOSAVE_TO_BE_OVERWRITTEN_IS_DAMAGED;
}
else
{
// If the autosave slot is empty, clear this flag now so that the overwrite message
// doesn't appear for the next autosave
CGenericGameStorage::SetFlagForAutosaveOverwriteMessage(false);
}
}
}
}
break;
case GENERIC_SAVE_CHECK_IF_THE_AUTOSAVE_TO_BE_OVERWRITTEN_IS_DAMAGED :
{
const int SlotNumber = CSavegameList::GetAutosaveSlotNumberForCurrentEpisode();
MemoryCardError DamagedAutoSaveResult = MEM_CARD_ERROR;
DamagedAutoSaveResult = CSavegameList::CheckIfSlotIsDamaged(SlotNumber);
switch (DamagedAutoSaveResult)
{
case MEM_CARD_COMPLETE :
if (CSavegameList::GetIsDamaged(SlotNumber))
{ // Don't need to find the name of the save game. The message will just say it is damaged.
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_THAT_PLAYER_WANTS_TO_OVERWRITE_EXISTING_AUTOSAVE;
CControlMgr::GetMainPlayerControl(false).DisableAllInputs(disableInputsDurationForAutoSave, ioValue::DisableOptions(ioValue::DisableOptions::F_ALLOW_SUSTAINED));
}
else
{ // The save game is not damaged so find its name.
ms_GenericSaveStatus = GENERIC_SAVE_FIND_THE_NAME_OF_THE_SLOT_THAT_WILL_BE_OVERWRITTEN_BY_THE_AUTOSAVE;
}
break;
case MEM_CARD_BUSY :
// Don't do anything
break;
case MEM_CARD_ERROR :
if (SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT == CSavegameDialogScreens::GetMostRecentErrorCode())
{
ReturnValue = MEM_CARD_ERROR;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_AUTOSAVE_FAILED_TIDY_UP;
}
break;
}
}
break;
case GENERIC_SAVE_FIND_THE_NAME_OF_THE_SLOT_THAT_WILL_BE_OVERWRITTEN_BY_THE_AUTOSAVE :
{
MemoryCardError FileTimeReadStatus = CSavegameList::GetTimeAndMissionNameFromDisplayName(CSavegameList::GetAutosaveSlotNumberForCurrentEpisode());
switch (FileTimeReadStatus)
{
case MEM_CARD_COMPLETE :
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_THAT_PLAYER_WANTS_TO_OVERWRITE_EXISTING_AUTOSAVE;
CControlMgr::GetMainPlayerControl(false).DisableAllInputs(disableInputsDurationForAutoSave, ioValue::DisableOptions(ioValue::DisableOptions::F_ALLOW_SUSTAINED));
break;
case MEM_CARD_BUSY :
// Don't do anything
break;
case MEM_CARD_ERROR :
if (SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT == CSavegameDialogScreens::GetMostRecentErrorCode())
{
ReturnValue = MEM_CARD_ERROR;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_AUTOSAVE_FAILED_TIDY_UP;
}
break;
}
}
break;
case GENERIC_SAVE_CHECK_THAT_PLAYER_WANTS_TO_OVERWRITE_EXISTING_AUTOSAVE :
if (CSavegameUsers::HasPlayerJustSignedOut())
{
ReturnValue = MEM_CARD_ERROR;
break;
}
#if RSG_DURANGO
if (CLiveManager::SignedInIntoNewProfileAfterSuspendMode())
{
savegameDisplayf("CSavegameSave::GenericSave - player has signed into a new profile so cancel this save (1)");
ReturnValue = MEM_CARD_ERROR;
break;
}
#endif // RSG_DURANGO
// if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
// {
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
// return MEM_CARD_ERROR;
// }
if (!CGenericGameStorage::ShouldWeDisplayTheMessageAboutOverwritingTheAutosaveSlot())
{ // On PS3, it's possible (though unlikely) that the first autosave happens before the files have been scanned
// and the game will get this far before realising that the autosave slot actually contains a Blank Save.
// The display name of "Blank Save" will only be filled in by the GetTimeOfFileInThisSlot above.
// This can only happen if the game is run with -noautoload, the autosave slot already contains a Blank Save
// and autosave is done before the Load or Save menu is viewed.
ms_GenericSaveStatus = GENERIC_SAVE_CREATE_SAVE_BUFFER;
// Set this to false if the player says they don't mind the autosave slot being overwritten
CGenericGameStorage::SetFlagForAutosaveOverwriteMessage(false);
}
else if (CSavegameDialogScreens::HandleSaveGameDialogBox(SAVE_GAME_DIALOG_OVERWRITE_EXISTING_AUTOSAVE, 0, &ReturnSelection))
{ // Do you want to overwrite the existing save game in the autosave slot?
if (ReturnSelection)
{
ms_GenericSaveStatus = GENERIC_SAVE_CREATE_SAVE_BUFFER;
// Set this to false if the player says they don't mind the autosave slot being overwritten
CGenericGameStorage::SetFlagForAutosaveOverwriteMessage(false);
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_PLAYER_WANTS_TO_SWITCH_OFF_AUTOSAVE;
}
}
break;
case GENERIC_SAVE_CREATE_SAVE_BUFFER :
{
#if RSG_DURANGO
if (CLiveManager::SignedInIntoNewProfileAfterSuspendMode())
{
savegameDisplayf("CSavegameSave::GenericSave - player has signed into a new profile so cancel this save (2)");
ReturnValue = MEM_CARD_ERROR;
break;
}
#endif // RSG_DURANGO
// if (CTheScripts::GetPlayerIsOnAMission())
// { // To fix bug 185794 where the player can start a new mission before the autosave has a chance to start.
// // Will just have to abandon the save here rather than store all the script variables in an "on mission" state
// savegameDebugf1("CSavegameSave::GenericSave - abandoning the save because the player is on a mission\n");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_NONE);
// ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
// break;
// }
CSavingMessage::BeginDisplaying(CSavingMessage::STORAGE_DEVICE_MESSAGE_SAVING);
#if __ALLOW_LOCAL_MP_STATS_SAVES
if (savegameVerifyf( (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MPSTATS_SAVEGAME_TO_CONSOLE), "CSavegameSave::GenericSave - No save game in progress"))
#else // __ALLOW_LOCAL_MP_STATS_SAVES
if (savegameVerifyf( (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_MISSION_REPEAT_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_SAVING_REPLAY_SAVEGAME_TO_CONSOLE)
|| (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING), "CSavegameSave::GenericSave - No save game in progress"))
#endif // __ALLOW_LOCAL_MP_STATS_SAVES
{
MemoryCardError AllocateBufferStatus = CGenericGameStorage::AllocateBuffer(ms_SaveGameType, true);
switch (AllocateBufferStatus)
{
case MEM_CARD_COMPLETE :
ms_GenericSaveStatus = GENERIC_SAVE_FILL_BUFFER;
if (CGenericGameStorage::BeginSaveBlockData(ms_SaveGameType) == false)
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SAVE_BLOCK_DATA_FAILED);
savegameDebugf1("CSavegameSave::GenericSave - BeginSaveBlockData failed for some reason \n");
CGenericGameStorage::EndSaveBlockData(ms_SaveGameType);
ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
}
break;
case MEM_CARD_BUSY :
// Don't do anything - still waiting for memory to be allocated
break;
case MEM_CARD_ERROR :
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_ALLOCATE_MEMORY_FOR_SAVE_FAILED);
ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
break;
}
}
}
break;
case GENERIC_SAVE_FILL_BUFFER:
{
switch (CGenericGameStorage::GetSaveBlockDataStatus(ms_SaveGameType))
{
case SAVEBLOCKDATA_PENDING:
// Don't do anything - still waiting for data to be saved
break;
case SAVEBLOCKDATA_ERROR:
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SAVE_BLOCK_DATA_FAILED);
savegameDebugf1("CSavegameSave::GenericSave - SaveBlockData failed for some reason \n");
CGenericGameStorage::EndSaveBlockData(ms_SaveGameType);
ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
}
break;
case SAVEBLOCKDATA_SUCCESS:
{
ms_GenericSaveStatus = GENERIC_SAVE_BEGIN_SAVE;
CGenericGameStorage::EndSaveBlockData(ms_SaveGameType);
}
break;
default:
FatalAssertf(0, "CSavegameSave::GenericSave - Unexpected return value from CGenericGameStorage::SaveBlockData");
break;
}
}
break;
case GENERIC_SAVE_BEGIN_SAVE :
{
#if RSG_ORBIS
if (TheText.DoesTextLabelExist("SG_BACKUP"))
{
SAVEGAME.SetLocalisedBackupTitleString(TheText.Get("SG_BACKUP"));
}
if (ms_bSavingABackupOnly)
{
ms_savingBackupSave = true;
}
else
{
ms_savingBackupSave = false;
}
#if USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
#if GTA_REPLAY
if (ReplayFileManager::CheckAvailableDiskSpaceForAutoSave())
{
savegameDisplayf("CSavegameSave::GenericSave - save the backup of the autosave to download0 before the main autosave");
ms_savingBackupSave = true; // Save backup autosave first. Then save the main autosave.
}
else
{
savegameDisplayf("CSavegameSave::GenericSave - ReplayFileManager::CheckAvailableDiskSpaceForAutoSave() has returned false so skip the saving of the autosave backup to download0. Move on to saving the main autosave");
ms_savingBackupSave = false;
}
#else // GTA_REPLAY
savegameDisplayf("CSavegameSave::GenericSave - save the backup of the autosave to download0 before the main autosave");
ms_savingBackupSave = true; // Save backup autosave first. Then save the main autosave.
#endif // GTA_REPLAY
}
#endif // USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
#endif
#if RSG_DURANGO
if (CLiveManager::SignedInIntoNewProfileAfterSuspendMode())
{
savegameDisplayf("CSavegameSave::GenericSave - player has signed into a new profile so cancel this save (3)");
ReturnValue = MEM_CARD_ERROR;
break;
}
#endif // RSG_DURANGO
ms_GenericSaveStatus = GENERIC_SAVE_DO_SAVE;
}
// deliberately fall through here
case GENERIC_SAVE_DO_SAVE :
{
#if RSG_ORBIS
MemoryCardError SaveResult = DoSave(ms_savingBackupSave);
#else
MemoryCardError SaveResult = DoSave(false);
#endif
switch (SaveResult)
{
case MEM_CARD_COMPLETE :
{
#if USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
if(ms_savingBackupSave)
{
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
savegameDisplayf("CSavegameSave::GenericSave - saving of backup autosave to download0 has completed so move on to saving the main autosave");
ms_savingBackupSave = false;
}
else
{
savegameDisplayf("CSavegameSave::GenericSave - backup save has completed so return MEM_CARD_COMPLETE");
ms_bSaveHasJustOccurred = true; // The script is expected to clear this flag when CommandActivateSaveMenu is called
ReturnValue = MEM_CARD_COMPLETE;
}
}
else
{
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
savegameDisplayf("CSavegameSave::GenericSave - main autosave has completed. The backup autosave to download0 should already have been done so return MEM_CARD_COMPLETE");
ms_bSaveHasJustOccurred = true; // The script is expected to clear this flag when CommandActivateSaveMenu is called
ReturnValue = MEM_CARD_COMPLETE;
}
else if (!ms_bAllowBackupSave)
{
savegameDisplayf("CSavegameSave::GenericSave - main save has completed and no backup save has been requested so return MEM_CARD_COMPLETE");
ms_bSaveHasJustOccurred = true; // The script is expected to clear this flag when CommandActivateSaveMenu is called
ReturnValue = MEM_CARD_COMPLETE;
}
else
{
savegameDisplayf("CSavegameSave::GenericSave - main save has completed so move on to saving the backup autosave");
ms_savingBackupSave = true;
}
}
#else // USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
#if RSG_ORBIS
if(ms_bAllowBackupSave && !ms_savingBackupSave)
{
ms_savingBackupSave = true;
}
else
{
ms_savingBackupSave = false;
if (!ms_bSavingABackupOnly)
{
ms_bSaveHasJustOccurred = true; // The script is expected to clear this flag when CommandActivateSaveMenu is called
}
ReturnValue = MEM_CARD_COMPLETE;
}
#else // RSG_ORBIS
ms_bSaveHasJustOccurred = true; // The script is expected to clear this flag when CommandActivateSaveMenu is called
ReturnValue = MEM_CARD_COMPLETE;
#endif // RSG_ORBIS
#endif // USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
}
break;
case MEM_CARD_BUSY :
// Do nothing - have to wait till it's complete
break;
case MEM_CARD_ERROR :
// Assertf(0, "CSavegameSave::GenericSave - CSavegameSave::DoSave returned an error");
// FreeAllData();
// EndGenericSave();
#if USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
if(ms_savingBackupSave && (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING) )
{ // If saving a backup autosave to download0 fails, don't return an error. Instead we'll move on to saving the main autosave
savegameDisplayf("CSavegameSave::GenericSave - saving of backup autosave to download0 has failed. Move on to saving the main autosave anyway");
CSavegameDialogScreens::ClearSaveGameError();
ms_savingBackupSave = false;
}
else
#endif // USE_DOWNLOAD0_FOR_AUTOSAVE_BACKUP
{
if (SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT == CSavegameDialogScreens::GetMostRecentErrorCode())
{
ReturnValue = MEM_CARD_ERROR;
}
else
{
if (CGenericGameStorage::GetSaveOperation() == OPERATION_AUTOSAVING)
{
ms_GenericSaveStatus = GENERIC_SAVE_AUTOSAVE_FAILED_TIDY_UP;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_HANDLE_ERRORS;
}
}
}
break;
default :
Assertf(0, "CSavegameSave::GenericSave - unexpected return value from CSavegameSave::DoSave");
break;
}
// return SaveResult;
}
break;
case GENERIC_SAVE_HANDLE_ERRORS :
/*
TCRHERE bug 64231
CONFIRM_AUTOSAVE_DISABLE
// Deal with the following cases
// Inform the player why the autosave hasn't happened and give them the option to retry
// sAutosaveDisableReason = NOT_SIGNED_IN;
// player has signed out during this process - can maybe be treated as NOT_SIGNED_IN
// storage device removed
// free space
// If the player doesn't want to retry then call
// CPauseMenu::SetMenuPreference(PREF_AUTOSAVE, false);
// and say that autosave has been turned off in the frontend
*/
if(bDisplayErrors == false)
{
ReturnValue = MEM_CARD_ERROR;
break;
}
CSavingMessage::Clear();
if (CSavegameDialogScreens::HandleSaveGameErrorCode())
{
ReturnValue = MEM_CARD_ERROR;
}
break;
case GENERIC_SAVE_AUTOSAVE_FAILED_TIDY_UP :
{
CSavingMessage::Clear();
CSavegameDialogScreens::ClearSaveGameError();
CGenericGameStorage::FreeBufferContainingContentsOfSavegameFile(ms_SaveGameType);
ms_GenericSaveStatus = GENERIC_SAVE_AUTOSAVE_FAILED;
}
// break; // Fall through
case GENERIC_SAVE_AUTOSAVE_FAILED :
if (CSavegameDialogScreens::HandleSaveGameDialogBox(SAVE_GAME_DIALOG_AUTOSAVE_FAILED_TRY_AGAIN, 0, &ReturnSelection))
{ // Autosave failed. Do you want to retry?
CGenericGameStorage::SetFlagForAutosaveOverwriteMessage(true);
if (ReturnSelection)
{
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_IF_THIS_IS_AN_AUTOSAVE;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_PLAYER_WANTS_TO_SWITCH_OFF_AUTOSAVE;
}
}
break;
case GENERIC_SAVE_CHECK_PLAYER_WANTS_TO_SWITCH_OFF_AUTOSAVE :
if (CSavegameUsers::HasPlayerJustSignedOut())
{
ReturnValue = MEM_CARD_ERROR;
break;
}
// if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
// {
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
// return MEM_CARD_ERROR;
// }
if (CSavegameDialogScreens::HandleSaveGameDialogBox(SAVE_GAME_DIALOG_AUTOSAVE_OFF_ARE_YOU_SURE, 0, &ReturnSelection))
{ // are you sure? Autosaving will be switched off.
CGenericGameStorage::SetFlagForAutosaveOverwriteMessage(true);
if (ReturnSelection)
{
ms_GenericSaveStatus = GENERIC_SAVE_SWITCH_OFF_AUTOSAVE;
}
else
{
ms_GenericSaveStatus = GENERIC_SAVE_CHECK_IF_THIS_IS_AN_AUTOSAVE;
}
}
break;
case GENERIC_SAVE_SWITCH_OFF_AUTOSAVE :
if (CSavegameUsers::HasPlayerJustSignedOut())
{
ReturnValue = MEM_CARD_ERROR;
break;
}
// if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
// {
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
// return MEM_CARD_ERROR;
// }
if (CSavegameDialogScreens::HandleSaveGameDialogBox(SAVE_GAME_DIALOG_AUTOSAVE_SWITCHED_OFF, 0, &ReturnSelection))
{ // single button
// display a message saying autosave has been switched off and can be switched on in the frontend
ReturnValue = MEM_CARD_COMPLETE;
CPauseMenu::SetMenuPreference(PREF_AUTOSAVE, false);
}
break;
}
if (ReturnValue != MEM_CARD_BUSY)
{
if (ReturnValue == MEM_CARD_ERROR)
{
CSavingMessage::Clear();
}
// These Free calls aren't really needed here. They should be called when the Manual/Auto Save QueuedOperation completes.
// CGenericGameStorage::Shutdown(SHUTDOWN_SESSION) is still calling CSavegameSave::GenericSave
// directly. I don't know if that will work at all.
#if RSG_ORBIS
if (!ms_bSavingABackupOnly)
#endif // RSG_ORBIS
{
CGenericGameStorage::FreeBufferContainingContentsOfSavegameFile(ms_SaveGameType);
CGenericGameStorage::FreeAllDataToBeSaved(ms_SaveGameType);
}
EndGenericSave();
if (bDisplayErrors)
{
CSavegameDialogScreens::SetMessageAsProcessing(false);
}
}
return ReturnValue;
}
MemoryCardError CSavegameSave::DoSave(bool ORBIS_ONLY(savingBackupSave))
{
enum eSaveState
{
SAVE_STATE_BEGIN_SAVE,
SAVE_STATE_CHECK_SAVE,
#if RSG_ORBIS
SAVE_STATE_GET_MODIFIED_TIME,
#endif // RSG_ORBIS
SAVE_STATE_BEGIN_ICON_SAVE,
SAVE_STATE_CHECK_ICON_SAVE,
#if CREATE_BACKUP_SAVES
SAVE_STATE_BEGIN_BACKUP_SAVE,
SAVE_STATE_CHECK_BACKUP_SAVE,
#endif // CREATE_BACKUP_SAVES
};
#if __XENON || __PPU || __WIN32PC || RSG_ORBIS || RSG_DURANGO
static eSaveState SaveState = SAVE_STATE_BEGIN_SAVE;
#if __BANK
char outFilename[CGenericGameStorage::ms_MaxLengthOfPcSaveFileName]; // SAVE_GAME_MAX_FILENAME_LENGTH+8];
FileHandle fileHandle = INVALID_FILE_HANDLE;
#endif // __BANK
switch (SaveState)
{
case SAVE_STATE_BEGIN_SAVE :
if (CSavegameUsers::HasPlayerJustSignedOut())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
return MEM_CARD_ERROR;
}
#if __BANK
if (CGenericGameStorage::ms_bSaveToPC)
{
// ASSET.PushFolder("common:/data");
ASSET.PushFolder(CGenericGameStorage::ms_NameOfPCSaveFolder);
if (strlen(CGenericGameStorage::ms_NameOfPCSaveFile) > 0)
{
strcpy(outFilename, CGenericGameStorage::ms_NameOfPCSaveFile);
}
else
{
strcpy(outFilename, CSavegameFilenames::GetFilenameOfLocalFile());
}
if (CGenericGameStorage::ms_bSaveAsPso)
{
strcat(outFilename, ".pso");
}
else
{
strcat(outFilename, ".xml");
}
fileHandle = CFileMgr::OpenFileForWriting(outFilename);
if (savegameVerifyf(CFileMgr::IsValidFileHandle(fileHandle), "CSavegameSave::DoSave - failed to open savegame file %s on PC for writing. Maybe the folder X:/gta5/build/dev/saves doesn't exist", outFilename))
{
CFileMgr::Write(fileHandle, (const char *) CGenericGameStorage::GetBuffer(ms_SaveGameType), CGenericGameStorage::GetBufferSize(ms_SaveGameType));
CFileMgr::CloseFile(fileHandle);
}
ASSET.PopFolder();
}
#endif // __BANK
#if __BANK
if (!CGenericGameStorage::ms_bSaveToPC || CGenericGameStorage::ms_bSaveToConsoleWhenSavingToPC)
#endif // __BANK
{
if (!SAVEGAME.BeginSave(CSavegameUsers::GetUser(), CGenericGameStorage::GetContentType(), CSavegameFilenames::GetNameToDisplay(),
#if RSG_ORBIS
savingBackupSave ? CSavegameFilenames::GetFilenameOfBackupSaveFile() :
#endif
CSavegameFilenames::GetFilenameOfLocalFile(), CGenericGameStorage::GetBuffer(ms_SaveGameType), CGenericGameStorage::GetBufferSize(ms_SaveGameType), true) ) // bool overwrite, CGameLogic::GetCurrentEpisodeIndex())
{
Assertf(0, "CSavegameSave::DoSave - BeginSave failed");
savegameDebugf1("CSavegameSave::DoSave - BeginSave failed\n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_SAVE_FAILED);
return MEM_CARD_ERROR;
}
SaveState = SAVE_STATE_CHECK_SAVE;
}
#if __BANK
else
{
savegameDisplayf("Finished saving to the PC and the widgets aren't set to save to the console so finish now\n");
SaveState = SAVE_STATE_BEGIN_SAVE;
return MEM_CARD_COMPLETE;
}
#endif // __BANK
// break;
case SAVE_STATE_CHECK_SAVE :
{
bool bOutIsValid = false;
bool bFileExists = false;
#if __XENON
SAVEGAME.UpdateClass();
#endif
if (SAVEGAME.CheckSave(CSavegameUsers::GetUser(), bOutIsValid, bFileExists))
{ // returns true for error or success, false for busy
// GSWTODO - bOutIsValid could be quite useful.
// I think it only returns TRUE if the save was finished successfully.
// So should be false if Memory card is removed half way through saving.
// Assertf(bOutIsValid, "CSavegameSave::DoSave - CheckSave - bOutIsValid is false (whatever that means)");
// Assertf(bFileExists, "CSavegameSave::DoSave - CheckSave - bFileExists is true. Is that good?");
SaveState = SAVE_STATE_BEGIN_SAVE;
SAVEGAME.EndSave(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_SAVE_FAILED1 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_SAVE_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_SAVE_FAILED2 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_SAVE_FAILED2);
return MEM_CARD_ERROR;
}
// #if __PPU
// CSavegameList::UpdateSlotDataAfterSave();
// #endif
#if ENABLE_SINGLE_PLAYER_CLOUD_SAVES
RegisterCloudSaveFile();
#endif // RSG_PC
#if RSG_ORBIS
if (!SAVEGAME.BeginGetFileModifiedTime(CSavegameUsers::GetUser(), savingBackupSave? CSavegameFilenames::GetFilenameOfBackupSaveFile() : CSavegameFilenames::GetFilenameOfLocalFile()))
{
Assertf(0, "CSavegameSave::DoSave - BeginGetFileModifiedTime failed");
savegameDebugf1("CSavegameSave::DoSave - BeginGetFileModifiedTime failed\n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_GET_FILE_MODIFIED_TIME_FAILED);
return MEM_CARD_ERROR;
}
SaveState = SAVE_STATE_GET_MODIFIED_TIME;
#else
SaveState = SAVE_STATE_BEGIN_ICON_SAVE;
#endif // RSG_ORBIS
}
}
break;
#if RSG_ORBIS
case SAVE_STATE_GET_MODIFIED_TIME :
{
// #if __XENON
// SAVEGAME.UpdateClass();
// #endif
u32 ModifiedTimeHigh = 0;
u32 ModifiedTimeLow = 0;
if (SAVEGAME.CheckGetFileModifiedTime(CSavegameUsers::GetUser(), ModifiedTimeHigh, ModifiedTimeLow))
{ // returns true for error or success, false for busy
SaveState = SAVE_STATE_BEGIN_SAVE;
SAVEGAME.EndGetFileModifiedTime(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED1 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED2 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED2);
return MEM_CARD_ERROR;
}
CSavegameList::UpdateSlotDataAfterSave(ModifiedTimeHigh, ModifiedTimeLow, savingBackupSave);
SaveState = SAVE_STATE_BEGIN_ICON_SAVE;
}
}
break;
#endif // RSG_ORBIS
case SAVE_STATE_BEGIN_ICON_SAVE :
if (ms_pSaveGameIcon)
{
if (!SAVEGAME.BeginIconSave(CSavegameUsers::GetUser(), CGenericGameStorage::GetContentType(),
#if RSG_ORBIS
savingBackupSave? CSavegameFilenames::GetFilenameOfBackupSaveFile() :
#endif
CSavegameFilenames::GetFilenameOfLocalFile(), static_cast<const void *>(ms_pSaveGameIcon), ms_SizeOfSaveGameIcon))
{
SaveState = SAVE_STATE_BEGIN_SAVE;
Assertf(0, "CSavegameSave::DoSave - BeginIconSave failed");
savegameDebugf1("CSavegameSave::DoSave - BeginIconSave failed\n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_ICON_SAVE_FAILED);
return MEM_CARD_ERROR;
}
SaveState = SAVE_STATE_CHECK_ICON_SAVE;
}
else
{
#if CREATE_BACKUP_SAVES
SaveState = SAVE_STATE_BEGIN_BACKUP_SAVE;
#else //CREATE_BACKUP_SAVES
SaveState = SAVE_STATE_BEGIN_SAVE; // Save completed
return MEM_CARD_COMPLETE;
#endif //CREATE_BACKUP_SAVES
}
break;
case SAVE_STATE_CHECK_ICON_SAVE :
#if __XENON
SAVEGAME.UpdateClass();
#endif
if (SAVEGAME.CheckIconSave(CSavegameUsers::GetUser()))
{ // returns true for error or success, false for busy
SaveState = SAVE_STATE_BEGIN_SAVE;
SAVEGAME.EndIconSave(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (CSavegameDevices::HasSelectedDeviceJustBeenRemoved())
{
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_SELECTED_DEVICE_HAS_BEEN_REMOVED);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED1 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameDebugf1("CSavegameSave::DoSave - SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED2 \n");
CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED2);
return MEM_CARD_ERROR;
}
#if CREATE_BACKUP_SAVES
SaveState = SAVE_STATE_BEGIN_BACKUP_SAVE;
#else //CREATE_BACKUP_SAVES
SaveState = SAVE_STATE_BEGIN_SAVE;
return MEM_CARD_COMPLETE;
#endif //CREATE_BACKUP_SAVES
}
break;
#if CREATE_BACKUP_SAVES
case SAVE_STATE_BEGIN_BACKUP_SAVE:
{
if (!SAVEGAME.BeginBackupSave(CSavegameUsers::GetUser(), CGenericGameStorage::GetContentType(), CSavegameFilenames::GetNameToDisplay(), CSavegameFilenames::GetFilenameOfLocalFile(), CGenericGameStorage::GetBuffer(ms_SaveGameType), CGenericGameStorage::GetBufferSize(ms_SaveGameType), true) ) // bool overwrite, CGameLogic::GetCurrentEpisodeIndex())
{
// What to do if the backup fails......
SaveState = SAVE_STATE_BEGIN_SAVE;
return MEM_CARD_COMPLETE; // Say it's complete even if our backup hasn't saved correctly, if we got this far, we must have saved the original save OK.
}
SaveState = SAVE_STATE_CHECK_BACKUP_SAVE;
}
break;
case SAVE_STATE_CHECK_BACKUP_SAVE:
{
bool bOutIsValid = false;
bool bFileExists = false;
if (SAVEGAME.CheckBackupSave(CSavegameUsers::GetUser(), bOutIsValid, bFileExists))
{ // returns true for error or success, false for busy
SaveState = SAVE_STATE_BEGIN_SAVE;
SAVEGAME.EndBackupSave(CSavegameUsers::GetUser());
return MEM_CARD_COMPLETE;
}
}
break;
#endif //CREATE_BACKUP_SAVES
}
#else // #if __XENON || __PPU || __WIN32PC || RSG_DURANGO
Assertf(0, "CSavegameSave::DoSave - save game only implemented for 360, PS3, PC, Orbis and Durango so far");
#endif
return MEM_CARD_BUSY;
}
#if ENABLE_SINGLE_PLAYER_CLOUD_SAVES
void CSavegameSave::RegisterCloudSaveFile()
{
// Only register SAVEGAME type for saves.
eSavegameFileType savegameFileType = CSavegameList::FindSavegameFileTypeForThisSlot(ms_SlotNumber);
if (savegameFileType != SG_FILE_TYPE_SAVEGAME)
{
savegameDebugf1("Not registering cloud save file, type %d is not SG_FILE_TYPE_SAVEGAME.", savegameFileType);
return;
}
memset(ms_CloudSaveMetadataString, 0, NELEM(ms_CloudSaveMetadataString));
RsonWriter rsonWriter(ms_CloudSaveMetadataString, NELEM(ms_CloudSaveMetadataString), RSON_FORMAT_JSON);
rsonWriter.Reset();
bool bSuccess = rsonWriter.Begin(NULL, NULL); // Top-level structure to contain all the rest of the data
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - rsonWriter.Begin failed");
if (bSuccess)
{
bSuccess = rsonWriter.WriteInt("Autosave", ms_bAutosave ? 1 : 0);
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write Autosave field");
}
if (bSuccess)
{
bSuccess = rsonWriter.WriteInt("Slot", ms_SlotNumber);
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write Slot field");
}
if (bSuccess)
{ // UTF8 localized string. Should I store the text key instead?
bSuccess = rsonWriter.WriteString("LastMission", CSavegameFilenames::GetNameOfLastMissionPassed());
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write LastMission field");
}
if (bSuccess)
{
bSuccess = rsonWriter.WriteFloat("CompletionPct", CSavegameFilenames::GetMissionCompletionPercentage());
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write completionPct field");
}
if (bSuccess)
{
u64 posixTime64 = rlGetPosixTime();
// savegameAssertf( (posixTime >> 32) == 0, "CSavegameSave::RegisterCloudSaveFile - expected the top 32 bits of the current POSIX time to be 0");
// u32 posixTime32 = (u32) (posixTime & 0xffffffff);
bSuccess = rsonWriter.WriteUns64("PosixTime", posixTime64);
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write PosixTime field");
}
if (bSuccess)
{ // 0 = Michael, 1 = Franklin, 2 = Trevor, -1 = something went wrong
s32 playerCharacterIndex = -1;
CPed* pPlayerPed = FindPlayerPed();
if(pPlayerPed != NULL)
{
playerCharacterIndex = CPlayerInfo::GetPlayerIndex(*pPlayerPed);
}
bSuccess = rsonWriter.WriteInt("PlayerCharacterIndex", playerCharacterIndex);
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - failed to write playerCharacterIndex field");
}
if (bSuccess)
{
bSuccess = rsonWriter.End(); // Close the top-level structure
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - rsonWriter.End failed");
}
// Data that is still to be added -
// 1. Last map area - is this necessary?
// Uncomment the following block when RegisterSinglePlayerCloudSaveFile() is ready to use
if (bSuccess)
{
bSuccess = CLiveManager::RegisterSinglePlayerCloudSaveFile(CSavegameFilenames::GetFilenameOfLocalFile(), ms_CloudSaveMetadataString);
savegameAssertf(bSuccess, "CSavegameSave::RegisterCloudSaveFile - RegisterSinglePlayerCloudSaveFile failed");
}
}
#endif // ENABLE_SINGLE_PLAYER_CLOUD_SAVES