You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.7 KiB
198 lines
6.7 KiB
//===== Copyright © 1996-2011, Valve Corporation, All rights reserved. ======//
|
|
|
|
#include "ps3_saveutil_v2.h"
|
|
#include "fmtstr.h"
|
|
#include "checksum_crc.h"
|
|
#include "memdbgon.h"
|
|
|
|
|
|
CON_COMMAND( ps3_saveutil_showtoc, "" )
|
|
{
|
|
AUTO_LOCK( g_SaveUtilV2TOC.m_mtx );
|
|
|
|
int numTocEntries = g_SaveUtilV2TOC.m_arrEntries.Count();
|
|
Msg( "--------- SAVEUTILTOC -----------\n" );
|
|
for ( int k = 0; k < numTocEntries; ++ k )
|
|
{
|
|
CSaveUtilV2ContainerTOC::TocEntry_t &e = g_SaveUtilV2TOC.m_arrEntries[k].m_entry;
|
|
Msg( "%02d : %016llx %s\n"
|
|
" '%s' %u/%u\n"
|
|
" '%s' %u/%u\n"
|
|
" %s\n",
|
|
k + 1, e.m_timeModification, e.m_chContainerName,
|
|
e.m_chFile[0], e.m_numBytesFile[0], e.m_numBytesDecompressedFile[0],
|
|
e.m_chFile[1], e.m_numBytesFile[1], e.m_numBytesDecompressedFile[1],
|
|
e.m_chComment
|
|
);
|
|
}
|
|
Msg( "--------- %02d ENTRIES -----------\n", numTocEntries );
|
|
}
|
|
|
|
void SaveUtilV2_GetFileInfoSync( CUtlVector< IPS3SaveRestoreToUI::PS3SaveGameInfo_t > &saveGameInfos, bool bFindAll )
|
|
{
|
|
// This can be called after starting a save op but before it completes, so this will return old data in that case.
|
|
// The caller should be aware that if SaveUtil is busy then it can check the operation TAG and know what is in
|
|
// progress and whether it can affect the TOC after it's finished.
|
|
// Currently only UI queries the TOC and ensures that writes of savegames are completed before queries.
|
|
AUTO_LOCK( g_SaveUtilV2TOC.m_mtx );
|
|
|
|
if ( !g_SaveUtilV2TOC.m_arrEntries.Count() )
|
|
{
|
|
saveGameInfos.RemoveAll();
|
|
return;
|
|
}
|
|
|
|
int numTocEntries = bFindAll ? g_SaveUtilV2TOC.m_arrEntries.Count() : 1;
|
|
saveGameInfos.SetCount( numTocEntries );
|
|
for ( int k = 0; k < numTocEntries; ++ k )
|
|
{
|
|
saveGameInfos[k].m_InternalName = CFmtStr( "!%s", g_SaveUtilV2TOC.m_arrEntries[k].m_entry.m_chContainerName );
|
|
saveGameInfos[k].m_Comment = g_SaveUtilV2TOC.m_arrEntries[k].m_entry.m_chComment;
|
|
saveGameInfos[k].m_Filename = g_SaveUtilV2TOC.m_arrEntries[k].m_entry.m_chFile[0];
|
|
saveGameInfos[k].m_ScreenshotFilename = g_SaveUtilV2TOC.m_arrEntries[k].m_entry.m_chFile[1];
|
|
saveGameInfos[k].m_nFileTime = g_SaveUtilV2TOC.m_arrEntries[k].m_entry.m_timeModification;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bool SaveUtilV2_CanStartJob()
|
|
{
|
|
bool bResult = ( g_pSaveUtilThreadPool && !g_pSaveUtilAsyncStatus );
|
|
if ( !bResult )
|
|
{
|
|
Warning( "SaveUtilV2_CanStartJob : cannot start job now! Invalid usage!\n" );
|
|
Assert( 0 );
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
void SaveUtilV2_EnqueueJob( CPS3SaveRestoreAsyncStatus *pAsync, ISaveUtilV2Job *pJob )
|
|
{
|
|
if ( g_pSaveUtilAsyncStatus )
|
|
Error( "SaveUtilV2_EnqueueJob while job already running ( %p running, %p attempted )!\n", g_pSaveUtilAsyncStatus, pAsync );
|
|
|
|
g_pSaveUtilAsyncStatus = pAsync;
|
|
|
|
// Prepare for saveutil operation
|
|
const int numContainers = VALVE_CONTAINER_COUNT;
|
|
pJob->m_bufSaveDirList.EnsureCapacity( numContainers * MAX( sizeof( CellSaveDataFileStat ), sizeof( CellSaveDataDirList ) ) );
|
|
|
|
// Prepare save dir info
|
|
memset( &pJob->m_SaveDirInfo, 0, sizeof(CellSaveDataSetBuf) );
|
|
pJob->m_SaveDirInfo.dirListMax = numContainers;
|
|
pJob->m_SaveDirInfo.fileListMax = numContainers;
|
|
pJob->m_SaveDirInfo.bufSize = pJob->m_bufSaveDirList.Size();
|
|
pJob->m_SaveDirInfo.buf = pJob->m_bufSaveDirList.Base();
|
|
|
|
// Mark the job as pending
|
|
g_pSaveUtilAsyncStatus->m_nSonyRetValue = CELL_SAVEDATA_ERROR_NOTSUPPORTED;
|
|
g_pSaveUtilAsyncStatus->m_bDone = 0;
|
|
|
|
// Let's notify the file system that a save is starting, that way the file system can try to reduce HDD accesses and use BluRay instead
|
|
g_pFullFileSystem->OnSaveStateChanged( true );
|
|
|
|
// Add the job to thread pool
|
|
pJob->SetFlags( JF_SERIAL | JF_QUEUE );
|
|
g_pSaveUtilThreadPool->AddJob( pJob );
|
|
pJob->Release();
|
|
}
|
|
|
|
JobStatus_t SaveUtilV2_JobDone( int nErrorCode )
|
|
{
|
|
// Let's notify the file system that a save is finished, that way the file system can restart using the HDD
|
|
g_pFullFileSystem->OnSaveStateChanged( false );
|
|
|
|
// Set the job error code and set that the job is done
|
|
if ( nErrorCode != CELL_SAVEDATA_ERROR_CBRESULT )
|
|
g_pSaveUtilAsyncStatus->m_nSonyRetValue = nErrorCode;
|
|
else if ( g_pSaveUtilAsyncStatus->m_nSonyRetValue >= 0 )
|
|
g_pSaveUtilAsyncStatus->m_nSonyRetValue = CELL_SAVEDATA_ERROR_FAILURE;
|
|
|
|
CPS3SaveRestoreAsyncStatus *pAsync = g_pSaveUtilAsyncStatus;
|
|
g_pSaveUtilAsyncStatus = NULL;
|
|
pAsync->m_bDone = 1;
|
|
return JOB_OK;
|
|
}
|
|
|
|
uint32 SaveUtilV2_ComputeBufferHash( void const *pvData, uint32 numBytes )
|
|
{
|
|
return CRC32_ProcessSingleBuffer( pvData, numBytes );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void ISaveUtilV2Job::csDataStatCallback( SONY_SAVEUTIL_STAT_PARAMS )
|
|
{
|
|
ISaveUtilV2Job *pSelf = static_cast<ISaveUtilV2Job*>( cbResult->userdata );
|
|
pSelf->DoDataStatCallback( SONY_SAVEUTIL_PARAMS );
|
|
}
|
|
|
|
void ISaveUtilV2Job::csDataFileCallback( SONY_SAVEUTIL_FILE_PARAMS )
|
|
{
|
|
ISaveUtilV2Job *pSelf = static_cast<ISaveUtilV2Job*>( cbResult->userdata );
|
|
if ( pSelf->m_pfnDoDataFileCallback )
|
|
{
|
|
(pSelf->*(pSelf->m_pfnDoDataFileCallback))( SONY_SAVEUTIL_PARAMS );
|
|
}
|
|
else
|
|
{
|
|
Msg( "ISaveUtilV2Job::csDataFileCallback finalizing save operation @%.3f\n", Plat_FloatTime() );
|
|
cbResult->result = CELL_SAVEDATA_CBRESULT_OK_LAST;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CSaveUtilV2ContainerTOC::SerializeIntoTocBuffer( void *pvBuffer )
|
|
{
|
|
uint32 *pui32 = (uint32*) pvBuffer;
|
|
*( pui32 ++ ) = m_idxNewSaveName;
|
|
*( pui32 ++ ) = m_arrEntries.Count();
|
|
V_memcpy( pui32, m_arrEntries.Base(), m_arrEntries.Count() * sizeof( TocStorageReserved_t ) );
|
|
}
|
|
|
|
void CSaveUtilV2ContainerTOC::SerializeFromTocBuffer( void *pvBuffer )
|
|
{
|
|
uint32 *pui32 = (uint32*) pvBuffer;
|
|
m_idxNewSaveName = *( pui32 ++ );
|
|
uint32 uiEntriesCount = *( pui32 ++ );
|
|
uiEntriesCount = MIN( uiEntriesCount, VALVE_CONTAINER_COUNT );
|
|
m_arrEntries.AddMultipleToTail( uiEntriesCount, reinterpret_cast< TocStorageReserved_t * >( pui32 ) );
|
|
}
|
|
|
|
void CSaveUtilV2ContainerTOC::CopyInto( CSaveUtilV2ContainerTOC *pOther )
|
|
{
|
|
pOther->m_idxNewSaveName = m_idxNewSaveName;
|
|
pOther->m_arrEntries.RemoveAll();
|
|
pOther->m_arrEntries.AddMultipleToTail( m_arrEntries.Count(), m_arrEntries.Base() );
|
|
}
|
|
|
|
int CSaveUtilV2ContainerTOC::FindByEmbeddedFileName( char const *szFilename, int *pnPartIndex )
|
|
{
|
|
for ( int k = 0; k < m_arrEntries.Count(); ++ k )
|
|
{
|
|
if ( szFilename[0] == '!' )
|
|
{
|
|
if ( V_stricmp( m_arrEntries[k].m_entry.m_chContainerName, szFilename + 1 ) )
|
|
continue;
|
|
if ( pnPartIndex )
|
|
*pnPartIndex = 0;
|
|
return k;
|
|
}
|
|
for ( int iPart = 0; iPart < VALVE_CONTAINER_FPARTS; ++ iPart )
|
|
{
|
|
if ( !V_stricmp( m_arrEntries[k].m_entry.m_chFile[iPart], szFilename ) )
|
|
{
|
|
if ( pnPartIndex )
|
|
*pnPartIndex = iPart;
|
|
return k;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pnPartIndex )
|
|
*pnPartIndex = -1;
|
|
return -1;
|
|
}
|
|
|