#pragma once #include #include #include #include // #include #include "../4J.Common/4J_Compat.h" class C4JStringTable; #define MAX_DISPLAYNAME_LENGTH 128 // CELL_SAVEDATA_SYSP_SUBTITLE_SIZE on PS3 #define MAX_DETAILS_LENGTH 128 // CELL_SAVEDATA_SYSP_SUBTITLE_SIZE on PS3 #define MAX_SAVEFILENAME_LENGTH 32 // CELL_SAVEDATA_DIRNAME_SIZE typedef struct { time_t modifiedTime; unsigned int dataSize; unsigned int thumbnailSize; } CONTAINER_METADATA; typedef struct { char UTF8SaveFilename[MAX_SAVEFILENAME_LENGTH]; char UTF8SaveTitle[MAX_DISPLAYNAME_LENGTH]; CONTAINER_METADATA metaData; std::uint8_t* thumbnailData; } SAVE_INFO, *PSAVE_INFO; typedef struct { int iSaveC; PSAVE_INFO SaveInfoA; } SAVE_DETAILS, *PSAVE_DETAILS; typedef std::vector OfferDataArray; typedef std::vector XContentDataArray; // typedef std::vector SaveDetailsArray; // Current version of the dlc data creator #define CURRENT_DLC_VERSION_NUM 3 class C4JStorage { public: // Structs defined in the DLC_Creator, but added here to be used in the app typedef struct { unsigned int uiFileSize; std::uint32_t dwType; std::uint32_t dwWchCount; // count of wchar_t in next array wchar_t wchFile[1]; } DLC_FILE_DETAILS, *PDLC_FILE_DETAILS; typedef struct { std::uint32_t dwType; std::uint32_t dwWchCount; // count of wchar_t in next array; wchar_t wchData[1]; // will be an array of size dwBytes } DLC_FILE_PARAM, *PDLC_FILE_PARAM; // End of DLC_Creator structs typedef struct { wchar_t wchDisplayName[XCONTENT_MAX_DISPLAYNAME_LENGTH]; char szFileName[XCONTENT_MAX_FILENAME_LENGTH]; std::uint32_t dwImageOffset; std::uint32_t dwImageBytes; } CACHEINFOSTRUCT; // structure to hold DLC info in TMS typedef struct { std::uint32_t dwVersion; std::uint32_t dwNewOffers; std::uint32_t dwTotalOffers; std::uint32_t dwInstalledTotalOffers; std::uint8_t bPadding[1024 - sizeof(std::uint32_t) * 4]; // future expansion } DLC_TMS_DETAILS; enum eGTS_FileTypes { eGTS_Type_Skin = 0, eGTS_Type_Cape, eGTS_Type_MAX }; enum eGlobalStorage { // eGlobalStorage_GameClip=0, eGlobalStorage_Title = 0, eGlobalStorage_TitleUser, eGlobalStorage_Max }; enum EMessageResult { EMessage_Undefined = 0, EMessage_Busy, EMessage_Pending, EMessage_Cancelled, EMessage_ResultAccept, EMessage_ResultDecline, EMessage_ResultThirdOption, EMessage_ResultFourthOption }; enum ESaveGameControlState { ESaveGameControl_Idle = 0, ESaveGameControl_Save, ESaveGameControl_InternalRequestingDevice, ESaveGameControl_InternalGetSaveName, ESaveGameControl_InternalSaving, ESaveGameControl_CopySave, ESaveGameControl_CopyingSave, }; enum ESaveGameState { ESaveGame_Idle = 0, ESaveGame_Save, ESaveGame_InternalRequestingDevice, ESaveGame_InternalGetSaveName, ESaveGame_InternalSaving, ESaveGame_CopySave, ESaveGame_CopyingSave, ESaveGame_Load, ESaveGame_GetSavesInfo, ESaveGame_Rename, ESaveGame_Delete, ESaveGame_GetSaveThumbnail // Not used as an actual state in the PS4, // but the game expects this to be returned // to indicate success when getting a // thumbnail }; enum ELoadGameStatus { ELoadGame_Idle = 0, ELoadGame_InProgress, ELoadGame_NoSaves, ELoadGame_ChangedDevice, ELoadGame_DeviceRemoved }; enum EDeleteGameStatus { EDeleteGame_Idle = 0, EDeleteGame_InProgress, }; enum ESGIStatus { ESGIStatus_Error = 0, ESGIStatus_Idle, ESGIStatus_ReadInProgress, ESGIStatus_NoSaves, }; enum EDLCStatus { EDLC_Error = 0, EDLC_Idle, EDLC_NoOffers, EDLC_AlreadyEnumeratedAllOffers, EDLC_NoInstalledDLC, EDLC_Pending, EDLC_LoadInProgress, EDLC_Loaded, EDLC_ChangedDevice }; enum ESavingMessage { ESavingMessage_None = 0, ESavingMessage_Short, ESavingMessage_Long }; enum ETMSStatus { ETMSStatus_Idle = 0, ETMSStatus_Fail, ETMSStatus_Fail_ReadInProgress, ETMSStatus_Fail_WriteInProgress, ETMSStatus_Pending, }; enum eTMS_FileType { eTMS_FileType_Normal = 0, eTMS_FileType_Graphic, }; enum eTMS_FILETYPEVAL { TMS_FILETYPE_BINARY, TMS_FILETYPE_CONFIG, TMS_FILETYPE_JSON, TMS_FILETYPE_MAX }; enum eTMS_UGCTYPE { TMS_UGCTYPE_NONE, TMS_UGCTYPE_IMAGE, TMS_UGCTYPE_MAX }; typedef struct { char szFilename[256]; int iFileSize; eTMS_FILETYPEVAL eFileTypeVal; } TMSPP_FILE_DETAILS, *PTMSPP_FILE_DETAILS; typedef struct { int iCount; PTMSPP_FILE_DETAILS FileDetailsA; } TMSPP_FILE_LIST, *PTMSPP_FILE_LIST; typedef struct { unsigned int size; std::uint8_t* pbData; } TMSPP_FILEDATA, *PTMSPP_FILEDATA; C4JStorage(); void Tick(void); // Messages C4JStorage::EMessageResult RequestMessageBox( unsigned int uiTitle, unsigned int uiText, unsigned int* uiOptionA, unsigned int uiOptionC, unsigned int pad = XUSER_INDEX_ANY, int (*Func)(void*, int, const C4JStorage::EMessageResult) = nullptr, void* lpParam = nullptr, C4JStringTable* pStringTable = nullptr, wchar_t* pwchFormatString = nullptr, unsigned int focusButton = 0); C4JStorage::EMessageResult GetMessageBoxResult(); // save device bool SetSaveDevice(int (*Func)(void*, const bool), void* lpParam, bool bForceResetOfSaveDevice = false); // savegame void Init(unsigned int uiSaveVersion, const wchar_t* pwchDefaultSaveName, char* pszSavePackName, int iMinimumSaveSize, int (*Func)(void*, const ESavingMessage, int), void* lpParam, const char* szGroupID); void ResetSaveData(); // Call before a new save to clear out stored save // file name void SetDefaultSaveNameForKeyboardDisplay( const wchar_t* pwchDefaultSaveName); void SetSaveTitle(const wchar_t* pwchDefaultSaveName); bool GetSaveUniqueNumber(int* piVal); bool GetSaveUniqueFilename(char* pszName); void SetSaveUniqueFilename(char* szFilename); void SetState(ESaveGameControlState eControlState, int (*Func)(void*, const bool), void* lpParam); void SetSaveDisabled(bool bDisable); bool GetSaveDisabled(void); unsigned int GetSaveSize(); void GetSaveData(void* pvData, unsigned int* puiBytes); void* AllocateSaveData(unsigned int uiBytes); void SetSaveImages( std::uint8_t* pbThumbnail, unsigned int thumbnailBytes, std::uint8_t* pbImage, unsigned int imageBytes, std::uint8_t* pbTextData, unsigned int textDataBytes); // Sets the thumbnail & image for the // save, optionally setting the // metadata in the png C4JStorage::ESaveGameState SaveSaveData(int (*Func)(void*, const bool), void* lpParam); void CopySaveDataToNewSave(std::uint8_t* pbThumbnail, unsigned int cbThumbnail, wchar_t* wchNewName, int (*Func)(void* lpParam, bool), void* lpParam); void SetSaveDeviceSelected(unsigned int uiPad, bool bSelected); bool GetSaveDeviceSelected(unsigned int iPad); C4JStorage::ESaveGameState DoesSaveExist(bool* pbExists); bool EnoughSpaceForAMinSaveGame(); void SetSaveMessageVPosition( float fY); // The 'Saving' message will display at a default position // unless changed // Get the info for the saves C4JStorage::ESaveGameState GetSavesInfo( int iPad, int (*Func)(void* lpParam, SAVE_DETAILS* pSaveDetails, const bool), void* lpParam, char* pszSavePackName); PSAVE_DETAILS ReturnSavesInfo(); void ClearSavesInfo(); // Clears results C4JStorage::ESaveGameState LoadSaveDataThumbnail( PSAVE_INFO pSaveInfo, int (*Func)(void* lpParam, std::uint8_t* thumbnailData, unsigned int thumbnailBytes), void* lpParam); // Get the thumbnail for an individual save referenced // by pSaveInfo void GetSaveCacheFileInfo(unsigned int fileIndex, XCONTENT_DATA& xContentData); void GetSaveCacheFileInfo(unsigned int fileIndex, std::uint8_t** ppbImageData, unsigned int* pImageBytes); // Load the save. Need to call GetSaveData once the callback is called C4JStorage::ESaveGameState LoadSaveData(PSAVE_INFO pSaveInfo, int (*Func)(void* lpParam, const bool, const bool), void* lpParam); C4JStorage::ESaveGameState DeleteSaveData(PSAVE_INFO pSaveInfo, int (*Func)(void* lpParam, const bool), void* lpParam); // DLC void RegisterMarketplaceCountsCallback( int (*Func)(void* lpParam, C4JStorage::DLC_TMS_DETAILS*, int), void* lpParam); void SetDLCPackageRoot(char* pszDLCRoot); C4JStorage::EDLCStatus GetDLCOffers( int iPad, int (*Func)(void*, int, std::uint32_t, int), void* lpParam, std::uint32_t dwOfferTypesBitmask = XMARKETPLACE_OFFERING_TYPE_CONTENT); unsigned int CancelGetDLCOffers(); void ClearDLCOffers(); XMARKETPLACE_CONTENTOFFER_INFO& GetOffer(unsigned int dw); int GetOfferCount(); unsigned int InstallOffer(int iOfferIDC, std::uint64_t* ullOfferIDA, int (*Func)(void*, int, int), void* lpParam, bool bTrial = false); unsigned int GetAvailableDLCCount(int iPad); C4JStorage::EDLCStatus GetInstalledDLC(int iPad, int (*Func)(void*, int, int), void* lpParam); XCONTENT_DATA& GetDLC(unsigned int dw); std::uint32_t MountInstalledDLC(int iPad, std::uint32_t dwDLC, int (*Func)(void*, int, std::uint32_t, std::uint32_t), void* lpParam, const char* szMountDrive = nullptr); unsigned int UnmountInstalledDLC(const char* szMountDrive = nullptr); void GetMountedDLCFileList(const char* szMountDrive, std::vector& fileList); std::string GetMountedPath(std::string szMount); // Global title storage C4JStorage::ETMSStatus ReadTMSFile( int iQuadrant, eGlobalStorage eStorageFacility, C4JStorage::eTMS_FileType eFileType, wchar_t* pwchFilename, std::uint8_t** ppBuffer, unsigned int* pBufferSize, int (*Func)(void*, wchar_t*, int, bool, int) = nullptr, void* lpParam = nullptr, int iAction = 0); bool WriteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility, wchar_t* pwchFilename, std::uint8_t* pBuffer, unsigned int bufferSize); bool DeleteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility, wchar_t* pwchFilename); void StoreTMSPathName(wchar_t* pwchName = nullptr); // TMS++ #ifdef _XBOX C4JStorage::ETMSStatus WriteTMSFile( int iPad, C4JStorage::eGlobalStorage eStorageFacility, C4JStorage::eTMS_FileType eFileType, char* pchFilePath, char* pchBuffer, unsigned int bufferSize, TMSCLIENT_CALLBACK Func, void* lpParam); int GetUserQuotaInfo(int iPad, TMSCLIENT_CALLBACK Func, void* lpParam); #endif // Older TMS++ write/quota entry points were kept in platform-specific // implementations and are intentionally not part of this shared API. C4JStorage::ETMSStatus TMSPP_ReadFile( int iPad, C4JStorage::eGlobalStorage eStorageFacility, C4JStorage::eTMS_FILETYPEVAL eFileTypeVal, const char* szFilename, int (*Func)(void*, int, int, PTMSPP_FILEDATA, const char*) = nullptr, void* lpParam = nullptr, int iUserData = 0); // Older TMS++ list/delete helpers stayed platform-specific. The shared // surface keeps the read path plus CRC/subfile helpers below. // enum eXBLWS // { // eXBLWS_GET, // eXBLWS_POST, // eXBLWS_PUT, // eXBLWS_DELETE, // }; // bool // XBLWS_Command(eXBLWS eCommand); unsigned int CRC(unsigned char* buf, int len); int AddSubfile(int regionIndex); unsigned int GetSubfileCount(); void GetSubfileDetails(unsigned int i, int* regionIndex, void** data, unsigned int* size); void ResetSubfiles(); void UpdateSubfile(int index, void* data, unsigned int size); void SaveSubfiles(int (*Func)(void*, const bool), void* param); ESaveGameState GetSaveState(); void ContinueIncompleteOperation(); C4JStringTable* m_pStringTable; }; extern C4JStorage StorageManager;