mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-08-31 09:45:24 +02:00
GameInfoCache: report the firmware updater bundled on a game disc
Adds GameInfoFlags::BUNDLED_UPDATE_INFO, holding the version, title, size and timestamp of the updater in PSP_GAME/SYSDIR/UPDATE. It comes from the PARAM.SFO and the directory entry next to the archive, so it's a couple of small reads on the ISOFileSystem the worker already has open - no decryption, and DATA.BIN itself is only sniffed for its magic. Only computed for ISOs; everything else is marked complete with an empty struct. ISOFileSystem now parses the date out of the ISO9660 directory record, stored as Unix UTC seconds and reported as the PSP's atime/ctime/mtime. Those used to always read back as zero, so games calling sceIoGetstat on a UMD file saw 1900 where hardware gives the mastering date. Shown on GameScreen as e.g. "Firmware update on disc: 6.60 (2011-10-05), 25.6 MB". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0149QcTVgZEXKXbgHyvXF4ZY
This commit is contained in:
co-authored by
Claude Opus 5
parent
c09e6bddaa
commit
396f9e802d
@@ -18,8 +18,10 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/File/FileUtil.h" // for localtime_r on Windows
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Common/StringUtils.h"
|
||||
@@ -138,6 +140,39 @@ struct VolDescriptor {
|
||||
char zeroos[653];
|
||||
};
|
||||
|
||||
// From http://howardhinnant.github.io/date_algorithms.html - same one sceRtc.cpp uses. Beats
|
||||
// timegm(), which isn't portable, and mktime(), which would drag the host's timezone in.
|
||||
static s64 DaysFromCivil(s64 y, u32 m, u32 d) {
|
||||
y -= m <= 2;
|
||||
const s64 era = (y >= 0 ? y : y - 399) / 400;
|
||||
const u32 yoe = (u32)(y - era * 400); // [0, 399]
|
||||
const u32 doy = (153 * (m > 2 ? m - 3 : m + 9) + 2) / 5 + d - 1; // [0, 365]
|
||||
const u32 doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
|
||||
return era * 146097 + (s64)doe - 719468;
|
||||
}
|
||||
|
||||
// The 7-byte date in a directory record, as Unix UTC seconds. Returns 0 if there isn't a real
|
||||
// date in there - plenty of ISOs leave it zeroed, and "1900-00-00" isn't worth propagating.
|
||||
static s64 UnixTimeFromDirectoryEntry(const DirectoryEntry &dir) {
|
||||
if (dir.month < 1 || dir.month > 12 || dir.day < 1 || dir.day > 31) {
|
||||
return 0;
|
||||
}
|
||||
// years is an offset from 1900, and offsetFromGMT is a signed count of 15-minute steps.
|
||||
const s64 days = DaysFromCivil(1900 + (s64)dir.years, dir.month, dir.day);
|
||||
return days * 86400 + dir.hour * 3600 + dir.minute * 60 + dir.second - (s64)(s8)dir.offsetFromGMT * 15 * 60;
|
||||
}
|
||||
|
||||
// ISO9660 has one timestamp per file, so it goes into all three of the PSP's. Local time, to
|
||||
// match what the other file systems report.
|
||||
static void FillFileTimes(PSPFileInfo *info, s64 unixTime) {
|
||||
if (unixTime == 0) {
|
||||
return;
|
||||
}
|
||||
const time_t t = (time_t)unixTime;
|
||||
localtime_r(&t, &info->mtime);
|
||||
info->atime = info->ctime = info->mtime;
|
||||
}
|
||||
|
||||
// Removes version numbers from filenames.
|
||||
static std::string_view CleanISOFileName(std::string_view name) {
|
||||
auto pos = name.find(';');
|
||||
@@ -258,6 +293,7 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) const {
|
||||
entry->startsector = dir.firstDataSector;
|
||||
entry->dirsize = dir.dataLength;
|
||||
entry->valid = isFile; // Can pre-mark as valid if file, as we don't recurse into those.
|
||||
entry->recordTime = UnixTimeFromDirectoryEntry(dir);
|
||||
VERBOSE_LOG(Log::FileSystem, "%s: %s %08x %08x %d", entry->isDirectory ? "D" : "F", entry->name.c_str(), (u32)dir.firstDataSector, entry->startingPosition, entry->startingPosition);
|
||||
|
||||
// Round down to avoid any false reports.
|
||||
@@ -662,6 +698,7 @@ PSPFileInfo ISOFileSystem::GetFileInfo(std::string filename) {
|
||||
x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
|
||||
x.isOnSectorSystem = true;
|
||||
x.startSector = entry->startingPosition / 2048;
|
||||
FillFileTimes(&x, entry->recordTime);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -679,6 +716,7 @@ PSPFileInfo ISOFileSystem::GetFileInfoByHandle(u32 handle) {
|
||||
x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
|
||||
x.isOnSectorSystem = true;
|
||||
x.startSector = entry->startingPosition / 2048;
|
||||
FillFileTimes(&x, entry->recordTime);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -714,6 +752,7 @@ std::vector<PSPFileInfo> ISOFileSystem::GetDirListing(std::string_view path, boo
|
||||
x.type = e->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
|
||||
x.isOnSectorSystem = true;
|
||||
x.startSector = e->startingPosition/2048;
|
||||
FillFileTimes(&x, e->recordTime);
|
||||
x.sectorSize = sectorSize;
|
||||
x.numSectors = (u32)((e->size + sectorSize - 1) / sectorSize);
|
||||
myVector.push_back(x);
|
||||
|
||||
Reference in New Issue
Block a user