From 43e7d9dbc22c2f3d241b6ff7c5904c3b5e41afd0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 25 Dec 2015 21:01:13 -0800 Subject: [PATCH 1/5] Gamedata: Use status delays in init/update/etc. Like with savedata. --- Core/Dialog/PSPGamedataInstallDialog.cpp | 136 ++++++++++++----------- Core/Dialog/PSPGamedataInstallDialog.h | 13 +-- 2 files changed, 78 insertions(+), 71 deletions(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index af297ba9be..d45de62db5 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -15,14 +15,20 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/Common.h" #include "Common/ChunkFile.h" #include "Core/MemMapHelpers.h" +#include "Core/Reporting.h" #include "Core/System.h" #include "Core/FileSystems/MetaFileSystem.h" #include "Core/Dialog/PSPGamedataInstallDialog.h" std::string saveBasePath = "ms0:/PSP/SAVEDATA/"; +// Guesses. +const static int GAMEDATA_INIT_DELAY_US = 200000; +const static int GAMEDATA_SHUTDOWN_DELAY_US = 2000; + namespace { std::vector GetPSPFileList (std::string dirpath) { @@ -44,92 +50,97 @@ PSPGamedataInstallDialog::~PSPGamedataInstallDialog() { } int PSPGamedataInstallDialog::Init(u32 paramAddr) { -/////////////////////////////////////////////////////// + if (GetStatus() != SCE_UTILITY_STATUS_NONE) { + ERROR_LOG_REPORT(SCEUTILITY, "A game install request is already running, not starting a new one"); + return SCE_ERROR_UTILITY_INVALID_STATUS; + } + this->paramAddr = paramAddr; - inFileNames = GetPSPFileList ("disc0:/PSP_GAME/INSDIR"); + inFileNames = GetPSPFileList("disc0:/PSP_GAME/INSDIR"); numFiles = (int)inFileNames.size(); readFiles = 0; progressValue = 0; allFilesSize = 0; allReadSize = 0; - for (auto it = inFileNames.begin(); it != inFileNames.end(); ++it) { - allFilesSize += pspFileSystem.GetFileInfo("disc0:/PSP_GAME/INSDIR/" + (*it)).size; + + for (std::string filename : inFileNames) { + allFilesSize += pspFileSystem.GetFileInfo("disc0:/PSP_GAME/INSDIR/" + filename).size; + } + + if (allFilesSize == 0) { + ERROR_LOG_REPORT(SCEUTILITY, "Game install with no files / data"); + // TODO: What happens here? + return -1; } -////////////////////////////////////////////////////// - // Already running - if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) - return SCE_ERROR_UTILITY_INVALID_STATUS; int size = Memory::Read_U32(paramAddr); memset(&request, 0, sizeof(request)); // Only copy the right size to support different request format Memory::Memcpy(&request, paramAddr, size); - status = SCE_UTILITY_STATUS_INITIALIZE; + ChangeStatusInit(GAMEDATA_INIT_DELAY_US); return 0; } int PSPGamedataInstallDialog::Update(int animSpeed) { - if (status == SCE_UTILITY_STATUS_INITIALIZE){ - status = SCE_UTILITY_STATUS_RUNNING; - } else if (status == SCE_UTILITY_STATUS_RUNNING) { - std::string fullinFileName; - std::string outFileName; - u64 totalLength; - u64 restLength; - u32 bytesToRead = 4096; - u32 inhandle; - u32 outhandle; - size_t readSize; - - if (readFiles < numFiles) { - u8 *temp = new u8[4096]; - fullinFileName = "disc0:/PSP_GAME/INSDIR/" + inFileNames[readFiles]; - outFileName = GetGameDataInstallFileName(&request, inFileNames[readFiles]); - totalLength = pspFileSystem.GetFileInfo(fullinFileName).size; - restLength = totalLength; - inhandle = pspFileSystem.OpenFile(fullinFileName, FILEACCESS_READ); - if (inhandle != 0) { - outhandle = pspFileSystem.OpenFile(outFileName, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE)); - if (outhandle != 0) { - while (restLength > 0) { - if (restLength < bytesToRead) - bytesToRead = (u32)restLength; - readSize = pspFileSystem.ReadFile(inhandle, temp, bytesToRead); - if(readSize > 0) { - pspFileSystem.WriteFile(outhandle, temp, readSize); - restLength -= readSize; - allReadSize += readSize; - } else - break; - } - pspFileSystem.CloseFile(outhandle); - } - ++readFiles; - pspFileSystem.CloseFile(inhandle); - } - updateProgress(); - delete[] temp; - } else { - //What is this? - request.unknownResult1 = readFiles; - request.unknownResult2 = readFiles; - Memory::WriteStruct(paramAddr,&request); + if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) + return SCE_ERROR_UTILITY_INVALID_STATUS; - status = SCE_UTILITY_STATUS_FINISHED; + std::string fullinFileName; + std::string outFileName; + u64 totalLength; + u64 restLength; + u32 bytesToRead = 4096; + u32 inhandle; + u32 outhandle; + size_t readSize; + + if (readFiles < numFiles) { + u8 *temp = new u8[4096]; + fullinFileName = "disc0:/PSP_GAME/INSDIR/" + inFileNames[readFiles]; + outFileName = GetGameDataInstallFileName(&request, inFileNames[readFiles]); + totalLength = pspFileSystem.GetFileInfo(fullinFileName).size; + restLength = totalLength; + inhandle = pspFileSystem.OpenFile(fullinFileName, FILEACCESS_READ); + if (inhandle != 0) { + outhandle = pspFileSystem.OpenFile(outFileName, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE)); + if (outhandle != 0) { + while (restLength > 0) { + if (restLength < bytesToRead) + bytesToRead = (u32)restLength; + readSize = pspFileSystem.ReadFile(inhandle, temp, bytesToRead); + if(readSize > 0) { + pspFileSystem.WriteFile(outhandle, temp, readSize); + restLength -= readSize; + allReadSize += readSize; + } else + break; + } + pspFileSystem.CloseFile(outhandle); + } + ++readFiles; + pspFileSystem.CloseFile(inhandle); } - } else if (status == SCE_UTILITY_STATUS_FINISHED) { - status = SCE_UTILITY_STATUS_SHUTDOWN; - } + UpdateProgress(); + delete[] temp; + } else { + //What is this? + request.unknownResult1 = readFiles; + request.unknownResult2 = readFiles; + Memory::WriteStruct(paramAddr,&request); + + ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); + } return 0; } int PSPGamedataInstallDialog::Abort() { + // TODO: Delete the files or anything? return PSPDialog::Shutdown(); } int PSPGamedataInstallDialog::Shutdown(bool force) { - if (status != SCE_UTILITY_STATUS_FINISHED && !force) + if (GetStatus() != SCE_UTILITY_STATUS_FINISHED && !force) return SCE_ERROR_UTILITY_INVALID_STATUS; return PSPDialog::Shutdown(force); @@ -145,16 +156,15 @@ std::string PSPGamedataInstallDialog::GetGameDataInstallFileName(SceUtilityGamed return GameDataInstallPath + filename; } -void PSPGamedataInstallDialog::updateProgress() { +void PSPGamedataInstallDialog::UpdateProgress() { // Update progress bar(if there is). - // progress value is progress[3] << 24 | progress[2] << 16 | progress[1] << 8 | progress[0]. // We only should update progress[0] here as the max progress value is 100. if (allFilesSize != 0) progressValue = (int)(allReadSize / allFilesSize) * 100; else progressValue = 100; - request.progress[0] = progressValue; - Memory::WriteStruct(paramAddr,&request); + request.progress = progressValue; + Memory::WriteStruct(paramAddr, &request); } void PSPGamedataInstallDialog::DoState(PointerWrap &p) { diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index 0ec969443b..bdd7bdbc6c 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -18,6 +18,7 @@ #pragma once #include "Core/Dialog/PSPDialog.h" +#include "Core/Dialog/SavedataParam.h" struct SceUtilityGamedataInstallParam { pspUtilityDialogCommon common; @@ -25,12 +26,8 @@ struct SceUtilityGamedataInstallParam { char gameName[13]; char ignore1[3]; char dataName[20]; - char gamedataParamsGameTitle[128]; - char gamedataParamsDataTitle[128]; - char gamedataParamsData[1024]; - u8 unknown2; - char ignore2[3]; - char progress[4]; // This is progress value,should be updated. + PspUtilitySavedataSFOParam sfoParam; + int progress; u32_le unknownResult1; u32_le unknownResult2; char ignore3[48]; @@ -50,6 +47,8 @@ public: std::string GetGameDataInstallFileName(SceUtilityGamedataInstallParam *param, std::string filename); private: + void UpdateProgress(); + SceUtilityGamedataInstallParam request; u32 paramAddr; std::vector inFileNames; @@ -58,6 +57,4 @@ private: u64 allFilesSize; // use this to calculate progress value. u64 allReadSize; // use this to calculate progress value. int progressValue; - - void updateProgress(); }; From fb9e5d47414d7c2d3adc32863ab1d45ef23f1a07 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 25 Dec 2015 21:13:55 -0800 Subject: [PATCH 2/5] Gamedata: Refactor out file iteration. Goal here is to process files in chunks, rather than one file at a time. Files are often > 100MB, so we don't want to copy all in one frame. --- Core/Dialog/PSPGamedataInstallDialog.cpp | 90 ++++++++++++++++-------- Core/Dialog/PSPGamedataInstallDialog.h | 5 ++ 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index d45de62db5..3f3b860f2e 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -62,6 +62,8 @@ int PSPGamedataInstallDialog::Init(u32 paramAddr) { progressValue = 0; allFilesSize = 0; allReadSize = 0; + currentInputFile = 0; + currentOutputFile = 0; for (std::string filename : inFileNames) { allFilesSize += pspFileSystem.GetFileInfo("disc0:/PSP_GAME/INSDIR/" + filename).size; @@ -86,43 +88,39 @@ int PSPGamedataInstallDialog::Update(int animSpeed) { if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) return SCE_ERROR_UTILITY_INVALID_STATUS; - std::string fullinFileName; - std::string outFileName; - u64 totalLength; - u64 restLength; u32 bytesToRead = 4096; - u32 inhandle; - u32 outhandle; size_t readSize; if (readFiles < numFiles) { - u8 *temp = new u8[4096]; - fullinFileName = "disc0:/PSP_GAME/INSDIR/" + inFileNames[readFiles]; - outFileName = GetGameDataInstallFileName(&request, inFileNames[readFiles]); - totalLength = pspFileSystem.GetFileInfo(fullinFileName).size; - restLength = totalLength; - inhandle = pspFileSystem.OpenFile(fullinFileName, FILEACCESS_READ); - if (inhandle != 0) { - outhandle = pspFileSystem.OpenFile(outFileName, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE)); - if (outhandle != 0) { - while (restLength > 0) { - if (restLength < bytesToRead) - bytesToRead = (u32)restLength; - readSize = pspFileSystem.ReadFile(inhandle, temp, bytesToRead); - if(readSize > 0) { - pspFileSystem.WriteFile(outhandle, temp, readSize); - restLength -= readSize; - allReadSize += readSize; - } else - break; + OpenNextFile(); + + if (currentInputFile != 0 && currentOutputFile != 0) { + u8 *temp = new u8[4096]; + + while (currentInputBytesLeft > 0) { + if (currentInputBytesLeft < bytesToRead) + bytesToRead = currentInputBytesLeft; + readSize = pspFileSystem.ReadFile(currentInputFile, temp, bytesToRead); + if (readSize > 0) { + pspFileSystem.WriteFile(currentOutputFile, temp, readSize); + currentInputBytesLeft -= readSize; + allReadSize += readSize; + } else { + break; } - pspFileSystem.CloseFile(outhandle); } + pspFileSystem.CloseFile(currentOutputFile); + currentOutputFile = 0; + + pspFileSystem.CloseFile(currentInputFile); + currentInputFile = 0; + + delete[] temp; + ++readFiles; - pspFileSystem.CloseFile(inhandle); } + UpdateProgress(); - delete[] temp; } else { //What is this? request.unknownResult1 = readFiles; @@ -134,6 +132,30 @@ int PSPGamedataInstallDialog::Update(int animSpeed) { return 0; } +void PSPGamedataInstallDialog::OpenNextFile() { + std::string inputFileName = "disc0:/PSP_GAME/INSDIR/" + inFileNames[readFiles]; + std::string outputFileName = GetGameDataInstallFileName(&request, inFileNames[readFiles]); + + currentInputFile = pspFileSystem.OpenFile(inputFileName, FILEACCESS_READ); + if (!currentInputFile) { + // TODO: Generate an error code? + ERROR_LOG_REPORT(SCEUTILITY, "Unable to read from install file: %s", inFileNames[readFiles].c_str()); + ++readFiles; + return; + } + currentOutputFile = pspFileSystem.OpenFile(outputFileName, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE)); + if (!currentOutputFile) { + // TODO: Generate an error code? + ERROR_LOG(SCEUTILITY, "Unable to write to install file: %s", inFileNames[readFiles].c_str()); + pspFileSystem.CloseFile(currentInputFile); + currentInputFile = 0; + ++readFiles; + return; + } + + currentInputBytesLeft = (u32)pspFileSystem.GetFileInfo(inputFileName).size; +} + int PSPGamedataInstallDialog::Abort() { // TODO: Delete the files or anything? return PSPDialog::Shutdown(); @@ -168,7 +190,7 @@ void PSPGamedataInstallDialog::UpdateProgress() { } void PSPGamedataInstallDialog::DoState(PointerWrap &p) { - auto s = p.Section("PSPGamedataInstallDialog", 0, 2); + auto s = p.Section("PSPGamedataInstallDialog", 0, 3); if (!s) return; @@ -188,4 +210,14 @@ void PSPGamedataInstallDialog::DoState(PointerWrap &p) { } else { paramAddr = 0; } + + if (s > 3) { + p.Do(currentInputFile); + p.Do(currentInputBytesLeft); + p.Do(currentOutputFile); + } else { + currentInputFile = 0; + currentInputBytesLeft = 0; + currentOutputFile = 0; + } } diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index bdd7bdbc6c..a0dbe41b2c 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -48,6 +48,7 @@ public: private: void UpdateProgress(); + void OpenNextFile(); SceUtilityGamedataInstallParam request; u32 paramAddr; @@ -57,4 +58,8 @@ private: u64 allFilesSize; // use this to calculate progress value. u64 allReadSize; // use this to calculate progress value. int progressValue; + + u32 currentInputFile; + u32 currentInputBytesLeft; + u32 currentOutputFile; }; From e4c6a8398e4740676b12c0ed79fab4cc769849dc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 25 Dec 2015 21:39:24 -0800 Subject: [PATCH 3/5] Gamedata: Copy in chunks instead of all at once. This way the game's progress shows correctly. Also, correct the progress calculation for < 100% (integer rounding.) --- Core/Dialog/PSPGamedataInstallDialog.cpp | 70 ++++++++++++++---------- Core/Dialog/PSPGamedataInstallDialog.h | 2 + 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 3f3b860f2e..c8f59f6e82 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "Common/Common.h" #include "Common/ChunkFile.h" #include "Core/MemMapHelpers.h" @@ -28,6 +29,8 @@ std::string saveBasePath = "ms0:/PSP/SAVEDATA/"; // Guesses. const static int GAMEDATA_INIT_DELAY_US = 200000; const static int GAMEDATA_SHUTDOWN_DELAY_US = 2000; +const static u32 GAMEDATA_BYTES_PER_READ = 32768; +const static u32 GAMEDATA_READS_PER_UPDATE = 100; namespace { @@ -87,37 +90,13 @@ int PSPGamedataInstallDialog::Init(u32 paramAddr) { int PSPGamedataInstallDialog::Update(int animSpeed) { if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) return SCE_ERROR_UTILITY_INVALID_STATUS; - - u32 bytesToRead = 4096; - size_t readSize; if (readFiles < numFiles) { - OpenNextFile(); - if (currentInputFile != 0 && currentOutputFile != 0) { - u8 *temp = new u8[4096]; - - while (currentInputBytesLeft > 0) { - if (currentInputBytesLeft < bytesToRead) - bytesToRead = currentInputBytesLeft; - readSize = pspFileSystem.ReadFile(currentInputFile, temp, bytesToRead); - if (readSize > 0) { - pspFileSystem.WriteFile(currentOutputFile, temp, readSize); - currentInputBytesLeft -= readSize; - allReadSize += readSize; - } else { - break; - } - } - pspFileSystem.CloseFile(currentOutputFile); - currentOutputFile = 0; - - pspFileSystem.CloseFile(currentInputFile); - currentInputFile = 0; - - delete[] temp; - - ++readFiles; + // Continue copying, this will close once done automatically. + CopyCurrentFileData(); + } else { + OpenNextFile(); } UpdateProgress(); @@ -156,6 +135,39 @@ void PSPGamedataInstallDialog::OpenNextFile() { currentInputBytesLeft = (u32)pspFileSystem.GetFileInfo(inputFileName).size; } +void PSPGamedataInstallDialog::CopyCurrentFileData() { + u8 buffer[GAMEDATA_BYTES_PER_READ]; + for (u32 i = 0; i < GAMEDATA_READS_PER_UPDATE; ++i) { + if (currentInputBytesLeft <= 0) { + break; + } + + const u32 bytesToRead = std::min(GAMEDATA_BYTES_PER_READ, currentInputBytesLeft); + size_t readSize = pspFileSystem.ReadFile(currentInputFile, buffer, bytesToRead); + if (readSize > 0) { + pspFileSystem.WriteFile(currentOutputFile, buffer, readSize); + currentInputBytesLeft -= (u32)readSize; + allReadSize += readSize; + } else { + break; + } + } + + if (currentInputBytesLeft <= 0) { + CloseCurrentFile(); + } +} + +void PSPGamedataInstallDialog::CloseCurrentFile() { + pspFileSystem.CloseFile(currentOutputFile); + currentOutputFile = 0; + + pspFileSystem.CloseFile(currentInputFile); + currentInputFile = 0; + + ++readFiles; +} + int PSPGamedataInstallDialog::Abort() { // TODO: Delete the files or anything? return PSPDialog::Shutdown(); @@ -182,7 +194,7 @@ void PSPGamedataInstallDialog::UpdateProgress() { // Update progress bar(if there is). // We only should update progress[0] here as the max progress value is 100. if (allFilesSize != 0) - progressValue = (int)(allReadSize / allFilesSize) * 100; + progressValue = (int)((allReadSize * 100) / allFilesSize); else progressValue = 100; request.progress = progressValue; diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index a0dbe41b2c..910cbd9b20 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -49,6 +49,8 @@ public: private: void UpdateProgress(); void OpenNextFile(); + void CopyCurrentFileData(); + void CloseCurrentFile(); SceUtilityGamedataInstallParam request; u32 paramAddr; From 34fc03068a2f6030bfef5fc8c16ad9ea4b31b0d5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 25 Dec 2015 21:54:14 -0800 Subject: [PATCH 4/5] Gamedata: Create a basic PARAM.SFO in data dir. Fixes #7903. Have not really tested, just based on game behavior. Could be inaccurate. --- Core/Dialog/PSPGamedataInstallDialog.cpp | 52 +++++++++++++++++++++--- Core/Dialog/PSPGamedataInstallDialog.h | 3 +- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index c8f59f6e82..8b074a4f77 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -18,6 +18,7 @@ #include #include "Common/Common.h" #include "Common/ChunkFile.h" +#include "Core/ELF/ParamSFO.h" #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/System.h" @@ -32,6 +33,8 @@ const static int GAMEDATA_SHUTDOWN_DELAY_US = 2000; const static u32 GAMEDATA_BYTES_PER_READ = 32768; const static u32 GAMEDATA_READS_PER_UPDATE = 100; +static const std::string SFO_FILENAME = "PARAM.SFO"; + namespace { std::vector GetPSPFileList (std::string dirpath) { @@ -58,7 +61,7 @@ int PSPGamedataInstallDialog::Init(u32 paramAddr) { return SCE_ERROR_UTILITY_INVALID_STATUS; } - this->paramAddr = paramAddr; + param.ptr = paramAddr; inFileNames = GetPSPFileList("disc0:/PSP_GAME/INSDIR"); numFiles = (int)inFileNames.size(); readFiles = 0; @@ -101,10 +104,12 @@ int PSPGamedataInstallDialog::Update(int animSpeed) { UpdateProgress(); } else { - //What is this? + WriteSfoFile(); + + // TODO: What is this? Should one of these update per file or anything? request.unknownResult1 = readFiles; request.unknownResult2 = readFiles; - Memory::WriteStruct(paramAddr,&request); + Memory::WriteStruct(param.ptr, &request); ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); } @@ -168,6 +173,41 @@ void PSPGamedataInstallDialog::CloseCurrentFile() { ++readFiles; } +void PSPGamedataInstallDialog::WriteSfoFile() { + ParamSFOData sfoFile; + std::string sfopath = GetGameDataInstallFileName(&request, SFO_FILENAME); + PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); + if (sfoInfo.exists) { + std::vector sfoData; + if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) { + sfoFile.ReadSFO(sfoData); + } + } + + // Update based on the just-saved data. + sfoFile.SetValue("TITLE", param->sfoParam.title, 128); + sfoFile.SetValue("SAVEDATA_TITLE", param->sfoParam.savedataTitle, 128); + sfoFile.SetValue("SAVEDATA_DETAIL", param->sfoParam.detail, 1024); + sfoFile.SetValue("PARENTAL_LEVEL", param->sfoParam.parentalLevel, 4); + // TODO: Verify category. + sfoFile.SetValue("CATEGORY", "MS", 4); + sfoFile.SetValue("SAVEDATA_DIRECTORY", std::string(param->gameName) + param->dataName, 64); + + // TODO: Maybe there should be other things in the SFO file? Needs testing. + + u8 *sfoData; + size_t sfoSize; + sfoFile.WriteSFO(&sfoData,&sfoSize); + + u32 handle = pspFileSystem.OpenFile(sfopath, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE)); + if (handle != 0) { + pspFileSystem.WriteFile(handle, sfoData, sfoSize); + pspFileSystem.CloseFile(handle); + } + + delete[] sfoData; +} + int PSPGamedataInstallDialog::Abort() { // TODO: Delete the files or anything? return PSPDialog::Shutdown(); @@ -198,7 +238,7 @@ void PSPGamedataInstallDialog::UpdateProgress() { else progressValue = 100; request.progress = progressValue; - Memory::WriteStruct(paramAddr, &request); + Memory::WriteStruct(param.ptr, &request); } void PSPGamedataInstallDialog::DoState(PointerWrap &p) { @@ -212,7 +252,7 @@ void PSPGamedataInstallDialog::DoState(PointerWrap &p) { // This was included in version 2 and higher. if (s > 2) { - p.Do(paramAddr); + p.Do(param.ptr); p.Do(inFileNames); p.Do(numFiles); p.Do(readFiles); @@ -220,7 +260,7 @@ void PSPGamedataInstallDialog::DoState(PointerWrap &p) { p.Do(allReadSize); p.Do(progressValue); } else { - paramAddr = 0; + param.ptr = 0; } if (s > 3) { diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index 910cbd9b20..85d0c33fc4 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -51,9 +51,10 @@ private: void OpenNextFile(); void CopyCurrentFileData(); void CloseCurrentFile(); + void WriteSfoFile(); SceUtilityGamedataInstallParam request; - u32 paramAddr; + PSPPointer param; std::vector inFileNames; int numFiles; int readFiles; From 7471516d05905300ec1fa72fcef80ba466bc1e30 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 25 Dec 2015 23:23:10 -0800 Subject: [PATCH 5/5] Gamedata: Reduce the transfer per call. The standard value made my desktop drop frames without the data cached. --- Core/Dialog/PSPGamedataInstallDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 8b074a4f77..a57de30af7 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -31,7 +31,9 @@ std::string saveBasePath = "ms0:/PSP/SAVEDATA/"; const static int GAMEDATA_INIT_DELAY_US = 200000; const static int GAMEDATA_SHUTDOWN_DELAY_US = 2000; const static u32 GAMEDATA_BYTES_PER_READ = 32768; -const static u32 GAMEDATA_READS_PER_UPDATE = 100; +// TODO: Could adjust based on real-time into frame? Or eat cycles? +// If this is too high, some games (e.g. Senjou no Valkyria 3) will lag. +const static u32 GAMEDATA_READS_PER_UPDATE = 20; static const std::string SFO_FILENAME = "PARAM.SFO";