int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf, mem_func_ptr_t<CellSaveDataListCallback> funcList, mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile, u32 container, u32 userdata_addr) { cellSysutil.Warning("cellSaveDataListLoad2(version=%d, setList_addr=0x%x, setBuf_addr=0x%x, funcList_addr=0x%x, funcStat_addr=0x%x, funcFile_addr=0x%x, container=%d, userdata_addr=0x%x)", version, setList.GetAddr(), setBuf.GetAddr(), funcList.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr); if (!setList.IsGood() || !setBuf.IsGood() || !funcList.IsGood() || !funcStat.IsGood() || !funcFile.IsGood()) return CELL_SAVEDATA_ERROR_PARAM; MemoryAllocator<CellSaveDataCBResult> result; MemoryAllocator<CellSaveDataListGet> listGet; MemoryAllocator<CellSaveDataListSet> listSet; MemoryAllocator<CellSaveDataStatGet> statGet; MemoryAllocator<CellSaveDataStatSet> statSet; MemoryAllocator<CellSaveDataFileGet> fileGet; MemoryAllocator<CellSaveDataFileSet> fileSet; std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user vfsDir dir(saveBaseDir); if(!dir.IsOpened()) return CELL_SAVEDATA_ERROR_INTERNAL; std::string dirNamePrefix = Memory.ReadString(setList->dirNamePrefix_addr); std::vector<SaveDataEntry> saveEntries; for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read()) { if (entry->flags & DirEntry_TypeDir && entry->name.substr(0,dirNamePrefix.size()) == dirNamePrefix) { // Count the amount of matches and the amount of listed directories listGet->dirListNum++; if (listGet->dirListNum > setBuf->dirListMax) continue; listGet->dirNum++; std::string saveDir = saveBaseDir + entry->name; addSaveDataEntry(saveEntries, saveDir); } } // Sort the entries and fill the listGet->dirList array std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder)); listGet->dirList.SetAddr(setBuf->buf_addr); CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr()); for (u32 i=0; i<saveEntries.size(); i++) { memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE); memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE); } funcList(result.GetAddr(), listGet.GetAddr(), listSet.GetAddr()); if (result->result < 0) { ConLog.Error("cellSaveDataListLoad2: CellSaveDataListCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } if (!listSet->fixedList.IsGood()) return CELL_SAVEDATA_ERROR_PARAM; setSaveDataList(saveEntries, (u32)listSet->fixedList.GetAddr(), listSet->fixedListNum); if (listSet->newData.IsGood()) addNewSaveDataEntry(saveEntries, (u32)listSet->newData.GetAddr()); if (saveEntries.size() == 0) { ConLog.Warning("cellSaveDataListLoad2: No save entries found!"); // TODO: Find a better way to handle this error return CELL_SAVEDATA_RET_OK; } u32 focusIndex = focusSaveDataEntry(saveEntries, listSet->focusPosition); // TODO: Display the dialog here u32 selectedIndex = focusIndex; // TODO: Until the dialog is implemented, select always the focused entry getSaveDataStat(saveEntries[selectedIndex], statGet.GetAddr()); result->userdata_addr = userdata_addr; funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr()); Memory.Free(statGet->fileList.GetAddr()); if (result->result < 0) { ConLog.Error("cellSaveDataListLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } /*if (statSet->setParam.IsGood()) // TODO: Write PARAM.SFO file */ fileGet->excSize = 0; while(true) { funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr()); if (result->result < 0) { ConLog.Error("cellSaveDataListLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) break; switch (fileSet->fileOperation) { case CELL_SAVEDATA_FILEOP_READ: fileGet->excSize = readSaveDataFile(fileSet.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName); break; case CELL_SAVEDATA_FILEOP_WRITE: fileGet->excSize = writeSaveDataFile(fileSet.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName); break; case CELL_SAVEDATA_FILEOP_DELETE: case CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC: ConLog.Warning("cellSaveDataListLoad2: TODO: fileSet->fileOperation not yet implemented"); break; } } // TODO: There are other returns in this function that doesn't free the memory. Fix it (without using goto's, please). for (auto& entry : saveEntries) { delete[] entry.iconBuf; entry.iconBuf = nullptr; } return CELL_SAVEDATA_RET_OK; }
int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf, mem_func_ptr_t<CellSaveDataListCallback> funcList, mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile, u32 container, u32 userdata_addr) { cellSysutil->Warning("cellSaveDataListLoad2(version=%d, setList_addr=0x%x, setBuf_addr=0x%x, funcList_addr=0x%x, funcStat_addr=0x%x, funcFile_addr=0x%x, container=%d, userdata_addr=0x%x)", version, setList.GetAddr(), setBuf.GetAddr(), funcList.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr); MemoryAllocator<CellSaveDataCBResult> result; MemoryAllocator<CellSaveDataListGet> listGet; MemoryAllocator<CellSaveDataListSet> listSet; MemoryAllocator<CellSaveDataStatGet> statGet; MemoryAllocator<CellSaveDataStatSet> statSet; std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user vfsDir dir(saveBaseDir); if(!dir.IsOpened()) return CELL_SAVEDATA_ERROR_INTERNAL; std::string dirNamePrefix = Memory.ReadString(setList->dirNamePrefix_addr); std::vector<SaveDataEntry> saveEntries; for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read()) { if (entry->flags & DirEntry_TypeDir && entry->name.substr(0,dirNamePrefix.size()) == dirNamePrefix) { // Count the amount of matches and the amount of listed directories listGet->dirListNum++; if (listGet->dirListNum > setBuf->dirListMax) continue; listGet->dirNum++; std::string saveDir = saveBaseDir + entry->name; addSaveDataEntry(saveEntries, saveDir); } } // Sort the entries and fill the listGet->dirList array std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder)); listGet->dirList.SetAddr(setBuf->buf_addr); CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr()); for (u32 i=0; i<saveEntries.size(); i++) { memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE); memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE); } funcList(result.GetAddr(), listGet.GetAddr(), listSet.GetAddr()); if (result->result < 0) { LOG_ERROR(HLE, "cellSaveDataListLoad2: CellSaveDataListCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } setSaveDataList(saveEntries, (u32)listSet->fixedList.GetAddr(), listSet->fixedListNum); if (listSet->newData.GetAddr()) addNewSaveDataEntry(saveEntries, (u32)listSet->newData.GetAddr()); if (saveEntries.size() == 0) { LOG_WARNING(HLE, "cellSaveDataListLoad2: No save entries found!"); // TODO: Find a better way to handle this error return CELL_SAVEDATA_RET_OK; } u32 focusIndex = focusSaveDataEntry(saveEntries, listSet->focusPosition); // TODO: Display the dialog here u32 selectedIndex = focusIndex; // TODO: Until the dialog is implemented, select always the focused entry getSaveDataStat(saveEntries[selectedIndex], statGet.GetAddr()); result->userdata_addr = userdata_addr; funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr()); Memory.Free(statGet->fileList.GetAddr()); if (result->result < 0) { LOG_ERROR(HLE, "cellSaveDataListLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } /*if (statSet->setParam.GetAddr()) // TODO: Write PARAM.SFO file */ // Enter the loop where the save files are read/created/deleted. s32 ret = modifySaveDataFiles(funcFile, result.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName); return ret; }
// Functions int cellSaveDataListSave2(u32 version, vm::ptr<CellSaveDataSetList> setList, vm::ptr<CellSaveDataSetBuf> setBuf, vm::ptr<CellSaveDataListCallback> funcList, vm::ptr<CellSaveDataStatCallback> funcStat, vm::ptr<CellSaveDataFileCallback> funcFile, u32 container, vm::ptr<void> userdata) { cellSysutil->Warning("cellSaveDataListSave2(version=%d, setList_addr=0x%x, setBuf_addr=0x%x, funcList_addr=0x%x, funcStat_addr=0x%x, funcFile_addr=0x%x, container=0x%x, userdata_addr=0x%x)", version, setList.addr(), setBuf.addr(), funcList.addr(), funcStat.addr(), funcFile.addr(), container, userdata.addr()); vm::var<CellSaveDataCBResult> result; vm::var<CellSaveDataListGet> listGet; vm::var<CellSaveDataListSet> listSet; vm::var<CellSaveDataStatGet> statGet; vm::var<CellSaveDataStatSet> statSet; std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user vfsDir dir(saveBaseDir); if(!dir.IsOpened()) return CELL_SAVEDATA_ERROR_INTERNAL; std::string dirNamePrefix = setList->dirNamePrefix.get_ptr(); std::vector<SaveDataEntry> saveEntries; for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read()) { if (entry->flags & DirEntry_TypeDir && entry->name.substr(0,dirNamePrefix.size()) == dirNamePrefix) { // Count the amount of matches and the amount of listed directories listGet->dirListNum++; if (listGet->dirListNum > setBuf->dirListMax) continue; listGet->dirNum++; std::string saveDir = saveBaseDir + entry->name; addSaveDataEntry(saveEntries, saveDir); } } // Sort the entries and fill the listGet->dirList array std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder)); listGet->dirList = vm::bptr<CellSaveDataDirList>::make(setBuf->buf.addr()); auto dirList = vm::get_ptr<CellSaveDataDirList>(listGet->dirList.addr()); for (u32 i=0; i<saveEntries.size(); i++) { strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); *dirList[i].reserved = {}; } funcList(result, listGet, listSet); if (result->result < 0) { cellSysutil->Error("cellSaveDataListSave2: CellSaveDataListCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } setSaveDataList(saveEntries, vm::ptr<CellSaveDataDirList>::make(listSet->fixedList.addr()), listSet->fixedListNum); if (listSet->newData) addNewSaveDataEntry(saveEntries, vm::ptr<CellSaveDataListNewData>::make(listSet->newData.addr())); if (saveEntries.size() == 0) { cellSysutil->Warning("cellSaveDataListSave2: No save entries found!"); // TODO: Find a better way to handle this error return CELL_SAVEDATA_RET_OK; } u32 focusIndex = focusSaveDataEntry(saveEntries, listSet->focusPosition); // TODO: Display the dialog here u32 selectedIndex = focusIndex; // TODO: Until the dialog is implemented, select always the focused entry getSaveDataStat(saveEntries[selectedIndex], statGet); result->userdata = userdata; funcStat(result, statGet, statSet); Memory.Free(statGet->fileList.addr()); if (result->result < 0) { cellSysutil->Error("cellSaveDataListLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } /*if (statSet->setParam) addNewSaveDataEntry(saveEntries, (u32)listSet->newData.addr()); // TODO: This *is* wrong */ // Enter the loop where the save files are read/created/deleted. s32 ret = modifySaveDataFiles(funcFile, result, saveBaseDir + (char*)statGet->dir.dirName); return ret; }