From 7bb798edb604b537dd2169183fc68e4b02a530ef Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Fri, 27 Sep 2013 22:52:25 +0800 Subject: [PATCH] Implemented sceUtilityGamedataInstallUpdate. --- Core/Dialog/PSPGamedataInstallDialog.cpp | 105 ++++++++++++++++++++++- Core/Dialog/PSPGamedataInstallDialog.h | 18 +++- Core/HLE/sceUtility.cpp | 19 ++-- 3 files changed, 131 insertions(+), 11 deletions(-) diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 583208432f..c6e339cddb 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -19,6 +19,23 @@ #include "ChunkFile.h" #include "../Core/MemMap.h" +std::string saveBasePath = "ms0:/PSP/SAVEDATA/"; + +namespace +{ + std::vector GetPSPFileList (std::string dirpath) { + std::vector FileList; + auto Fileinfos = pspFileSystem.GetDirListing(dirpath); + std::string info; + + for (auto it = Fileinfos.begin(); it != Fileinfos.end(); ++it) { + std::string info = (*it).name; + FileList.push_back(info); + } + return FileList; + } +} + PSPGamedataInstallDialog::PSPGamedataInstallDialog() { } @@ -26,6 +43,18 @@ PSPGamedataInstallDialog::~PSPGamedataInstallDialog() { } int PSPGamedataInstallDialog::Init(u32 paramAddr) { +/////////////////////////////////////////////////////// + this->paramAddr = paramAddr; + inFileNames = GetPSPFileList ("disc0:/PSP_GAME/INSDIR"); + numFiles = 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; + } +////////////////////////////////////////////////////// // Already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) return SCE_ERROR_UTILITY_INVALID_STATUS; @@ -39,6 +68,61 @@ int PSPGamedataInstallDialog::Init(u32 paramAddr) { return 0; } +int PSPGamedataInstallDialog::Update() { + 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; + u8 *temp = new u8[4096]; + u32 inhandle; + u32 outhandle; + size_t readSize; + + if (readFiles < numFiles) { + 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)); + 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); + + status = SCE_UTILITY_STATUS_FINISHED; + } + } else if (status == SCE_UTILITY_STATUS_FINISHED) { + status = SCE_UTILITY_STATUS_SHUTDOWN; + } + return 0; +} + int PSPGamedataInstallDialog::Abort() { return PSPDialog::Shutdown(); } @@ -50,6 +134,25 @@ int PSPGamedataInstallDialog::Shutdown(bool force) { return PSPDialog::Shutdown(); } +std::string PSPGamedataInstallDialog::GetGameDataInstallFileName(SceUtilityGamedataInstallParam *param, std::string filename){ + if (!param) + return ""; + std::string GameDataInstallPath = saveBasePath + param->gameName + param->dataName + "/"; + if (!pspFileSystem.GetFileInfo(GameDataInstallPath).exists) + pspFileSystem.MkDir(GameDataInstallPath); + + return GameDataInstallPath + filename; +} + +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. + progressValue = (int)(allReadSize / allFilesSize) * 100; + request.progress[0] = progressValue; + Memory::WriteStruct(paramAddr,&request); +} + void PSPGamedataInstallDialog::DoState(PointerWrap &p) { auto s = p.Section("PSPGamedataInstallDialog", 0, 1); if (!s) @@ -57,4 +160,4 @@ void PSPGamedataInstallDialog::DoState(PointerWrap &p) { PSPDialog::DoState(p); p.Do(request); -} +} \ No newline at end of file diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index 3bcf270e5e..c083fda347 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -18,6 +18,7 @@ #pragma once #include "Core/Dialog/PSPDialog.h" +#include "Core/System.h" struct SceUtilityGamedataInstallParam { pspUtilityDialogCommon common; @@ -29,10 +30,11 @@ struct SceUtilityGamedataInstallParam { char gamedataParamsDataTitle[128]; char gamedataParamsData[1024]; u8 unknown2; - char ignore2[7]; + char ignore2[3]; + char progress[4]; // This is progress value,should be updated. u32 unknownResult1; u32 unknownResult2; - char ignore[48]; + char ignore3[48]; }; class PSPGamedataInstallDialog: public PSPDialog { @@ -41,12 +43,22 @@ public: virtual ~PSPGamedataInstallDialog(); virtual int Init(u32 paramAddr); - //virtual int Update(); + virtual int Update(); virtual int Shutdown(bool force = false); virtual void DoState(PointerWrap &p); int Abort(); + std::string GetGameDataInstallFileName(SceUtilityGamedataInstallParam *param, std::string filename); private: SceUtilityGamedataInstallParam request; + u32 paramAddr; + std::vector inFileNames; + int numFiles; + int readFiles; + u64 allFilesSize; + u64 allReadSize; + int progressValue; + + void updateProgress(); }; diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 53f61ab3dd..a67d5a81fa 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -454,9 +454,10 @@ int sceUtilityGamedataInstallInitStart(u32 paramsAddr) WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallInitStart(%08x): wrong dialog type", paramsAddr); return SCE_ERROR_UTILITY_WRONG_TYPE; } - DEBUG_LOG(SCEUTILITY, "sceUtilityGamedataInstallInitStart(%08x)", paramsAddr); currentDialogType = UTILITY_DIALOG_GAMEDATAINSTALL; - currentDialogActive = true; + currentDialogActive = true; + + DEBUG_LOG(SCEUTILITY, "sceUtilityGamedataInstallInitStart(%08x)", paramsAddr); return gamedataInstallDialog.Init(paramsAddr); } @@ -472,11 +473,15 @@ int sceUtilityGamedataInstallShutdownStart() { return gamedataInstallDialog.Shutdown(); } -int sceUtilityGamedataInstallUpdate(int speed) { - ERROR_LOG(SCEUTILITY, "UNIMPL sceUtilityGamedataInstallUpdate(%08x)", speed); - currentDialogActive = false; - gamedataInstallDialog.Abort(); - return 0; +int sceUtilityGamedataInstallUpdate(int Speed) { + if (currentDialogType != UTILITY_DIALOG_GAMEDATAINSTALL) + { + WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallUpdate(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + + DEBUG_LOG(SCEUTILITY, "sceUtilityGamedataInstallUpdate(%i)", Speed); + return gamedataInstallDialog.Update(); } int sceUtilityGamedataInstallGetStatus()