mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 17:19:28 +01:00
sceReg: Set category_version to the installed firmware's schema version
The shell writes the default of every registry key added after the stored category_version, and some of those (umd_autoboot) are now mapped to our config. Each firmware's version is the default in its registry schema table, in vshmain.prx (common_util.prx before 2.00). Installing a firmware now stores it, and headless sets it from the NAND's firmware. Also builds the config setting lookup in headless and libretro: without g_Config.Init(), sceReg served its static dump instead of the mapped config values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2fd47cd7eb
commit
4b74eccc38
4 files changed
+47
No files matched your search
@@ -1343,6 +1343,33 @@ bool EraseInstalledFirmware(const Path &nandRoot, std::string *error) {
|
||||
return success;
|
||||
}
|
||||
|
||||
int SceRegCategoryVersionForFirmware(std::string_view version) {
|
||||
// The default of /REGISTRY/category_version in each firmware's registry schema, a table of
|
||||
// { name, type, size, default } entries in vsh/module/vshmain.prx (common_util.prx before 2.00).
|
||||
// When the stored version is below this, the shell writes the default of every key added since
|
||||
// that version (from 1, that includes umd_autoboot). One above it means a corrupt registry.
|
||||
static const struct {
|
||||
int firmware; // The first firmware with this version, as FirmwareVersionToInt() gives it.
|
||||
int categoryVersion;
|
||||
} versions[] = {
|
||||
{ 100, 0x00 }, { 150, 0x01 }, { 200, 0x06 }, { 250, 0x13 }, { 260, 0x14 }, { 270, 0x1b },
|
||||
{ 280, 0x20 }, { 300, 0x26 }, { 310, 0x2c }, { 330, 0x31 }, { 350, 0x35 }, { 360, 0x36 },
|
||||
{ 370, 0x3b }, { 380, 0x3e }, { 395, 0x40 }, { 405, 0x43 }, { 420, 0x46 }, { 500, 0x4c },
|
||||
{ 550, 0x58 }, { 570, 0x61 }, { 600, 0x63 }, { 620, 0x64 }, { 630, 0x66 },
|
||||
};
|
||||
const int fw = FirmwareVersionToInt(version);
|
||||
if (fw < versions[0].firmware) {
|
||||
return 1;
|
||||
}
|
||||
int categoryVersion = versions[0].categoryVersion;
|
||||
for (const auto &v : versions) {
|
||||
if (fw >= v.firmware) {
|
||||
categoryVersion = v.categoryVersion;
|
||||
}
|
||||
}
|
||||
return categoryVersion;
|
||||
}
|
||||
|
||||
int FirmwareVersionToInt(std::string_view version) {
|
||||
const size_t dot = version.find('.');
|
||||
if (dot == std::string_view::npos || dot == 0 || dot + 1 >= version.size()) {
|
||||
@@ -1674,6 +1701,11 @@ bool InstallFirmware(const Path &updater, const Path &nandRoot, const PSARUnpack
|
||||
if (ok) {
|
||||
ok = SwapStagingIntoPlace(nandRoot, staging, error);
|
||||
}
|
||||
if (ok) {
|
||||
// Match the registry to the new firmware's schema, so its shell doesn't reset the
|
||||
// settings (which sceReg maps to our config) to its defaults at first boot.
|
||||
g_Config.iSceRegCategoryVersion = SceRegCategoryVersionForFirmware(stats->firmwareVersion);
|
||||
}
|
||||
|
||||
// Whether it worked or not, don't leave the staging copy behind.
|
||||
if (File::Exists(staging) && !File::DeleteDirRecursively(staging)) {
|
||||
|
||||
@@ -181,6 +181,9 @@ bool EraseInstalledFirmware(const Path &nandRoot, std::string *error);
|
||||
// makes the result safe to compare with: an unknown version is older than every real one.
|
||||
int FirmwareVersionToInt(std::string_view version);
|
||||
|
||||
// The /REGISTRY/category_version the shell of this firmware expects. 1 for an unknown version.
|
||||
int SceRegCategoryVersionForFirmware(std::string_view version);
|
||||
|
||||
// The firmware versions we can actually boot the VSH (XMB) on. Every other version loads, but
|
||||
// the module patches it needs are version-specific, so it won't get anywhere.
|
||||
bool FirmwareVersionSupportsVSH(std::string_view version);
|
||||
|
||||
@@ -941,6 +941,8 @@ int main(int argc, const char* argv[]) {
|
||||
#endif
|
||||
PROFILE_INIT();
|
||||
TimeInit();
|
||||
// Builds the pointer to setting lookup, which sceReg's registry mapping uses.
|
||||
g_Config.Init();
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
if (!IsDebuggerPresent()) {
|
||||
SetCleanExitOnAssert();
|
||||
@@ -1445,6 +1447,14 @@ int main(int argc, const char* argv[]) {
|
||||
coreParameter.nandRoot = nand;
|
||||
}
|
||||
|
||||
// Headless doesn't keep a config, so set the registry version that installing this firmware
|
||||
// in the app would have stored.
|
||||
{
|
||||
InstalledFirmwareInfo firmwareInfo;
|
||||
ReadInstalledFirmwareInfo(g_Config.nandRootDirectory, &firmwareInfo, false);
|
||||
g_Config.iSceRegCategoryVersion = SceRegCategoryVersionForFirmware(firmwareInfo.version);
|
||||
}
|
||||
|
||||
// Placed here rather than with the other early-exit subcommands above, because resolving a
|
||||
// "flash0:/kd/foo.prx" module path needs nandRootDirectory, which is only settled just above.
|
||||
if (cmdLineOptions.reDecrypt.has_value()) {
|
||||
|
||||
@@ -1225,6 +1225,8 @@ void retro_init(void)
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
|
||||
libretro_supports_bitmasks = true;
|
||||
|
||||
// Builds the pointer to setting lookup, which sceReg's registry mapping uses.
|
||||
g_Config.Init();
|
||||
g_Config.Load("", "");
|
||||
g_Config.iInternalResolution = 0;
|
||||
|
||||
|
||||
Reference in new issue
Block a user