Files
GTASource/game/SaveLoad/SavegameMigration/savegame_import.cpp
T
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

982 lines
32 KiB
C++

#include "savegame_import.h"
#if __ALLOW_IMPORT_OF_SP_SAVEGAMES
// Rage headers
#include "zlib/lz4.h"
// Framework headers
#include "fwsys/gameskeleton.h"
// Game headers
#include "SaveLoad/GenericGameStorage.h"
#include "SaveLoad/savegame_channel.h"
#include "SaveLoad/savegame_frontend.h"
#include "SaveLoad/savegame_initial_checks.h"
#include "SaveLoad/savegame_save.h"
#include "SaveLoad/savegame_users_and_devices.h"
#include "SaveLoad/SavegameScriptData/script_save_data.h"
const u32 s_MaxBufferSize_LoadedXmlData_Compressed = 220000; // This might need to be increased
CSaveGameMigrationBuffer CSaveGameImport::sm_BufferContainingLoadedXmlData_Compressed(s_MaxBufferSize_LoadedXmlData_Compressed);
const u32 s_MaxBufferSize_LoadedXmlData_Uncompressed = 2500000; // This might need to be increased
CSaveGameMigrationBuffer CSaveGameImport::sm_BufferContainingLoadedXmlData_Uncompressed(s_MaxBufferSize_LoadedXmlData_Uncompressed);
const u32 s_MaxBufferSize_SavedPsoData = 640000;
CSaveGameMigrationBuffer CSaveGameImport::sm_BufferContainingPsoDataForSaving(s_MaxBufferSize_SavedPsoData);
CSaveGameMigrationData_Code CSaveGameImport::sm_SaveGameBufferContents_Code;
CSaveGameMigrationData_Script CSaveGameImport::sm_SaveGameBufferContents_Script;
psoBuilder *CSaveGameImport::m_pPsoBuilderToBeSaved = NULL;
CSaveGameImport::SaveBlockDataForImportStatus CSaveGameImport::sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_IDLE;
CSaveGameImport::eSaveGameImportProgress CSaveGameImport::sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_GET_SIZE_OF_XML_FILE;
bool CSaveGameImport::sm_bIsImporting = false;
const char *CSaveGameImport::sm_XMLTextDirectoryName = "X:\\";
const char *CSaveGameImport::sm_XMLTextFilename = "exported_savegame_compressed.xml";
void CSaveGameImport::Init(unsigned UNUSED_PARAM(initMode))
{
m_pPsoBuilderToBeSaved = NULL;
sm_bIsImporting = false;
sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_IDLE;
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_GET_SIZE_OF_XML_FILE;
}
void CSaveGameImport::Shutdown(unsigned shutdownMode)
{
if (shutdownMode == SHUTDOWN_SESSION)
{
FreeAllData();
}
}
bool CSaveGameImport::BeginImport()
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_GET_SIZE_OF_XML_FILE;
return true;
}
bool CSaveGameImport::BeginImportOfDownloadedData()
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_DECOMPRESS_XML_DATA;
return true;
}
bool CSaveGameImport::CreateCopyOfDownloadedData(const u8 *pData, u32 dataSize)
{
sm_BufferContainingLoadedXmlData_Compressed.SetBufferSize(dataSize);
if (sm_BufferContainingLoadedXmlData_Compressed.AllocateBuffer() == MEM_CARD_COMPLETE)
{
memcpy(sm_BufferContainingLoadedXmlData_Compressed.GetBuffer(), pData, dataSize);
return true;
}
savegameErrorf("CSaveGameImport::CreateCopyOfDownloadedData - failed to allocate %u bytes for copy of data", dataSize);
savegameAssertf(0, "CSaveGameImport::CreateCopyOfDownloadedData - failed to allocate %u bytes for copy of data", dataSize);
return false;
}
MemoryCardError CSaveGameImport::UpdateImport()
{
MemoryCardError returnValue = MEM_CARD_BUSY;
switch (sm_SaveGameImportProgress)
{
case SAVEGAME_IMPORT_PROGRESS_GET_SIZE_OF_XML_FILE :
{
// Eventually the exported data will be downloaded from the cloud
// For now, read it from a text file on the PC.
if (GetSizeOfXmlFile())
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_ALLOCATE_COMPRESSED_BUFFER_FOR_XML_DATA;
}
else
{
returnValue = MEM_CARD_ERROR;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_ALLOCATE_COMPRESSED_BUFFER_FOR_XML_DATA :
{
switch (sm_BufferContainingLoadedXmlData_Compressed.AllocateBuffer())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_READ_XML_DATA_FROM_FILE;
break;
case MEM_CARD_BUSY :
savegameDebugf1("CSaveGameImport::UpdateImport - waiting for sm_BufferContainingLoadedXmlData_Compressed.AllocateBuffer() to succeed");
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - sm_BufferContainingLoadedXmlData_Compressed.AllocateBuffer() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_READ_XML_DATA_FROM_FILE :
{
if (ReadXmlDataFromFile())
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_DECOMPRESS_XML_DATA;
}
else
{
returnValue = MEM_CARD_ERROR;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_DECOMPRESS_XML_DATA :
{
if (DecompressLoadedXmlData())
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_READ_XML_DATA_FROM_BUFFER;
}
else
{
returnValue = MEM_CARD_ERROR;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_READ_XML_DATA_FROM_BUFFER :
{
if (ReadXmlDataFromBuffer())
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_CREATE_PSO_SAVE_DATA;
}
else
{
returnValue = MEM_CARD_ERROR;
}
// The loaded XML buffer is not needed after this, so free it now
sm_BufferContainingLoadedXmlData_Compressed.FreeBuffer();
sm_BufferContainingLoadedXmlData_Uncompressed.FreeBuffer();
}
break;
case SAVEGAME_IMPORT_PROGRESS_CREATE_PSO_SAVE_DATA :
{
switch (CreateSaveDataAndCalculateSize())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_ALLOCATE_SAVE_BUFFER;
break;
case MEM_CARD_BUSY :
savegameErrorf("CSaveGameImport::UpdateImport - didn't expect CreateSaveDataAndCalculateSize() to ever return MEM_CARD_BUSY");
returnValue = MEM_CARD_ERROR;
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - CreateSaveDataAndCalculateSize() returned MEM_CARD_ERROR");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_ALLOCATE_SAVE_BUFFER :
{
switch (sm_BufferContainingPsoDataForSaving.AllocateBuffer())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_WRITING_TO_SAVE_BUFFER;
break;
case MEM_CARD_BUSY :
savegameDebugf1("CSaveGameImport::UpdateImport - waiting for sm_BufferContainingPsoDataForSaving.AllocateBuffer() to succeed");
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - sm_BufferContainingPsoDataForSaving.AllocateBuffer() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_BEGIN_WRITING_TO_SAVE_BUFFER :
{
if (BeginSaveBlockData())
{
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_CHECK_WRITING_TO_SAVE_BUFFER;
}
else
{
savegameErrorf("CSaveGameImport::UpdateImport - BeginSaveBlockData() failed");
EndSaveBlockData();
returnValue = MEM_CARD_ERROR;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_CHECK_WRITING_TO_SAVE_BUFFER :
{
switch (sm_SaveBlockDataForImportStatus)
{
case SAVEBLOCKDATAFORIMPORT_IDLE :
savegameErrorf("CSaveGameImport::UpdateImport - didn't expect status to be IDLE during the writing of the save buffer");
EndSaveBlockData();
returnValue = MEM_CARD_ERROR;
break;
case SAVEBLOCKDATAFORIMPORT_PENDING :
// Don't do anything - still waiting for the data to finish being written
break;
case SAVEBLOCKDATAFORIMPORT_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - status has been set to ERROR while writing the save buffer");
EndSaveBlockData();
returnValue = MEM_CARD_ERROR;
break;
case SAVEBLOCKDATAFORIMPORT_SUCCESS :
savegameDebugf1("CSaveGameImport::UpdateImport - writing of the save buffer has succeeded");
EndSaveBlockData();
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_INITIAL_CHECKS;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_BEGIN_INITIAL_CHECKS :
{
switch (BeginInitialChecks())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_INITIAL_CHECKS;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - BeginInitialChecks() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_INITIAL_CHECKS :
{
switch (InitialChecks())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_SAVE;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - InitialChecks() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_BEGIN_SAVE :
{
switch (BeginSave())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_CHECK_SAVE;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - BeginSave() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_CHECK_SAVE :
{
switch (CSaveGameImport::CheckSave())
{
case MEM_CARD_COMPLETE :
#if RSG_ORBIS
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_GET_MODIFIED_TIME;
#else
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_ICON_SAVE;
#endif // RSG_ORBIS
break;
case MEM_CARD_BUSY : // the save is still in progress
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - CheckSave() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
#if RSG_ORBIS
case SAVEGAME_IMPORT_PROGRESS_BEGIN_GET_MODIFIED_TIME :
{
switch (CSaveGameImport::BeginGetModifiedTime())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_GET_MODIFIED_TIME;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - BeginGetModifiedTime() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_GET_MODIFIED_TIME :
{
switch (GetModifiedTime())
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_BEGIN_ICON_SAVE;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - GetModifiedTime() failed");
returnValue = MEM_CARD_ERROR;
break;
}
}
break;
#endif // RSG_ORBIS
case SAVEGAME_IMPORT_PROGRESS_BEGIN_ICON_SAVE :
{
char *pSaveGameIcon = CSavegameSave::GetSaveGameIcon();
u32 sizeOfSaveGameIcon = CSavegameSave::GetSizeOfSaveGameIcon();
if (pSaveGameIcon)
{
switch (BeginIconSave(pSaveGameIcon, sizeOfSaveGameIcon))
{
case MEM_CARD_COMPLETE :
sm_SaveGameImportProgress = SAVEGAME_IMPORT_PROGRESS_CHECK_ICON_SAVE;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - BeginIconSave() failed");
// savegameAssertf(0, "CSaveGameImport::UpdateImport - BeginIconSave() failed");
returnValue = MEM_CARD_COMPLETE; // Saving the icon isn't essential so set MEM_CARD_COMPLETE instead of MEM_CARD_ERROR
break;
}
}
else
{
savegameErrorf("CSaveGameImport::UpdateImport - failed to get savegame icon");
savegameAssertf(0, "CSaveGameImport::UpdateImport - failed to get savegame icon");
returnValue = MEM_CARD_COMPLETE; // Saving the icon isn't essential so set MEM_CARD_COMPLETE instead of MEM_CARD_ERROR
}
}
break;
case SAVEGAME_IMPORT_PROGRESS_CHECK_ICON_SAVE :
{
switch (CheckIconSave())
{
case MEM_CARD_COMPLETE :
returnValue = MEM_CARD_COMPLETE;
break;
case MEM_CARD_BUSY :
break;
case MEM_CARD_ERROR :
savegameErrorf("CSaveGameImport::UpdateImport - CheckIconSave() failed");
// savegameAssertf(0, "CSaveGameImport::UpdateImport - CheckIconSave() failed");
returnValue = MEM_CARD_COMPLETE; // Saving the icon isn't essential so set MEM_CARD_COMPLETE instead of MEM_CARD_ERROR
break;
}
}
break;
}
if ( (returnValue == MEM_CARD_COMPLETE) || (returnValue == MEM_CARD_ERROR) )
{
FreeAllData();
// I think I might need to call this because I will probably have set it to OPERATION_SAVING_SAVEGAME_TO_CONSOLE
CGenericGameStorage::SetSaveOperation(OPERATION_NONE);
// Do this too?
CSavingMessage::Clear();
}
return returnValue;
}
void CSaveGameImport::FreeAllData()
{
sm_BufferContainingLoadedXmlData_Compressed.FreeBuffer();
sm_BufferContainingLoadedXmlData_Uncompressed.FreeBuffer();
sm_BufferContainingPsoDataForSaving.FreeBuffer();
sm_SaveGameBufferContents_Code.Delete();
sm_SaveGameBufferContents_Script.Delete();
delete m_pPsoBuilderToBeSaved;
m_pPsoBuilderToBeSaved = NULL;
}
bool CSaveGameImport::GetSizeOfXmlFile()
{
bool bReturnValue = false;
ASSET.PushFolder(sm_XMLTextDirectoryName);
FileHandle fileHandle = CFileMgr::OpenFile(sm_XMLTextFilename);
if (savegameVerifyf(CFileMgr::IsValidFileHandle(fileHandle), "CSaveGameImport::GetSizeOfXmlFile - failed to open text file %s on PC", sm_XMLTextFilename))
{
s32 fileSize = CFileMgr::GetTotalSize(fileHandle);
if (savegameVerifyf(fileSize > 0, "CSaveGameImport::GetSizeOfXmlFile - fileSize is %d", fileSize))
{
sm_BufferContainingLoadedXmlData_Compressed.SetBufferSize(fileSize);
bReturnValue = true;
}
CFileMgr::CloseFile(fileHandle);
}
ASSET.PopFolder();
return bReturnValue;
}
bool CSaveGameImport::ReadXmlDataFromFile()
{
bool bReturnValue = false;
ASSET.PushFolder(sm_XMLTextDirectoryName);
FileHandle fileHandle = CFileMgr::OpenFile(sm_XMLTextFilename);
if (savegameVerifyf(CFileMgr::IsValidFileHandle(fileHandle), "CSaveGameImport::ReadXmlDataFromFile - failed to open text file %s on PC", sm_XMLTextFilename))
{
s32 amountRead = CFileMgr::Read(fileHandle, (char*) sm_BufferContainingLoadedXmlData_Compressed.GetBuffer(), sm_BufferContainingLoadedXmlData_Compressed.GetBufferSize());
if (amountRead == (s32)sm_BufferContainingLoadedXmlData_Compressed.GetBufferSize())
{
bReturnValue = true;
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromFile - read %d bytes, expected to read %u bytes", amountRead, sm_BufferContainingLoadedXmlData_Compressed.GetBufferSize());
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromFile - read %d bytes, expected to read %u bytes", amountRead, sm_BufferContainingLoadedXmlData_Compressed.GetBufferSize());
}
CFileMgr::CloseFile(fileHandle);
}
ASSET.PopFolder();
return bReturnValue;
}
bool CSaveGameImport::DecompressLoadedXmlData()
{
// Decrypt the buffer
AES aes(AES_KEY_ID_GTA5SAVE_MIGRATION);
aes.Decrypt(sm_BufferContainingLoadedXmlData_Compressed.GetBuffer(), sm_BufferContainingLoadedXmlData_Compressed.GetBufferSize());
const char *pHeaderId = "COMP";
const u32 sizeOfHeaderId = 4;
const u32 sizeOfHeaderFieldContainingUncompressedSize = 4;
const u32 sizeOfHeader = (sizeOfHeaderId + sizeOfHeaderFieldContainingUncompressedSize);
u8 *pCompressedBuffer = sm_BufferContainingLoadedXmlData_Compressed.GetBuffer();
if (strncmp((reinterpret_cast<const char*>(pCompressedBuffer)), pHeaderId, sizeOfHeaderId) == 0)
{
// Get the size of the uncompressed buffer
u32 sourceSizeL = 0;
memcpy(&sourceSizeL, pCompressedBuffer + sizeOfHeaderId, sizeOfHeaderFieldContainingUncompressedSize);
u32 uncompressedSize = sysEndian::LtoN(sourceSizeL);
sm_BufferContainingLoadedXmlData_Uncompressed.SetBufferSize(uncompressedSize);
if (sm_BufferContainingLoadedXmlData_Uncompressed.AllocateBuffer() != MEM_CARD_COMPLETE)
{
savegameErrorf("CSaveGameImport::DecompressLoadedXmlData - failed to allocate memory for uncompressed buffer");
savegameAssertf(0, "CSaveGameImport::DecompressLoadedXmlData - failed to allocate memory for uncompressed buffer");
return false;
}
int returnValue = LZ4_decompress_fast((const char*) pCompressedBuffer + sizeOfHeader,
(char*) sm_BufferContainingLoadedXmlData_Uncompressed.GetBuffer(),
sm_BufferContainingLoadedXmlData_Uncompressed.GetBufferSize());
if(returnValue <= 0)
{
savegameErrorf("CSaveGameImport::DecompressLoadedXmlData - LZ4_decompress_fast failed");
savegameAssertf(0, "CSaveGameImport::DecompressLoadedXmlData - LZ4_decompress_fast failed");
return false;
}
}
else
{
savegameErrorf("CSaveGameImport::DecompressLoadedXmlData - expected the first four bytes of the compressed buffer to contain '%s'", pHeaderId);
savegameAssertf(0, "CSaveGameImport::DecompressLoadedXmlData - expected the first four bytes of the compressed buffer to contain '%s'", pHeaderId);
return false;
}
return true;
}
bool CSaveGameImport::ReadXmlDataFromBuffer()
{
bool bReturnValue = false;
u8* buffer = sm_BufferContainingLoadedXmlData_Uncompressed.GetBuffer();
u32 bufferSize = sm_BufferContainingLoadedXmlData_Uncompressed.GetBufferSize();
char memFileName[RAGE_MAX_PATH];
fiDevice::MakeMemoryFileName(memFileName, RAGE_MAX_PATH, buffer, bufferSize, false, "");
const int inputFormat = PARSER.FindInputFormat(*(reinterpret_cast<u32*>(buffer)));
if (inputFormat == parManager::XML)
{
fiStream* pReadStream = ASSET.Open(memFileName, "");
{
savegameAssertf(!PARSER.Settings().GetFlag(parSettings::USE_TEMPORARY_HEAP), "CSaveGameImport::ReadXmlDataFromBuffer - Graeme - I'm not dealing with AutoUseTempMemory properly");
parTree *pLoadedParTree = PARSER.LoadTree(pReadStream, NULL);
if (pLoadedParTree)
{
if (pLoadedParTree->GetRoot())
{
if (sm_SaveGameBufferContents_Code.ReadDataFromParTree(pLoadedParTree))
{
if (sm_SaveGameBufferContents_Script.ReadDataFromParTree(pLoadedParTree))
{
bReturnValue = true;
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromBuffer - Failed to read script save data from pLoadedParTree");
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromBuffer - Failed to read script save data from pLoadedParTree");
}
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromBuffer - Failed to read code save data from pLoadedParTree");
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromBuffer - Failed to read code save data from pLoadedParTree");
}
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromBuffer - Failed to find root for parTree loaded from file '%s'", pReadStream->GetName());
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromBuffer - Failed to find root for parTree loaded from file '%s'", pReadStream->GetName());
}
{
parManager::AutoUseTempMemory temp;
delete pLoadedParTree;
pLoadedParTree = NULL;
}
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromBuffer - Couldn't load from file '%s'. File was empty or incorrect format", pReadStream->GetName());
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromBuffer - Couldn't load from file '%s'. File was empty or incorrect format", pReadStream->GetName());
}
}
savegameDebugf2("CSaveGameImport::ReadXmlDataFromBuffer - Done loading from stream '%s'", pReadStream->GetName());
pReadStream->Close();
}
else
{
savegameErrorf("CSaveGameImport::ReadXmlDataFromBuffer - Expected PARSER.FindInputFormat() to be parManager::XML, but it's %d. memFileName='%s'", inputFormat, memFileName);
savegameAssertf(0, "CSaveGameImport::ReadXmlDataFromBuffer - Expected PARSER.FindInputFormat() to be parManager::XML, but it's %d. memFileName='%s'", inputFormat, memFileName);
}
return bReturnValue;
}
#define Align16(x) (((x)+15)&~15)
// Mostly copied from CSaveGameBuffer::CreateSaveDataAndCalculateSize()
MemoryCardError CSaveGameImport::CreateSaveDataAndCalculateSize()
{
if (m_pPsoBuilderToBeSaved)
{
savegameAssertf(0, "CSaveGameImport::CreateSaveDataAndCalculateSize - didn't expect m_pPsoBuilderToBeSaved to be allocated at this stage");
delete m_pPsoBuilderToBeSaved;
m_pPsoBuilderToBeSaved = NULL;
}
m_pPsoBuilderToBeSaved = rage_new psoBuilder;
m_pPsoBuilderToBeSaved->IncludeChecksum();
psoBuilderInstance *pBuilderInstance = sm_SaveGameBufferContents_Code.ConstructPsoDataToSave(m_pPsoBuilderToBeSaved);
CScriptSaveData::AddActiveScriptDataToPsoToBeSaved(SAVEGAME_SINGLE_PLAYER, *m_pPsoBuilderToBeSaved, pBuilderInstance);
m_pPsoBuilderToBeSaved->FinishBuilding();
u32 psoFileSize = m_pPsoBuilderToBeSaved->GetFileSize();
savegameDisplayf("CSaveGameImport::CreateSaveDataAndCalculateSize - Size of PSO Buffer is %u", psoFileSize);
sm_BufferContainingPsoDataForSaving.SetBufferSize(Align16(psoFileSize)); // need alignment for encryption
return MEM_CARD_COMPLETE;
}
void CSaveGameImport::SaveBlockDataForImportThreadFunc(void* )
{
PF_PUSH_MARKER("SaveBlockDataForImport");
bool bSuccess = DoSaveBlockData();
if(bSuccess)
{
sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_SUCCESS;
}
else
{
sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_ERROR;
}
#if !__FINAL
unsigned current, maxi;
if (sysIpcEstimateStackUsage(current,maxi))
savegameDisplayf("Save game thread used %u of %u bytes stack space.",current,maxi);
#endif
PF_POP_MARKER();
}
static sysIpcThreadId s_ImportThreadId = sysIpcThreadIdInvalid;
bool CSaveGameImport::BeginSaveBlockData()
{
if (s_ImportThreadId != sysIpcThreadIdInvalid)
{
Errorf("CSaveGameImport::BeginSaveBlockData started twice. Previous thread not finished, can't start.");
return false;
}
FatalAssertf(sm_SaveBlockDataForImportStatus == SAVEBLOCKDATAFORIMPORT_IDLE, "CSaveGameImport::BeginSaveBlockData called twice");
sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_PENDING;
s_ImportThreadId = sysIpcCreateThread(SaveBlockDataForImportThreadFunc, NULL, 16384, PRIO_BELOW_NORMAL, "SaveBlockDataThread", 0, "SaveBlockDataThread");
return s_ImportThreadId != sysIpcThreadIdInvalid;
}
bool CSaveGameImport::DoSaveBlockData()
{
savegameAssertf(m_pPsoBuilderToBeSaved, "CSaveGameImport::DoSaveBlockData - Couldn't find a PSO builder object to save");
m_pPsoBuilderToBeSaved->SaveToBuffer(reinterpret_cast<char*>(sm_BufferContainingPsoDataForSaving.GetBuffer()), sm_BufferContainingPsoDataForSaving.GetBufferSize());
savegameDisplayf("CSaveGameImport::DoSaveBlockData - size before encryption = %u", sm_BufferContainingPsoDataForSaving.GetBufferSize());
//Now encrypt the buffer
AES aes(AES_KEY_ID_SAVEGAME);
aes.Encrypt(sm_BufferContainingPsoDataForSaving.GetBuffer(), sm_BufferContainingPsoDataForSaving.GetBufferSize());
savegameDisplayf("CSaveGameImport::DoSaveBlockData - size after encryption = %u", sm_BufferContainingPsoDataForSaving.GetBufferSize());
return true;
}
void CSaveGameImport::EndSaveBlockData()
{
if (s_ImportThreadId != sysIpcThreadIdInvalid)
{
sysIpcWaitThreadExit(s_ImportThreadId);
s_ImportThreadId = sysIpcThreadIdInvalid;
}
sm_SaveBlockDataForImportStatus = SAVEBLOCKDATAFORIMPORT_IDLE;
}
// GraemeSW
// Should I allow the Autosave slot to be overwritten by an imported savegame?
// During normal gameplay, the PS4 game saves a backup copy of the savegame at the same time as it saves an autosave or manual save.
// I'm not currently doing that when importing a savegame.
MemoryCardError CSaveGameImport::BeginInitialChecks()
{
if (CGenericGameStorage::GetSaveOperation() != OPERATION_NONE)
{
savegameErrorf("CSaveGameImport::BeginInitialChecks - CGenericGameStorage::GetSaveOperation() is not OPERATION_NONE");
savegameAssertf(0, "CSaveGameImport::BeginInitialChecks - CGenericGameStorage::GetSaveOperation() is not OPERATION_NONE");
return MEM_CARD_ERROR;
}
s32 savegameSlotNumber = CSavegameFrontEnd::GetSaveGameSlotToImport();
CSavegameFilenames::MakeValidSaveNameForLocalFile(savegameSlotNumber);
// Set the display name using the stats for last mission passed and completion percentage
SetDisplayNameForSavegame();
CSavegameInitialChecks::SetSizeOfBufferToBeSaved(sm_BufferContainingPsoDataForSaving.GetBufferSize());
#if RSG_ORBIS
CSavegameList::SetSlotToUpdateOnceSaveHasCompleted(savegameSlotNumber);
#endif
CGenericGameStorage::SetSaveOperation(OPERATION_SAVING_SAVEGAME_TO_CONSOLE);
CSavegameInitialChecks::BeginInitialChecks(false);
return MEM_CARD_COMPLETE;
}
MemoryCardError CSaveGameImport::InitialChecks()
{
CSavingMessage::BeginDisplaying(CSavingMessage::STORAGE_DEVICE_MESSAGE_SAVING);
return CSavegameInitialChecks::InitialChecks();
}
MemoryCardError CSaveGameImport::BeginSave()
{
if (CSavegameUsers::HasPlayerJustSignedOut())
{
savegameErrorf("CSaveGameImport::BeginSave - Player has signed out");
savegameAssertf(0, "CSaveGameImport::BeginSave - Player has signed out");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (!SAVEGAME.BeginSave(CSavegameUsers::GetUser(), CGenericGameStorage::GetContentType(),
CSavegameFilenames::GetNameToDisplay(),
CSavegameFilenames::GetFilenameOfLocalFile(),
sm_BufferContainingPsoDataForSaving.GetBuffer(),
sm_BufferContainingPsoDataForSaving.GetBufferSize(),
true) )
{
savegameErrorf("CSaveGameImport::BeginSave - SAVEGAME.BeginSave failed");
savegameAssertf(0, "CSaveGameImport::BeginSave - SAVEGAME.BeginSave failed");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_SAVE_FAILED);
return MEM_CARD_ERROR;
}
return MEM_CARD_COMPLETE;
}
MemoryCardError CSaveGameImport::CheckSave()
{
bool bOutIsValid = false;
bool bFileExists = false;
if (SAVEGAME.CheckSave(CSavegameUsers::GetUser(), bOutIsValid, bFileExists))
{ // returns true for error or success, false for busy
SAVEGAME.EndSave(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
savegameErrorf("CSaveGameImport::CheckSave - Player has signed out");
savegameAssertf(0, "CSaveGameImport::CheckSave - Player has signed out");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameErrorf("CSaveGameImport::CheckSave - SAVEGAME.GetState() returned HAD_ERROR");
savegameAssertf(0, "CSaveGameImport::CheckSave - SAVEGAME.GetState() returned HAD_ERROR");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_SAVE_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameErrorf("CSaveGameImport::CheckSave - SAVEGAME.GetError() didn't return SAVE_GAME_SUCCESS");
savegameAssertf(0, "CSaveGameImport::CheckSave - SAVEGAME.GetError() didn't return SAVE_GAME_SUCCESS");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_SAVE_FAILED2);
return MEM_CARD_ERROR;
}
return MEM_CARD_COMPLETE;
}
return MEM_CARD_BUSY;
}
#if RSG_ORBIS
MemoryCardError CSaveGameImport::BeginGetModifiedTime()
{
if (!SAVEGAME.BeginGetFileModifiedTime(CSavegameUsers::GetUser(), CSavegameFilenames::GetFilenameOfLocalFile()))
{
savegameErrorf("CSaveGameImport::BeginGetModifiedTime - SAVEGAME.BeginGetFileModifiedTime() failed");
savegameAssertf(0, "CSaveGameImport::BeginGetModifiedTime - SAVEGAME.BeginGetFileModifiedTime() failed");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_GET_FILE_MODIFIED_TIME_FAILED);
return MEM_CARD_ERROR;
}
return MEM_CARD_COMPLETE;
}
MemoryCardError CSaveGameImport::GetModifiedTime()
{
u32 ModifiedTimeHigh = 0;
u32 ModifiedTimeLow = 0;
if (SAVEGAME.CheckGetFileModifiedTime(CSavegameUsers::GetUser(), ModifiedTimeHigh, ModifiedTimeLow))
{ // returns true for error or success, false for busy
SAVEGAME.EndGetFileModifiedTime(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
savegameErrorf("CSaveGameImport::GetModifiedTime - Player has signed out");
savegameAssertf(0, "CSaveGameImport::GetModifiedTime - Player has signed out");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameErrorf("CSaveGameImport::GetModifiedTime - SAVEGAME.GetState() returned HAD_ERROR");
savegameAssertf(0, "CSaveGameImport::GetModifiedTime - SAVEGAME.GetState() returned HAD_ERROR");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameErrorf("CSaveGameImport::GetModifiedTime - SAVEGAME.GetError() didn't return SAVE_GAME_SUCCESS");
savegameAssertf(0, "CSaveGameImport::GetModifiedTime - SAVEGAME.GetError() didn't return SAVE_GAME_SUCCESS");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_GET_FILE_MODIFIED_TIME_FAILED2);
return MEM_CARD_ERROR;
}
CSavegameList::UpdateSlotDataAfterSave(ModifiedTimeHigh, ModifiedTimeLow, false); // savingBackupSave);
return MEM_CARD_COMPLETE;
}
return MEM_CARD_BUSY;
}
#endif // RSG_ORBIS
MemoryCardError CSaveGameImport::BeginIconSave(char *pSaveGameIcon, u32 sizeOfSaveGameIcon)
{
if (pSaveGameIcon)
{
if (!SAVEGAME.BeginIconSave(CSavegameUsers::GetUser(), CGenericGameStorage::GetContentType(),
CSavegameFilenames::GetFilenameOfLocalFile(), static_cast<const void *>(pSaveGameIcon), sizeOfSaveGameIcon))
{
savegameErrorf("CSaveGameImport::BeginIconSave - SAVEGAME.BeginIconSave() failed");
savegameAssertf(0, "CSaveGameImport::BeginIconSave - SAVEGAME.BeginIconSave() failed");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_BEGIN_ICON_SAVE_FAILED);
return MEM_CARD_ERROR;
}
}
return MEM_CARD_COMPLETE;
}
MemoryCardError CSaveGameImport::CheckIconSave()
{
if (SAVEGAME.CheckIconSave(CSavegameUsers::GetUser()))
{ // returns true for error or success, false for busy
SAVEGAME.EndIconSave(CSavegameUsers::GetUser());
if (CSavegameUsers::HasPlayerJustSignedOut())
{
savegameErrorf("CSaveGameImport::CheckIconSave - Player has signed out");
savegameAssertf(0, "CSaveGameImport::CheckIconSave - Player has signed out");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_PLAYER_HAS_SIGNED_OUT);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetState(CSavegameUsers::GetUser()) == fiSaveGameState::HAD_ERROR)
{
savegameErrorf("CSaveGameImport::CheckIconSave - GetState() returned HAD_ERROR");
savegameAssertf(0, "CSaveGameImport::CheckIconSave - GetState() returned HAD_ERROR");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED1);
return MEM_CARD_ERROR;
}
if (SAVEGAME.GetError(CSavegameUsers::GetUser()) != fiSaveGame::SAVE_GAME_SUCCESS)
{
savegameErrorf("CSaveGameImport::CheckIconSave - GetError() didn't return SAVE_GAME_SUCCESS");
savegameAssertf(0, "CSaveGameImport::CheckIconSave - GetError() didn't return SAVE_GAME_SUCCESS");
// CSavegameDialogScreens::SetSaveGameError(SAVE_GAME_DIALOG_CHECK_ICON_SAVE_FAILED2);
return MEM_CARD_ERROR;
}
return MEM_CARD_COMPLETE;
}
return MEM_CARD_BUSY;
}
void CSaveGameImport::SetDisplayNameForSavegame()
{
const char *pNameOfLastMissionPassed = NULL;
s32 hashOfLastMissionPassed = sm_SaveGameBufferContents_Code.GetHashOfNameOfLastMissionPassed();
if (TheText.DoesTextLabelExist(hashOfLastMissionPassed))
{
pNameOfLastMissionPassed = TheText.Get(hashOfLastMissionPassed, "SP_LAST_MISSION_NAME");
}
else
{
// Still need to add this to americanCode.txt
// It should say something like "Migrated Savegame"
pNameOfLastMissionPassed = TheText.Get("MIGRATED_SAVE");
}
float fPercentageComplete = sm_SaveGameBufferContents_Code.GetSinglePlayerCompletionPercentage();
CSavegameFilenames::SetNameToDisplay(pNameOfLastMissionPassed, fPercentageComplete);
}
#endif // __ALLOW_IMPORT_OF_SP_SAVEGAMES