mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-02 22:30:39 +00:00
Minor changes for save data utility (#3005)
This commit is contained in:
parent
aed9b31294
commit
6610abcd5f
3 changed files with 107 additions and 46 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||||
|
|
||||||
#include "cellSaveData.h"
|
#include "cellSaveData.h"
|
||||||
|
|
||||||
|
@ -63,7 +64,6 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
PFuncFile funcFile, u32 container, u32 unknown, vm::ptr<void> userdata, u32 userId, PFuncDone funcDone)
|
PFuncFile funcFile, u32 container, u32 unknown, vm::ptr<void> userdata, u32 userId, PFuncDone funcDone)
|
||||||
{
|
{
|
||||||
// TODO: check arguments
|
// TODO: check arguments
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(g_savedata_mutex, std::try_to_lock);
|
std::unique_lock<std::mutex> lock(g_savedata_mutex, std::try_to_lock);
|
||||||
|
|
||||||
if (!lock)
|
if (!lock)
|
||||||
|
@ -82,6 +82,8 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
vm::ptr<CellSaveDataFileGet> fileGet = g_savedata_context.ptr(&savedata_context::fileGet);
|
vm::ptr<CellSaveDataFileGet> fileGet = g_savedata_context.ptr(&savedata_context::fileGet);
|
||||||
vm::ptr<CellSaveDataFileSet> fileSet = g_savedata_context.ptr(&savedata_context::fileSet);
|
vm::ptr<CellSaveDataFileSet> fileSet = g_savedata_context.ptr(&savedata_context::fileSet);
|
||||||
|
|
||||||
|
//TODO: get current user ID
|
||||||
|
// userId(0) = CELL_SYSUTIL_USERID_CURRENT
|
||||||
// path of the specified user (00000001 by default)
|
// path of the specified user (00000001 by default)
|
||||||
const std::string& base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u));
|
const std::string& base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u));
|
||||||
|
|
||||||
|
@ -100,6 +102,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
|
|
||||||
const auto prefix_list = fmt::split(setList->dirNamePrefix.get_ptr(), { "|" });
|
const auto prefix_list = fmt::split(setList->dirNamePrefix.get_ptr(), { "|" });
|
||||||
|
|
||||||
|
// get the saves matching the supplied prefix
|
||||||
for (const auto& entry : fs::dir(base_dir))
|
for (const auto& entry : fs::dir(base_dir))
|
||||||
{
|
{
|
||||||
if (!entry.is_directory)
|
if (!entry.is_directory)
|
||||||
|
@ -211,13 +214,15 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
|
|
||||||
if (result->result < 0)
|
if (result->result < 0)
|
||||||
{
|
{
|
||||||
|
//TODO: display dialog
|
||||||
cellSaveData.warning("savedata_op(): funcList returned < 0.");
|
cellSaveData.warning("savedata_op(): funcList returned < 0.");
|
||||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the callback has returned ok, lets return OK.
|
// if the callback has returned ok, lets return OK.
|
||||||
// typically used at game launch when no list is actually required.
|
// typically used at game launch when no list is actually required.
|
||||||
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
|
// CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM is only valid for funcFile and funcDone
|
||||||
|
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||||
{
|
{
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +241,16 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
return true;
|
return true;
|
||||||
}), save_entries.end());
|
}), save_entries.end());
|
||||||
|
|
||||||
|
// Add any new data (not currently supported by the UI)
|
||||||
|
//if (listSet->newData)
|
||||||
|
//{
|
||||||
|
// SaveDataEntry *_saveDataEntry = new SaveDataEntry();
|
||||||
|
// _saveDataEntry->dirName = listSet->newData->dirName.get_ptr();
|
||||||
|
|
||||||
|
// save_entry.dirName = listSet->newData->dirName.get_ptr();
|
||||||
|
// save_entries.emplace_back(*_saveDataEntry);
|
||||||
|
//}
|
||||||
|
|
||||||
// Focus save data
|
// Focus save data
|
||||||
s32 focused = -1;
|
s32 focused = -1;
|
||||||
|
|
||||||
|
@ -296,6 +311,8 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
}
|
}
|
||||||
case CELL_SAVEDATA_FOCUSPOS_NEWDATA:
|
case CELL_SAVEDATA_FOCUSPOS_NEWDATA:
|
||||||
{
|
{
|
||||||
|
//TODO: If adding the new data to the save_entries vector
|
||||||
|
// to be displayed in the save mangaer UI, it should be focused here
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -339,8 +356,19 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
// Fixed Callback
|
// Fixed Callback
|
||||||
funcFixed(ppu, result, listGet, fixedSet);
|
funcFixed(ppu, result, listGet, fixedSet);
|
||||||
|
|
||||||
|
// skip all following steps if OK_LAST
|
||||||
|
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||||
|
{
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (result->result < 0)
|
if (result->result < 0)
|
||||||
{
|
{
|
||||||
|
//TODO: Show msgDialog if required
|
||||||
|
// depends on fixedSet->option
|
||||||
|
// 0 = none
|
||||||
|
// 1 = skip confirmation dialog
|
||||||
|
|
||||||
cellSaveData.warning("savedata_op(): funcFixed returned < 0.");
|
cellSaveData.warning("savedata_op(): funcFixed returned < 0.");
|
||||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||||
}
|
}
|
||||||
|
@ -363,10 +391,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
{
|
{
|
||||||
save_entry.dirName = fixedSet->dirName.get_ptr();
|
save_entry.dirName = fixedSet->dirName.get_ptr();
|
||||||
}
|
}
|
||||||
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
|
|
||||||
{
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected >= 0)
|
if (selected >= 0)
|
||||||
|
@ -479,6 +504,11 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||||
|
{
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (statSet->setParam)
|
if (statSet->setParam)
|
||||||
{
|
{
|
||||||
// Update PARAM.SFO
|
// Update PARAM.SFO
|
||||||
|
@ -498,18 +528,20 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
{ "TITLE", psf::string(128, statSet->setParam->title) },
|
{ "TITLE", psf::string(128, statSet->setParam->title) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (psf.empty())
|
//else if (psf.empty())
|
||||||
{
|
//{
|
||||||
// setParam is NULL for new savedata: abort operation
|
// // setParam is specified if something required updating.
|
||||||
|
// // Do not exit. Recreate mode will handle the rest
|
||||||
return CELL_OK;
|
// //return CELL_OK;
|
||||||
}
|
//}
|
||||||
|
|
||||||
switch (const u32 mode = statSet->reCreateMode & 0xffff)
|
switch (const u32 mode = statSet->reCreateMode & 0xffff)
|
||||||
{
|
{
|
||||||
case CELL_SAVEDATA_RECREATE_NO:
|
case CELL_SAVEDATA_RECREATE_NO:
|
||||||
{
|
{
|
||||||
cellSaveData.error("Savedata %s considered broken", save_entry.dirName);
|
//CELL_SAVEDATA_RECREATE_NO = overwrite and let the user know, not data is corrupt.
|
||||||
|
//cellSaveData.error("Savedata %s considered broken", save_entry.dirName);
|
||||||
|
//TODO: if this is a save, and it's not auto, then show a dialog
|
||||||
// fallthrough
|
// fallthrough
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,7 +553,8 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
case CELL_SAVEDATA_RECREATE_YES:
|
case CELL_SAVEDATA_RECREATE_YES:
|
||||||
case CELL_SAVEDATA_RECREATE_YES_RESET_OWNER:
|
case CELL_SAVEDATA_RECREATE_YES_RESET_OWNER:
|
||||||
{
|
{
|
||||||
// TODO?
|
|
||||||
|
// TODO: Only delete data, not owner info
|
||||||
for (const auto& entry : fs::dir(dir_path))
|
for (const auto& entry : fs::dir(dir_path))
|
||||||
{
|
{
|
||||||
if (!entry.is_directory)
|
if (!entry.is_directory)
|
||||||
|
@ -530,12 +563,13 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: probably not deleting owner info
|
||||||
if (!statSet->setParam)
|
if (!statSet->setParam)
|
||||||
{
|
{
|
||||||
// Savedata deleted and setParam is NULL: delete directory and abort operation
|
// Savedata deleted and setParam is NULL: delete directory and abort operation
|
||||||
if (fs::remove_dir(dir_path)) cellSaveData.error("savedata_op(): savedata directory %s deleted", save_entry.dirName);
|
if (fs::remove_dir(dir_path)) cellSaveData.error("savedata_op(): savedata directory %s deleted", save_entry.dirName);
|
||||||
|
|
||||||
return CELL_OK;
|
//return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -549,16 +583,13 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
|
|
||||||
{
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create save directory if necessary
|
// Create save directory if necessary
|
||||||
if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path))
|
if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path))
|
||||||
{
|
{
|
||||||
// Let's ignore this error for now
|
|
||||||
cellSaveData.warning("savedata_op(): failed to create %s", dir_path);
|
cellSaveData.warning("savedata_op(): failed to create %s", dir_path);
|
||||||
|
return CELL_SAVEDATA_ERROR_ACCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter the loop where the save files are read/created/deleted
|
// Enter the loop where the save files are read/created/deleted
|
||||||
|
@ -578,9 +609,13 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
|
|
||||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
||||||
{
|
{
|
||||||
|
//todo: display user prompt
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Show progress
|
||||||
|
// if it's not an auto load/save
|
||||||
|
|
||||||
std::string file_path;
|
std::string file_path;
|
||||||
|
|
||||||
switch (const u32 type = fileSet->fileType)
|
switch (const u32 type = fileSet->fileType)
|
||||||
|
@ -681,6 +716,51 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 static NEVER_INLINE save_op_get_list_item(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB, u32 userId)
|
||||||
|
{
|
||||||
|
|
||||||
|
//TODO: accurately get the current user
|
||||||
|
if (userId == 0)
|
||||||
|
{
|
||||||
|
userId = 1u;
|
||||||
|
}
|
||||||
|
std::string save_path = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/%s/", userId, dirName.get_ptr()));
|
||||||
|
std::string sfo = save_path + "param.sfo";
|
||||||
|
|
||||||
|
if (!fs::is_dir(save_path) && !fs::is_file(sfo))
|
||||||
|
{
|
||||||
|
cellSaveData.error("cellSaveDataGetListItem(): Savedata at %s does not exist", dirName);
|
||||||
|
return CELL_SAVEDATA_ERROR_NODATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto psf = psf::load_object(fs::file(sfo));
|
||||||
|
|
||||||
|
if (sysFileParam)
|
||||||
|
{
|
||||||
|
strcpy_trunc(sysFileParam->listParam, psf.at("SAVEDATA_LIST_PARAM").as_string());
|
||||||
|
strcpy_trunc(sysFileParam->title, psf.at("TITLE").as_string());
|
||||||
|
strcpy_trunc(sysFileParam->subTitle, psf.at("SUB_TITLE").as_string());
|
||||||
|
strcpy_trunc(sysFileParam->detail, psf.at("DETAIL").as_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::stat_t dir_info{};
|
||||||
|
if (!fs::stat(save_path, dir_info))
|
||||||
|
{
|
||||||
|
return CELL_SAVEDATA_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get file stats, namely directory
|
||||||
|
strcpy_trunc(dir->dirName, dirName.get_ptr());
|
||||||
|
dir->atime = dir_info.atime;
|
||||||
|
dir->ctime = dir_info.ctime;
|
||||||
|
dir->mtime = dir_info.mtime;
|
||||||
|
|
||||||
|
//TODO: Set bind in accordance to any problems
|
||||||
|
*bind = 0;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
s32 cellSaveDataListSave2(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList,
|
s32 cellSaveDataListSave2(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncList funcList,
|
||||||
PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata)
|
PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata)
|
||||||
|
@ -949,27 +1029,8 @@ s32 cellSaveDataFixedExport(ppu_thread& ppu, vm::cptr<char> dirName, u32 maxSize
|
||||||
s32 cellSaveDataGetListItem(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB)
|
s32 cellSaveDataGetListItem(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB)
|
||||||
{
|
{
|
||||||
cellSaveData.warning("cellSavaDataGetListItem(dirName=%s, dir=*0x%x, sysFileParam=*0x%x, bind=*0x%x, sizeKB=*0x%x)", dirName, dir, sysFileParam, bind, sizeKB);
|
cellSaveData.warning("cellSavaDataGetListItem(dirName=%s, dir=*0x%x, sysFileParam=*0x%x, bind=*0x%x, sizeKB=*0x%x)", dirName, dir, sysFileParam, bind, sizeKB);
|
||||||
|
|
||||||
std::string save_path = vfs::get(fmt::format("/dev_hdd0/home/00000001/savedata/%s/", dirName.get_ptr()));
|
return save_op_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, 0);
|
||||||
std::string sfo = save_path + "param.sfo";
|
|
||||||
|
|
||||||
if (!fs::is_dir(save_path) && !fs::is_file(sfo))
|
|
||||||
{
|
|
||||||
cellSaveData.error("cellSaveDataGetListItem(): Savedata at %s does not exist", dirName);
|
|
||||||
return CELL_SAVEDATA_ERROR_NODATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto psf = psf::load_object(fs::file(sfo));
|
|
||||||
|
|
||||||
if (sysFileParam)
|
|
||||||
{
|
|
||||||
strcpy_trunc(sysFileParam->listParam, psf.at("SAVEDATA_LIST_PARAM").as_string());
|
|
||||||
strcpy_trunc(sysFileParam->title, psf.at("TITLE").as_string());
|
|
||||||
strcpy_trunc(sysFileParam->subTitle, psf.at("SUB_TITLE").as_string());
|
|
||||||
strcpy_trunc(sysFileParam->detail, psf.at("DETAIL").as_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellSaveDataUserListDelete(ppu_thread& ppu, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
s32 cellSaveDataUserListDelete(ppu_thread& ppu, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||||
|
@ -1009,9 +1070,9 @@ s32 cellSaveDataUserFixedExport(ppu_thread& ppu, u32 userId, vm::cptr<char> dirN
|
||||||
|
|
||||||
s32 cellSaveDataUserGetListItem(u32 userId, vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB)
|
s32 cellSaveDataUserGetListItem(u32 userId, vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellSaveData);
|
cellSaveData.warning("cellSavaDataGetListItem(dirName=%s, dir=*0x%x, sysFileParam=*0x%x, bind=*0x%x, sizeKB=*0x%x, userID=*0x%x)", dirName, dir, sysFileParam, bind, sizeKB, userId);
|
||||||
|
|
||||||
return CELL_OK;
|
return save_op_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cellSysutil_SaveData_init()
|
void cellSysutil_SaveData_init()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace vm { using namespace ps3; }
|
namespace vm { using namespace ps3; }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace vm { using namespace ps3; }
|
namespace vm { using namespace ps3; }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue