From dac2407a3603ce6f9d24a18cd3b89856c4931afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 23 Feb 2026 11:01:18 +0100 Subject: [PATCH] sceIo: Add support for microseconds in filetimes (not implemented in platforms yet) --- Common/File/DirListing.h | 12 ++++++-- Core/Dialog/SavedataParam.cpp | 35 ++++++++++++------------ Core/FileSystems/DirectoryFileSystem.cpp | 4 +++ Core/FileSystems/FileSystem.h | 6 ++-- Core/HLE/sceIo.cpp | 17 ++++++------ Core/HLE/sceIo.h | 2 +- 6 files changed, 42 insertions(+), 34 deletions(-) diff --git a/Common/File/DirListing.h b/Common/File/DirListing.h index 20c5667ad3..60e6ccc900 100644 --- a/Common/File/DirListing.h +++ b/Common/File/DirListing.h @@ -11,17 +11,23 @@ namespace File { struct FileInfo { - std::string name; + std::string name; // local name in directory Path fullName; + bool exists = false; bool isDirectory = false; bool isWritable = false; - uint64_t size = 0; - + uint64_t size = 0; // in bytes + // time_t uint64_t atime = 0; uint64_t mtime = 0; uint64_t ctime = 0; + // Microseconds, addition to the time_t. + int atimeUs = 0; + int mtimeUs = 0; + int ctimeUs = 0; + // Access bitfield uint32_t access = 0; // st_mode & 0x1ff bool operator <(const FileInfo &other) const; diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index f00642a891..c2be8911d8 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -1236,14 +1236,16 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param) { entries[i].st_mode = 0x11FF; if (sfoFiles[i].exists) { - __IoCopyDate(entries[i].st_ctime, sfoFiles[i].ctime); - __IoCopyDate(entries[i].st_atime, sfoFiles[i].atime); - __IoCopyDate(entries[i].st_mtime, sfoFiles[i].mtime); + ConvertTmToPspDateTime(entries[i].st_ctime, sfoFiles[i].ctime, sfoFiles[i].ctimeUs); + ConvertTmToPspDateTime(entries[i].st_atime, sfoFiles[i].atime, sfoFiles[i].atimeUs); + ConvertTmToPspDateTime(entries[i].st_mtime, sfoFiles[i].mtime, sfoFiles[i].mtimeUs); } else { - __IoCopyDate(entries[i].st_ctime, validDir[i].ctime); - __IoCopyDate(entries[i].st_atime, validDir[i].atime); - __IoCopyDate(entries[i].st_mtime, validDir[i].mtime); + // What? + ConvertTmToPspDateTime(entries[i].st_ctime, validDir[i].ctime, validDir[i].ctimeUs); + ConvertTmToPspDateTime(entries[i].st_atime, validDir[i].atime, validDir[i].atimeUs); + ConvertTmToPspDateTime(entries[i].st_mtime, validDir[i].mtime, validDir[i].mtimeUs); } + // folder name without gamename (max 20 u8) std::string outName = validDir[i].name.substr(GetGameName(param).size()); memset(entries[i].name, 0, sizeof(entries[i].name)); @@ -1364,9 +1366,9 @@ int SavedataParam::GetFilesList(SceUtilitySavedataParam *param, u32 requestAddr) entry->st_mode = 0x21FF; entry->st_size = file->size + sizeOffset; - __IoCopyDate(entry->st_ctime, file->ctime); - __IoCopyDate(entry->st_atime, file->atime); - __IoCopyDate(entry->st_mtime, file->mtime); + ConvertTmToPspDateTime(entry->st_ctime, file->ctime, file->ctimeUs); + ConvertTmToPspDateTime(entry->st_atime, file->atime, file->atimeUs); + ConvertTmToPspDateTime(entry->st_mtime, file->mtime, file->mtimeUs); // TODO: Probably actually 13 + 3 pad... strncpy(entry->name, file->name.c_str(), 16); entry->name[15] = '\0'; @@ -1467,14 +1469,12 @@ bool SavedataParam::GetSize(SceUtilitySavedataParam *param) { return exists; } -void SavedataParam::Clear() -{ - if (saveDataList) - { - for (int i = 0; i < saveNameListDataCount; i++) - { - if (saveDataList[i].texture != NULL && (!noSaveIcon || saveDataList[i].texture != noSaveIcon->texture)) +void SavedataParam::Clear() { + if (saveDataList) { + for (int i = 0; i < saveNameListDataCount; i++) { + if (saveDataList[i].texture && (!noSaveIcon || saveDataList[i].texture != noSaveIcon->texture)) { delete saveDataList[i].texture; + } saveDataList[i].texture = NULL; } @@ -1491,8 +1491,7 @@ void SavedataParam::Clear() } } -int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) -{ +int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) { pspParam = param; if (!pspParam) { Clear(); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 3206476267..a459b125dc 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -776,6 +776,10 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { localtime_r((time_t*)&ctime, &x.ctime); localtime_r((time_t*)&mtime, &x.mtime); + x.atimeUs = info.atimeUs; + x.ctimeUs = info.ctimeUs; + x.mtimeUs = info.mtimeUs; + return ReplayApplyDiskFileInfo(x, CoreTiming::GetGlobalTimeUs()); } diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 8c46e6f77d..90dfc50649 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -118,9 +118,9 @@ struct PSPFileInfo { bool exists = false; FileType type = FILETYPE_NORMAL; - tm atime{}; - tm ctime{}; - tm mtime{}; + tm atime{}; int atimeUs = 0; + tm ctime{}; int ctimeUs = 0; + tm mtime{}; int mtimeUs = 0; bool isOnSectorSystem = false; u32 startSector = 0; diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 84f3edd604..b647a1ecd9 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -905,18 +905,17 @@ u64 __IoCompleteAsyncIO(FileNode *f) { return 0; } -void __IoCopyDate(ScePspDateTime& date_out, const tm& date_in) -{ - date_out.year = date_in.tm_year+1900; - date_out.month = date_in.tm_mon+1; +void ConvertTmToPspDateTime(ScePspDateTime& date_out, const tm& date_in, int microSeconds) { + date_out.year = date_in.tm_year + 1900; + date_out.month = date_in.tm_mon + 1; date_out.day = date_in.tm_mday; date_out.hour = date_in.tm_hour; date_out.minute = date_in.tm_min; date_out.second = date_in.tm_sec; - date_out.microsecond = 0; + date_out.microsecond = microSeconds; } -static void __IoGetStat(SceIoStat *stat, PSPFileInfo &info) { +static void __IoGetStat(SceIoStat *stat, const PSPFileInfo &info) { memset(stat, 0xfe, sizeof(SceIoStat)); int type, attr; @@ -931,9 +930,9 @@ static void __IoGetStat(SceIoStat *stat, PSPFileInfo &info) { stat->st_mode = type | info.access; stat->st_attr = attr; stat->st_size = info.size; - __IoCopyDate(stat->st_a_time, info.atime); - __IoCopyDate(stat->st_c_time, info.ctime); - __IoCopyDate(stat->st_m_time, info.mtime); + ConvertTmToPspDateTime(stat->st_a_time, info.atime, info.atimeUs); + ConvertTmToPspDateTime(stat->st_c_time, info.ctime, info.ctimeUs); + ConvertTmToPspDateTime(stat->st_m_time, info.mtime, info.mtimeUs); stat->st_private[0] = info.startSector; } diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index d6a4d6a824..06963aef05 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -35,7 +35,7 @@ u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 ou int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec); u32 __IoGetFileHandleFromId(u32 id, u32 &outError); -void __IoCopyDate(ScePspDateTime& date_out, const tm& date_in); +void ConvertTmToPspDateTime(ScePspDateTime& date_out, const tm& date_in, int microSeconds); KernelObject *__KernelFileNodeObject(); KernelObject *__KernelDirListingObject();