From 28bbb7c5b049e7f093a318a6c3c2a33716e47b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 13:48:11 +0200 Subject: [PATCH 01/11] Update the sceReg registry to include the CONFIG category --- Core/HLE/sceReg.cpp | 1090 ++++++++++++++++++++++++++++++------------- 1 file changed, 775 insertions(+), 315 deletions(-) diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index b70ea5eb42..2d51cf1d9d 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -20,13 +20,12 @@ enum RegKeyTypes { typedef unsigned int REGHANDLE; -struct RegParam -{ - unsigned int regtype; /* 0x0, set to 1 only for system */ - char name[256]; /* 0x4-0x104 */ - unsigned int namelen; /* 0x104 */ - unsigned int unk2; /* 0x108 */ - unsigned int unk3; /* 0x10C */ +struct RegParam { + unsigned int regtype; /* 0x0, set to 1 only for system */ + char name[256]; /* 0x4-0x104 */ + unsigned int namelen; /* 0x104 */ + unsigned int unk2; /* 0x108 */ + unsigned int unk3; /* 0x10C */ }; struct OpenCategory { @@ -53,374 +52,373 @@ enum class ValueType { struct KeyValue { std::string name; ValueType type; - std::string strValue; // also can be used for bin + const char *strValue; // also can be used for bin. Note: can't be std::string/string_view, will cut off the length. int intValue; const KeyValue *dirContents; // intValue is the count. }; -// Dump of the PSP registry using tests/misc/reg.prx in pspautotests - // TODO: /DATA/FONT/PROPERTY could just be generated from our fontRegistry in sceFont.cpp. +// Dump of the PSP registry using tests/misc/reg.prx in pspautotests // Dump of /DATA/FONT/PROPERTY/INFO0 static const KeyValue tree_DATA_FONT_PROPERTY_INFO0[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000067 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000001 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro DB" }, - { "file_name", ValueType::STR, "jpn0.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x67 }, // decimal: 103 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro DB", 20 }, + { "file_name", ValueType::STR, "jpn0.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO1 static const KeyValue tree_DATA_FONT_PROPERTY_INFO1[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000001 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn0.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn0.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO2 static const KeyValue tree_DATA_FONT_PROPERTY_INFO2[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000001 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn1.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn1.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO3 static const KeyValue tree_DATA_FONT_PROPERTY_INFO3[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000002 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn2.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn2.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO4 static const KeyValue tree_DATA_FONT_PROPERTY_INFO4[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000002 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn3.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn3.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO5 static const KeyValue tree_DATA_FONT_PROPERTY_INFO5[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000005 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn4.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn4.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO6 static const KeyValue tree_DATA_FONT_PROPERTY_INFO6[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000005 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn5.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn5.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO7 static const KeyValue tree_DATA_FONT_PROPERTY_INFO7[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000006 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn6.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x6 }, // decimal: 6 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn6.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO8 static const KeyValue tree_DATA_FONT_PROPERTY_INFO8[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000006 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn7.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x6 }, // decimal: 6 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn7.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO9 static const KeyValue tree_DATA_FONT_PROPERTY_INFO9[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000001 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn8.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn8.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO10 static const KeyValue tree_DATA_FONT_PROPERTY_INFO10[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000001 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn9.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn9.pgf", 9 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO11 static const KeyValue tree_DATA_FONT_PROPERTY_INFO11[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000002 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn10.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn10.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO12 static const KeyValue tree_DATA_FONT_PROPERTY_INFO12[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000002 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn11.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn11.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO13 static const KeyValue tree_DATA_FONT_PROPERTY_INFO13[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000005 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn12.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn12.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO14 static const KeyValue tree_DATA_FONT_PROPERTY_INFO14[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000005 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn13.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn13.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO15 static const KeyValue tree_DATA_FONT_PROPERTY_INFO15[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000006 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin" }, - { "file_name", ValueType::STR, "ltn14.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x6 }, // decimal: 6 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-NewRodin Pro Latin", 23 }, + { "file_name", ValueType::STR, "ltn14.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO16 static const KeyValue tree_DATA_FONT_PROPERTY_INFO16[] = { - { "h_size", ValueType::INT, "", (int)0x000001c0 }, - { "v_size", ValueType::INT, "", (int)0x000001c0 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000002 }, - { "style", ValueType::INT, "", (int)0x00000006 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000002 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000001 }, - { "font_name", ValueType::STR, "FTT-Matisse Pro Latin" }, - { "file_name", ValueType::STR, "ltn15.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "v_size", ValueType::INT, "", (int)0x1c0 }, // decimal: 448 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "style", ValueType::INT, "", (int)0x6 }, // decimal: 6 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "font_name", ValueType::STR, "FTT-Matisse Pro Latin", 22 }, + { "file_name", ValueType::STR, "ltn15.pgf", 10 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY/INFO17 static const KeyValue tree_DATA_FONT_PROPERTY_INFO17[] = { - { "h_size", ValueType::INT, "", (int)0x00000288 }, - { "v_size", ValueType::INT, "", (int)0x00000288 }, - { "h_resolution", ValueType::INT, "", (int)0x00002000 }, - { "v_resolution", ValueType::INT, "", (int)0x00002000 }, - { "extra_attributes", ValueType::INT, "", (int)0x00000000 }, - { "weight", ValueType::INT, "", (int)0x00000000 }, - { "family_code", ValueType::INT, "", (int)0x00000001 }, - { "style", ValueType::INT, "", (int)0x00000001 }, - { "sub_style", ValueType::INT, "", (int)0x00000000 }, - { "language_code", ValueType::INT, "", (int)0x00000003 }, - { "region_code", ValueType::INT, "", (int)0x00000000 }, - { "country_code", ValueType::INT, "", (int)0x00000003 }, - { "font_name", ValueType::STR, "AsiaNHH(512Johab)" }, - { "file_name", ValueType::STR, "kr0.pgf" }, - { "expire_date", ValueType::INT, "", (int)0x00000000 }, - { "shadow_option", ValueType::INT, "", (int)0x00000000 }, + { "h_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "v_size", ValueType::INT, "", (int)0x288 }, // decimal: 648 + { "h_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "v_resolution", ValueType::INT, "", (int)0x2000 }, // decimal: 8192 + { "extra_attributes", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "weight", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "family_code", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "style", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "sub_style", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language_code", ValueType::INT, "", (int)0x3 }, // decimal: 3 + { "region_code", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "country_code", ValueType::INT, "", (int)0x3 }, // decimal: 3 + { "font_name", ValueType::STR, "AsiaNHH(512Johab)", 18 }, + { "file_name", ValueType::STR, "kr0.pgf", 8 }, + { "expire_date", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shadow_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA/FONT/PROPERTY @@ -447,19 +445,19 @@ static const KeyValue tree_DATA_FONT_PROPERTY[] = { // Dump of /DATA/FONT static const KeyValue tree_DATA_FONT[] = { - { "path_name", ValueType::STR, "flash0:/font" }, - { "num_fonts", ValueType::INT, "", (int)0x00000012 }, + { "path_name", ValueType::STR, "flash0:/font", 13 }, + { "num_fonts", ValueType::INT, "", (int)0x12 }, // decimal: 18 { "PROPERTY", ValueType::DIR, "", ARRAY_SIZE(tree_DATA_FONT_PROPERTY), tree_DATA_FONT_PROPERTY }, }; // Dump of /DATA/COUNT static const KeyValue tree_DATA_COUNT[] = { - { "boot_count", ValueType::INT, "", (int)0x00000000 }, - { "game_exec_count", ValueType::INT, "", (int)0x00000046 }, - { "slide_count", ValueType::INT, "", (int)0x00000000 }, - { "usb_connect_count", ValueType::INT, "", (int)0x000000ec }, - { "wifi_connect_count", ValueType::INT, "", (int)0x00000000 }, - { "psn_access_count", ValueType::INT, "", (int)0x00000000 }, + { "boot_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "game_exec_count", ValueType::INT, "", (int)0x56 }, // decimal: 86 + { "slide_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "usb_connect_count", ValueType::INT, "", (int)0xf8 }, // decimal: 248 + { "wifi_connect_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "psn_access_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 }; // Dump of /DATA @@ -470,20 +468,482 @@ static const KeyValue tree_DATA[] = { // Dump of /SYSPROFILE/RESOLUTION static const KeyValue tree_SYSPROFILE_RESOLUTION[] = { - { "horizontal", ValueType::INT, "", (int)0x00002012 }, - { "vertical", ValueType::INT, "", (int)0x00002012 }, + { "horizontal", ValueType::INT, "", (int)0x2012 }, // decimal: 8210 + { "vertical", ValueType::INT, "", (int)0x2012 }, // decimal: 8210 }; // Dump of /SYSPROFILE static const KeyValue tree_SYSPROFILE[] = { - { "sound_reduction", ValueType::INT, "", (int)0x00000000 }, + { "sound_reduction", ValueType::INT, "", (int)0x0 }, // decimal: 0 { "RESOLUTION", ValueType::DIR, "", ARRAY_SIZE(tree_SYSPROFILE_RESOLUTION), tree_SYSPROFILE_RESOLUTION }, }; -// There's also SYSTEM, CONFIG, REGISTRY but not adding them until they are needed. +// Dump of /CONFIG/VIDEO +static const KeyValue tree_CONFIG_VIDEO[] = { + { "menu_language", ValueType::BIN, "en", 2 }, + { "sound_language", ValueType::BIN, "00", 2 }, + { "subtitle_language", ValueType::BIN, "en", 2 }, + { "appended_volume", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "lr_button_enable", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "list_play_mode", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "title_display_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "output_ext_menu", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "output_ext_func", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/PHOTO +static const KeyValue tree_CONFIG_PHOTO[] = { + { "slideshow_speed", ValueType::INT, "", (int)0x1 }, // decimal: 1 +}; + +// Dump of /CONFIG/MUSIC +static const KeyValue tree_CONFIG_MUSIC[] = { + { "wma_play", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "visualizer_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "track_info_mode", ValueType::INT, "", (int)0x1 }, // decimal: 1 +}; + +// Dump of /CONFIG/BROWSER +static const KeyValue tree_CONFIG_BROWSER[] = { + { "home_uri", ValueType::STR, "", 1 }, + { "cookie_mode", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "proxy_mode", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "proxy_address", ValueType::STR, "", 1 }, + { "proxy_port", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "picture", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "animation", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "javascript", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "cache_size", ValueType::INT, "", (int)0x200 }, // decimal: 512 + { "char_size", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "disp_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "connect_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "flash_activated", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "flash_play", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "proxy_protect", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "proxy_autoauth", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "proxy_user", ValueType::STR, "", 1 }, + { "proxy_password", ValueType::STR, "", 1 }, + { "webpage_quality", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/BROWSER2 +static const KeyValue tree_CONFIG_BROWSER2[] = { + { "tm_service", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tm_ec_ttl", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tm_ec_ttl_update_time", ValueType::BIN, "", 8 }, // (all zero) + { "tm_service_sub_status", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/LFTV +static const KeyValue tree_CONFIG_LFTV[] = { + { "easy_reg_done", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "netav_domain_name", ValueType::STR, "", 1 }, + { "netav_ip_address", ValueType::STR, "172.29.71.1", 12 }, + { "netav_port_no_home", ValueType::INT, "", (int)0x139d }, // decimal: 5021 + { "netav_port_no_away", ValueType::INT, "", (int)0x139d }, // decimal: 5021 + { "netav_nonce", ValueType::STR, "", 1 }, + { "base_station_version", ValueType::STR, "0.000", 6 }, + { "base_station_region", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tuner_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "input_line", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tv_channel", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "bitrate_home", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "bitrate_away", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "channel_setting_jp", ValueType::BIN, "", 24 }, // (all zero) + { "channel_setting_us", ValueType::BIN, "", 68 }, // (all zero) + { "channel_setting_us_catv", ValueType::BIN, "", 125 }, // (all zero) + { "overwrite_netav_setting", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "screen_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "remocon_setting_region", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "remocon_setting", ValueType::BIN, "", 96 }, // (all zero) + { "remocon_setting_revision", ValueType::STR, "0000.00", 8 }, + { "external_tuner_channel", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "ssid", ValueType::STR, "", 1 }, + { "audio_gain", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "broadcast_standard_video1", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "broadcast_standard_video2", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "version", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tv_channel_range", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "tuner_type_no", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "input_line_no", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "audio_channel", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shared_remocon_setting", ValueType::BIN, "", 96 }, // (all zero) +}; + +// Dump of /CONFIG/RSS +static const KeyValue tree_CONFIG_RSS[] = { + { "download_items", ValueType::INT, "", (int)0x5 }, // decimal: 5 +}; + +// Dump of /CONFIG/ALARM +static const KeyValue tree_CONFIG_ALARM[] = { + { "alarm_0_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_1_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_2_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_3_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_4_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_5_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_6_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_7_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_8_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_9_time", ValueType::INT, "", (int)0xffffffff }, // decimal: -1 + { "alarm_0_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_1_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_2_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_3_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_4_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_5_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_6_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_7_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_8_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "alarm_9_property", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/PREMO +static const KeyValue tree_CONFIG_PREMO[] = { + { "guide_page", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "response", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "ps3_name", ValueType::STR, "", 1 }, + { "ps3_mac", ValueType::BIN, "", 6 }, // (all zero) + { "ps3_keytype", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "ps3_key", ValueType::BIN, "", 16 }, // (all zero) + { "custom_video_bitrate1", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "custom_video_bitrate2", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "custom_video_buffer1", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "custom_video_buffer2", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "setting_internet", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "button_assign", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "flags", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "account_id", ValueType::BIN, "", 16 }, // (all zero) + { "login_id", ValueType::STR, "", 1 }, + { "password", ValueType::STR, "", 1 }, +}; + +// Dump of /CONFIG/CAMERA +static const KeyValue tree_CONFIG_CAMERA[] = { + { "still_size", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "movie_size", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "still_quality", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "movie_quality", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "movie_fps", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "white_balance", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "exposure_bias", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "shutter_sound_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "file_folder", ValueType::INT, "", (int)0x65 }, // decimal: 101 + { "file_number", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "msid", ValueType::BIN, "", 16 }, // (all zero) + { "still_effect", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "medium_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "file_number_eflash", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "folder_number_eflash", ValueType::INT, "", (int)0x65 }, // decimal: 101 +}; + +// Dump of /CONFIG/DISPLAY +static const KeyValue tree_CONFIG_DISPLAY[] = { + { "aspect_ratio", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "scan_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "screensaver_start_time", ValueType::INT, "", (int)0x258 }, // decimal: 600 + { "color_space_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "pi_blending_mode", ValueType::INT, "", (int)0x1 }, // decimal: 1 +}; + +// Dump of /CONFIG/NP +static const KeyValue tree_CONFIG_NP[] = { + { "env", ValueType::STR, "np", 3 }, + { "account_id", ValueType::BIN, "", 16 }, // (all zero) + { "login_id", ValueType::STR, "", 1 }, + { "password", ValueType::STR, "", 1 }, + { "auto_sign_in_enable", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "nav_only", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "np_ad_clock_diff", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "view_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "np_geo_filtering", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "guest_country", ValueType::STR, "", 1 }, + { "guest_lang", ValueType::STR, "", 1 }, + { "guest_yob", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "guest_mob", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "guest_dob", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "check_drm", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/ONESEG +static const KeyValue tree_CONFIG_ONESEG[] = { + { "schedule_data_key", ValueType::BIN, "", 16 }, // (all zero) +}; + +// Dump of /CONFIG/SYSTEM/XMB/THEME +static const KeyValue tree_CONFIG_SYSTEM_XMB_THEME[] = { + { "color_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "wallpaper_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "system_color", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "custom_theme_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/SYSTEM/XMB +static const KeyValue tree_CONFIG_SYSTEM_XMB[] = { + { "theme_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "language", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "button_assign", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "THEME", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_XMB_THEME), tree_CONFIG_SYSTEM_XMB_THEME }, +}; + +// Dump of /CONFIG/SYSTEM/SOUND +static const KeyValue tree_CONFIG_SYSTEM_SOUND[] = { + { "main_volume", ValueType::INT, "", (int)0x1b }, // decimal: 27 + { "mute", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "avls", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "equalizer_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "operation_sound_mode", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "dynamic_normalizer", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/SYSTEM/POWER_SAVING +static const KeyValue tree_CONFIG_SYSTEM_POWER_SAVING[] = { + { "suspend_interval", ValueType::INT, "", (int)0x258 }, // decimal: 600 + { "backlight_off_interval", ValueType::INT, "", (int)0x12c }, // decimal: 300 + { "wlan_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "active_backlight_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/SYSTEM/LOCK +static const KeyValue tree_CONFIG_SYSTEM_LOCK[] = { + { "password", ValueType::BIN, "0000", 4 }, + { "parental_level", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "browser_start", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/SYSTEM/CHARACTER_SET +static const KeyValue tree_CONFIG_SYSTEM_CHARACTER_SET[] = { + { "oem", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "ansi", ValueType::INT, "", (int)0x13 }, // decimal: 19 +}; + +// Dump of /CONFIG/SYSTEM +static const KeyValue tree_CONFIG_SYSTEM[] = { + { "owner_name", ValueType::STR, "P939", 5 }, + { "backlight_brightness", ValueType::INT, "", (int)0x3 }, // decimal: 3 + { "umd_autoboot", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "usb_charge", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "umd_cache", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "usb_auto_connect", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "slide_action", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "first_boot_tick", ValueType::BIN, "\307\216\216\266\023\074\341\000\000\000\000\000\377\377\377\377\377\377\377\377\000b\240\010p\262\241\010 \350\377\t\006\000\002\000\006\000\022\000\050\302\231\010\304\r\217\010\000\000\300\300\340\347\377\t\360\\\274\t6\077\034A", 64 }, + { "owner_mob", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "owner_dob", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "slide_welcome", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "exh_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "XMB", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_XMB), tree_CONFIG_SYSTEM_XMB }, + { "SOUND", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_SOUND), tree_CONFIG_SYSTEM_SOUND }, + { "POWER_SAVING", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_POWER_SAVING), tree_CONFIG_SYSTEM_POWER_SAVING }, + { "LOCK", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_LOCK), tree_CONFIG_SYSTEM_LOCK }, + { "CHARACTER_SET", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM_CHARACTER_SET), tree_CONFIG_SYSTEM_CHARACTER_SET }, +}; + +// Dump of /CONFIG/DATE +static const KeyValue tree_CONFIG_DATE[] = { + { "time_format", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "date_format", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "summer_time", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "time_zone_offset", ValueType::INT, "", (int)0x3c }, // decimal: 60 + { "time_zone_area", ValueType::STR, "sweden", 7 }, +}; + +// Dump of /CONFIG/NETWORK/ADHOC +static const KeyValue tree_CONFIG_NETWORK_ADHOC[] = { + { "channel", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "ssid_prefix", ValueType::STR, "PSP", 4 }, +}; + +// Dump of /CONFIG/NETWORK/INFRASTRUCTURE/0/SUB1 +static const KeyValue tree_CONFIG_NETWORK_INFRASTRUCTURE_0_SUB1[] = { + { "wifisvc_auth_name", ValueType::STR, "", 1 }, + { "wifisvc_auth_key", ValueType::STR, "", 1 }, + { "wifisvc_option", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "last_leased_dhcp_addr", ValueType::STR, "", 1 }, + { "bt_id", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "at_command", ValueType::STR, "", 1 }, + { "phone_number", ValueType::STR, "", 1 }, +}; + +// Dump of /CONFIG/NETWORK/INFRASTRUCTURE/0 +static const KeyValue tree_CONFIG_NETWORK_INFRASTRUCTURE_0[] = { + { "SUB1", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK_INFRASTRUCTURE_0_SUB1), tree_CONFIG_NETWORK_INFRASTRUCTURE_0_SUB1 }, + { "version", ValueType::INT, "", (int)0x5 }, // decimal: 5 + { "device", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "cnf_name", ValueType::STR, "", 1 }, + { "ssid", ValueType::STR, "", 1 }, + { "auth_proto", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "wep_key", ValueType::BIN, "", 5 }, // (all zero) + { "how_to_set_ip", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "ip_address", ValueType::STR, "", 1 }, + { "netmask", ValueType::STR, "", 1 }, + { "default_route", ValueType::STR, "", 1 }, + { "dns_flag", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "primary_dns", ValueType::STR, "", 1 }, + { "secondary_dns", ValueType::STR, "", 1 }, + { "auth_name", ValueType::STR, "", 1 }, + { "auth_key", ValueType::STR, "", 1 }, + { "http_proxy_flag", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "http_proxy_server", ValueType::STR, "", 1 }, + { "http_proxy_port", ValueType::INT, "", (int)0x1f90 }, // decimal: 8080 + { "auth_8021x_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "auth_8021x_auth_name", ValueType::STR, "", 1 }, + { "auth_8021x_auth_key", ValueType::STR, "", 1 }, + { "wpa_key_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "wpa_key", ValueType::BIN, "", 64 }, // (all zero) + { "browser_flag", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "wifisvc_config", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/NETWORK/INFRASTRUCTURE +static const KeyValue tree_CONFIG_NETWORK_INFRASTRUCTURE[] = { + { "latest_id", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "eap_md5", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "auto_setting", ValueType::INT, "", (int)0x2 }, // decimal: 2 + { "wifisvc_setting", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "btdun_warnings_check", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "0", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK_INFRASTRUCTURE_0), tree_CONFIG_NETWORK_INFRASTRUCTURE_0 }, +}; + +// Dump of /CONFIG/NETWORK/GO_MESSENGER +static const KeyValue tree_CONFIG_NETWORK_GO_MESSENGER[] = { + { "auth_name", ValueType::STR, "", 1 }, + { "auth_key", ValueType::STR, "", 1 }, +}; + +// Dump of /CONFIG/NETWORK +static const KeyValue tree_CONFIG_NETWORK[] = { + { "ADHOC", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK_ADHOC), tree_CONFIG_NETWORK_ADHOC }, + { "INFRASTRUCTURE", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK_INFRASTRUCTURE), tree_CONFIG_NETWORK_INFRASTRUCTURE }, + { "GO_MESSENGER", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK_GO_MESSENGER), tree_CONFIG_NETWORK_GO_MESSENGER }, +}; + +// Dump of /CONFIG/OSK +static const KeyValue tree_CONFIG_OSK[] = { + { "version_id", ValueType::INT, "", (int)0x226 }, // decimal: 550 + { "disp_locale", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "writing_locale", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "input_char_mask", ValueType::INT, "", (int)0xf }, // decimal: 15 + { "keytop_index", ValueType::INT, "", (int)0x5 }, // decimal: 5 +}; + +// Dump of /CONFIG/INFOBOARD +static const KeyValue tree_CONFIG_INFOBOARD[] = { + { "locale_lang", ValueType::STR, "", 1 }, + { "qa_server", ValueType::INT, "", (int)0x0 }, // decimal: 0 +}; + +// Dump of /CONFIG/BT/DEVICE0 +static const KeyValue tree_CONFIG_BT_DEVICE0[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE1 +static const KeyValue tree_CONFIG_BT_DEVICE1[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE2 +static const KeyValue tree_CONFIG_BT_DEVICE2[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE3 +static const KeyValue tree_CONFIG_BT_DEVICE3[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE4 +static const KeyValue tree_CONFIG_BT_DEVICE4[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE5 +static const KeyValue tree_CONFIG_BT_DEVICE5[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE6 +static const KeyValue tree_CONFIG_BT_DEVICE6[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT/DEVICE7 +static const KeyValue tree_CONFIG_BT_DEVICE7[] = { + { "audio_type", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "device_type", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "device_name", ValueType::BIN, "", 64 }, // (all zero) +}; + +// Dump of /CONFIG/BT +static const KeyValue tree_CONFIG_BT[] = { + { "connect_mode", ValueType::INT, "", (int)0x0 }, // decimal: 0 + { "DEVICE0", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE0), tree_CONFIG_BT_DEVICE0 }, + { "DEVICE1", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE1), tree_CONFIG_BT_DEVICE1 }, + { "DEVICE2", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE2), tree_CONFIG_BT_DEVICE2 }, + { "DEVICE3", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE3), tree_CONFIG_BT_DEVICE3 }, + { "DEVICE4", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE4), tree_CONFIG_BT_DEVICE4 }, + { "DEVICE5", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE5), tree_CONFIG_BT_DEVICE5 }, + { "DEVICE6", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE6), tree_CONFIG_BT_DEVICE6 }, + { "DEVICE7", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT_DEVICE7), tree_CONFIG_BT_DEVICE7 }, +}; + +// Dump of /CONFIG/GAME +static const KeyValue tree_CONFIG_GAME[] = { + { "hibernation_ow_guide", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "hibernation_op_guide", ValueType::INT, "", (int)0x1 }, // decimal: 1 + { "subs_expiration_guide", ValueType::INT, "", (int)0x1 }, // decimal: 1 +}; + +// Dump of /CONFIG +static const KeyValue tree_CONFIG[] = { + { "VIDEO", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_VIDEO), tree_CONFIG_VIDEO }, + { "PHOTO", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_PHOTO), tree_CONFIG_PHOTO }, + { "MUSIC", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_MUSIC), tree_CONFIG_MUSIC }, + { "BROWSER", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BROWSER), tree_CONFIG_BROWSER }, + { "BROWSER2", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BROWSER2), tree_CONFIG_BROWSER2 }, + { "LFTV", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_LFTV), tree_CONFIG_LFTV }, + { "RSS", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_RSS), tree_CONFIG_RSS }, + { "ALARM", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_ALARM), tree_CONFIG_ALARM }, + { "PREMO", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_PREMO), tree_CONFIG_PREMO }, + { "CAMERA", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_CAMERA), tree_CONFIG_CAMERA }, + { "DISPLAY", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_DISPLAY), tree_CONFIG_DISPLAY }, + { "NP", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NP), tree_CONFIG_NP }, + { "ONESEG", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_ONESEG), tree_CONFIG_ONESEG }, + { "SYSTEM", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_SYSTEM), tree_CONFIG_SYSTEM }, + { "DATE", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_DATE), tree_CONFIG_DATE }, + { "NETWORK", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_NETWORK), tree_CONFIG_NETWORK }, + { "OSK", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_OSK), tree_CONFIG_OSK }, + { "INFOBOARD", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_INFOBOARD), tree_CONFIG_INFOBOARD }, + { "BT", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_BT), tree_CONFIG_BT }, + { "GAME", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG_GAME), tree_CONFIG_GAME }, +}; + +// Dump of /REGISTRY +static const KeyValue tree_REGISTRY[] = { + { "category_version", ValueType::INT, "", (int)0x66 }, // decimal: 102 +}; + +// There might be more categories. const KeyValue ROOT[] = { { "DATA", ValueType::DIR, "", ARRAY_SIZE(tree_DATA), tree_DATA }, { "SYSPROFILE", ValueType::DIR, "", ARRAY_SIZE(tree_SYSPROFILE), tree_SYSPROFILE }, + { "CONFIG", ValueType::DIR, "", ARRAY_SIZE(tree_CONFIG), tree_CONFIG }, + { "REGISTRY", ValueType::DIR, "", ARRAY_SIZE(tree_REGISTRY), tree_REGISTRY }, }; // Updater checks for CONFIG/SYSTEM/XMB. @@ -704,8 +1164,8 @@ int sceRegGetKeyInfo(int catHandle, const char *name, u32 outKeyHandleAddr, u32 int size = 0; if (Memory::IsValid4AlignedAddress(outSizeAddr)) { switch (keyvals[i].type) { - case ValueType::BIN: size = (int)keyvals[i].strValue.size(); break; - case ValueType::STR: size = (int)keyvals[i].strValue.size() + 1; break; + case ValueType::BIN: size = (int)keyvals[i].intValue; break; + case ValueType::STR: size = (int)keyvals[i].intValue; break; case ValueType::DIR: size = 0; break; case ValueType::INT: size = 4; break; default: break; @@ -747,11 +1207,11 @@ int sceRegGetKeyValue(int catHandle, int keyHandle, u32 bufAddr, u32 size) { const KeyValue &keyval = keyvals[keyHandle]; switch (keyval.type) { case ValueType::BIN: - Memory::MemcpyUnchecked(bufAddr, keyval.strValue.data(), std::min(size, (u32)keyval.strValue.size())); + Memory::MemcpyUnchecked(bufAddr, keyval.strValue, std::min(size, (u32)keyval.intValue)); return hleLogInfo(Log::sceReg, 0); case ValueType::STR: - Memory::MemcpyUnchecked(bufAddr, keyval.strValue.data(), std::min(size, (u32)keyval.strValue.size() + 1)); - return hleLogInfo(Log::sceReg, 0, "value: '%s'", keyval.strValue.data()); + Memory::MemcpyUnchecked(bufAddr, keyval.strValue, std::min(size, (u32)keyval.intValue)); + return hleLogInfo(Log::sceReg, 0, "value: '%s'", keyval.strValue); case ValueType::INT: Memory::WriteUnchecked_U32(keyval.intValue, bufAddr); return hleLogInfo(Log::sceReg, 0, "value: %d (0x%08x)", keyval.intValue, keyval.intValue); From d04c39db1dfd2d196475bdf9b3b97cd3481626ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 14:36:51 +0200 Subject: [PATCH 02/11] Bump pspautotests --- pspautotests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pspautotests b/pspautotests index 4374348477..23ae650d05 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 4374348477b425f48f99c8fd58a853c439f78acd +Subproject commit 23ae650d0537890247f49adb117618d715b75311 From 5c1d1132796bd6c964dc8a770c5695d1ebaf0150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 13:49:12 +0200 Subject: [PATCH 03/11] Warning fix in sceUsbCam --- Core/HLE/sceUsbCam.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index d7738250c1..d33552122a 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -328,13 +328,15 @@ void Register_sceUsbCam() } std::vector Camera::getDeviceList() { - #ifdef HAVE_WIN32_CAMERA - if (winCamera) { - return winCamera->getDeviceList(); - } - #else - return System_GetCameraDeviceList(); - #endif +#ifdef HAVE_WIN32_CAMERA + if (winCamera) { + return winCamera->getDeviceList(); + } else { + return std::vector(); + } +#else + return System_GetCameraDeviceList(); +#endif } int Camera::startCapture() { From 4bf36fc7f835aad1c10a292ace3d1ba0f600be99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 11:07:04 +0200 Subject: [PATCH 04/11] Add command line option --vsh to try to boot the VSH. Logspam reduction, improve printf logs. --- Common/File/FileUtil.cpp | 2 +- Common/Log/LogManager.cpp | 15 +++++++------- Core/CmdLine.cpp | 3 +++ Core/CmdLine.h | 4 ++++ Core/Core.cpp | 2 +- Core/ELF/ElfReader.cpp | 2 +- Core/FileSystems/DirectoryFileSystem.cpp | 25 ++++++++++++++---------- Core/HLE/sceReg.cpp | 4 ++-- UI/NativeApp.cpp | 9 ++++++--- headless/Headless.cpp | 19 ++++++++++++------ 10 files changed, 54 insertions(+), 31 deletions(-) diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 0cc02ecf0b..d0612e61a0 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -710,7 +710,7 @@ bool CreateDir(const Path &path) { // Creates the full path of fullPath returns true on success bool CreateFullPath(const Path &path) { if (File::Exists(path)) { - DEBUG_LOG(Log::IO, "CreateFullPath: path exists %s", path.ToVisualString().c_str()); + VERBOSE_LOG(Log::IO, "CreateFullPath: path exists %s", path.ToVisualString().c_str()); return true; } diff --git a/Common/Log/LogManager.cpp b/Common/Log/LogManager.cpp index f07fb838fb..fc1cdab996 100644 --- a/Common/Log/LogManager.cpp +++ b/Common/Log/LogManager.cpp @@ -27,7 +27,6 @@ #include #include "Common/Data/Encoding/Utf8.h" - #include "Common/Log/LogManager.h" #if PPSSPP_PLATFORM(WINDOWS) @@ -469,25 +468,27 @@ void LogManager::StdioLog(const LogMessage &message) { } void PrintfLog(const LogMessage &message) { + const char *category = message.log; + switch (message.level) { case LogLevel::LVERBOSE: - fprintf(stderr, "V %s", message.msg.c_str()); + fprintf(stderr, "V %s: %s", category, message.msg.c_str()); break; case LogLevel::LDEBUG: - fprintf(stderr, "D %s", message.msg.c_str()); + fprintf(stderr, "D %s: %s", category, message.msg.c_str()); break; case LogLevel::LINFO: - fprintf(stderr, "I %s", message.msg.c_str()); + fprintf(stderr, "I %s: %s", category, message.msg.c_str()); break; case LogLevel::LERROR: - fprintf(stderr, "E %s", message.msg.c_str()); + fprintf(stderr, "E %s: %s", category, message.msg.c_str()); break; case LogLevel::LWARNING: - fprintf(stderr, "W %s", message.msg.c_str()); + fprintf(stderr, "W %s: %s", category, message.msg.c_str()); break; case LogLevel::LNOTICE: default: - fprintf(stderr, "N %s", message.msg.c_str()); + fprintf(stderr, "N %s: %s", category, message.msg.c_str()); break; } } diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index 32ea4096c1..50a2f9c99d 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -151,6 +151,7 @@ static const CommandLineParam g_autoParams[] = { {POFF(timeout), CmdParamType::Double, "timeout", '\0', "Set the timeout value"}, {POFF(resolutionScale), CmdParamType::Int, "resolution-scale", '\0', "Set the resolution scale factor"}, {POFF(debuggerPort), CmdParamType::Int, "debugger", '\0', "Enable the WebSocket debugger on this port (0 = pick automatically); see docs/WebSocketDebugger.md"}, + {POFF(bootVSH), CmdParamType::Bool, "vsh", '\0', "Boot the VSH (requires files dumped from a PSP in the flash0 directory)"}, // TODO: At some point we should maybe simply expose all config settings to be set directly from the command line automatically? }; @@ -422,6 +423,8 @@ void CommandLineOptions::ApplyToConfig() const { g_Config.DoNotSaveSetting(&g_Config.iInternalResolution); } + // --vsh is applied by the caller. + // Note: dpi is not applied here - it's platform-specific. // Platforms should check cmdLineOptions.dpi.has_value() and handle accordingly. } diff --git a/Core/CmdLine.h b/Core/CmdLine.h index 0724610419..2b045fc865 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -44,6 +44,10 @@ struct CommandLineOptions { // Also breaks the CPU at start in the headless build. See docs/WebSocketDebugger.md. std::optional debuggerPort; + // Attempts to boot the vsh, which will only work if the correct files are present in the flash + // and once we've fixed all the bugs. This is just here to allow testing. + std::optional bootVSH; + std::optional appendConfig; std::optional root; // mount root, needs more explanation std::optional stateToLoad; diff --git a/Core/Core.cpp b/Core/Core.cpp index 5cfcfdc92f..ce5bc45e2d 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -625,7 +625,7 @@ void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) { } void Core_BreakException(u32 pc) { - ERROR_LOG(Log::CPU, "BREAK!"); + ERROR_LOG(Log::CPU, "CPU exception: break instruction hit at %08x", pc); MIPSExceptionInfo &e = g_exceptionInfo; e = {}; diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index e4fd7e2bf8..658d668b18 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -362,7 +362,7 @@ void ElfReader::LoadRelocations2(int rel_seg) } op = Memory::Read_Instruction(rel_offset, true).encoding; - DEBUG_LOG(Log::Loader, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op); + VERBOSE_LOG(Log::Loader, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op); switch(type){ case 0: diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 3534e301cd..ed98a9b851 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -68,18 +68,23 @@ DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, const Path & static const std::string_view mixedCase = "wJpCzSBNnZfxSgoS"; static const std::string_view upperCase = "WJPCZSBNNZFXSGOS"; - // Check for case sensitivity - bool checkSucceeded = false; - File::CreateEmptyFile(basePath / mixedCase); - if (File::Exists(basePath / mixedCase)) { - checkSucceeded = true; - if (!File::Exists(basePath / upperCase)) { - flags |= FileSystemFlags::CASE_SENSITIVE; + // Check for case sensitivity. TODO: Add more special cases to avoid the file creation dance. +#if !PPSSPP_PLATFORM(WINDOWS) + if (basePath.Type() == PathType::CONTENT_URI) { + // Android: Is not case sensitive. + } else { + bool checkSucceeded = false; + File::CreateEmptyFile(basePath / mixedCase); + if (File::Exists(basePath / mixedCase)) { + checkSucceeded = true; + if (!File::Exists(basePath / upperCase)) { + flags |= FileSystemFlags::CASE_SENSITIVE; + } } + File::Delete(basePath / mixedCase); + INFO_LOG(Log::IO, "Is file system case sensitive? %s (base: '%s') (checkOK: %d)", (flags & FileSystemFlags::CASE_SENSITIVE) ? "yes" : "no", _basePath.c_str(), checkSucceeded); } - File::Delete(basePath / mixedCase); - - INFO_LOG(Log::IO, "Is file system case sensitive? %s (base: '%s') (checkOK: %d)", (flags & FileSystemFlags::CASE_SENSITIVE) ? "yes" : "no", _basePath.c_str(), checkSucceeded); +#endif hAlloc = _hAlloc; } diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index 2d51cf1d9d..8eb36ee349 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -57,9 +57,9 @@ struct KeyValue { const KeyValue *dirContents; // intValue is the count. }; - // TODO: /DATA/FONT/PROPERTY could just be generated from our fontRegistry in sceFont.cpp. -// Dump of the PSP registry using tests/misc/reg.prx in pspautotests + +// Partial dump of the PSP registry using tests/misc/reg.prx in pspautotests // Dump of /DATA/FONT/PROPERTY/INFO0 static const KeyValue tree_DATA_FONT_PROPERTY_INFO0[] = { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 442fea7ba9..964d6ef215 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -579,11 +579,13 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO // Apply parsed command line options to config. cmdLineOptions.ApplyToConfig(); - const char *fileToLog = nullptr; - bool gotBootFilename = false; boot_filename.clear(); + if (boot_filename.empty() && cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { + boot_filename = g_Config.flash0Directory / "vsh/module/vshmain.prx"; + } + // Parse command line LogLevel logLevel = LogLevel::LINFO; bool forceLogLevel = false; @@ -596,6 +598,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO setLogLevel(cmdLineOptions.logLevel.value()); } + std::string fileToLog; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { #if defined(__APPLE__) @@ -672,7 +675,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO } } - if (fileToLog) { + if (!fileToLog.empty()) { // Start logging immediately. g_logManager.EnableOutput(LogOutput::File); g_logManager.SetFileLogPath(Path(fileToLog)); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index b35e9915b7..ab29ab0c3d 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -510,11 +510,14 @@ int main(int argc, const char* argv[]) { } } + if (!fullLog) { + printf("Pass the -l flag to see full log output.\n"); + } + for (const std::string &filename : cmdLineOptions.bootFilenames) { AddToTestsByPath(&testFilenames, filename); } - if (testFilenames.size() == 1 && testFilenames[0][0] == '@') testFilenames = ReadFromListFile(testFilenames[0].substr(1)); @@ -528,23 +531,20 @@ int main(int argc, const char* argv[]) { testFilenames.end() ); - if (testFilenames.empty()) - return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); - g_Config.bEnableLogging = (fullLog || outputDebugStringLog); g_logManager.Init(&g_Config.bEnableLogging, outputDebugStringLog); for (int i = 0; i < (int)Log::NUMBER_OF_LOGS; i++) { Log type = (Log)i; g_logManager.SetEnabled(type, (fullLog || outputDebugStringLog)); - g_logManager.SetLogLevel(type, LogLevel::LDEBUG); + g_logManager.SetLogLevel(type, LogLevel::LDEBUG); // TODO: Make the level configurable. } if (fullLog) { // Only with --log, add the printfLogger. g_logManager.EnableOutput(LogOutput::Printf); } - g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS | RestoreSettingsBits::CONTROLS | RestoreSettingsBits::RECENT, true); + g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS | RestoreSettingsBits::CONTROLS | RestoreSettingsBits::RECENT, false); // Needs to be after log so we don't interfere with test output. g_threadManager.Init(cpu_info.num_cores, cpu_info.logical_cpu_count); @@ -679,6 +679,13 @@ int main(int argc, const char* argv[]) { UpdateUIState(UISTATE_INGAME); + if (cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { + AddToTestsByPath(&testFilenames, (g_Config.flash0Directory / "vsh/module/vshmain.prx").ToString()); + } + if (testFilenames.empty()) { + return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); + } + if (cmdLineOptions.debuggerPort.has_value()) { coreParameter.startBreak = true; StartWebServer(WebServerFlags::DEBUGGER); From 3139d7ccfe80d0409fbd2381f8c525b71721e3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 14:27:05 +0200 Subject: [PATCH 05/11] Add command line parameters for controlling the behavior on memory/instruction exceptions --- Core/CmdLine.cpp | 91 +++++++++++++++++++++++++++++++++++++-------- Core/CmdLine.h | 7 ++++ Core/Config.h | 5 +++ Core/ConfigValues.h | 7 ++++ Core/Core.cpp | 88 ++++++++++++++++++++++--------------------- Core/Core.h | 7 +--- Core/MemFault.cpp | 2 +- 7 files changed, 144 insertions(+), 63 deletions(-) diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index 50a2f9c99d..e722bba378 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -23,6 +23,7 @@ enum class CmdParamType { Int, Double, String, + Enum, }; struct CommandLineParam { @@ -32,6 +33,8 @@ struct CommandLineParam { char shortName; // can be 0 for no short name const char *docString; CmdLineMode mode; + const char **enumValues; + int enumCount; }; enum class ParseParamResult { @@ -41,6 +44,7 @@ enum class ParseParamResult { }; ParseParamResult SetValue(CommandLineOptions *options, const CommandLineParam ¶m, const std::string &value) { + uint8_t *optionsPtr = reinterpret_cast(options); switch (param.type) { case CmdParamType::Bool: case CmdParamType::BoolInverse: @@ -58,18 +62,37 @@ ParseParamResult SetValue(CommandLineOptions *options, const CommandLineParam &p if (param.type == CmdParamType::BoolInverse) { v = !v; } - *reinterpret_cast *>(reinterpret_cast(options) + param.offsetInStruct) = v; + *reinterpret_cast *>(optionsPtr + param.offsetInStruct) = v; break; } case CmdParamType::Int: - *reinterpret_cast *>(reinterpret_cast(options) + param.offsetInStruct) = std::stoi(value); + *reinterpret_cast *>(optionsPtr + param.offsetInStruct) = std::stoi(value); break; case CmdParamType::Double: - *reinterpret_cast *>(reinterpret_cast(options) + param.offsetInStruct) = std::stod(value); + *reinterpret_cast *>(optionsPtr + param.offsetInStruct) = std::stod(value); break; case CmdParamType::String: - *reinterpret_cast *>(reinterpret_cast(options) + param.offsetInStruct) = value; + *reinterpret_cast *>(optionsPtr + param.offsetInStruct) = value; break; + case CmdParamType::Enum: + { + int enumIndex = -1; + for (int i = 0; i < param.enumCount; ++i) { + if (value == param.enumValues[i]) { + enumIndex = i; + break; + } + } + if (enumIndex == -1) { + PRINT_STDERR("Error: Invalid value for parameter --%s: '%s'. Expected one of: ", param.longName, value.c_str()); + for (int i = 0; i < param.enumCount; ++i) { + PRINT_STDERR("%s%s", param.enumValues[i], (i + 1 < param.enumCount) ? ", " : "\n"); + } + return ParseParamResult::BadValue; + } + *reinterpret_cast *>(optionsPtr + param.offsetInStruct) = enumIndex; + break; + } default: break; } @@ -132,6 +155,14 @@ static ParseParamResult ParseParameterStr(int argc, const char *argv[], size_t & return ParseParamResult::NoMatch; } +// Enum ExceptionAction +const char *g_ExceptionActionValues[] = { + "default", + "ignore", + "log", + "break", +}; + #define POFF(member) offsetof(CommandLineOptions, member) static const CommandLineParam g_autoParams[] = { {POFF(fullscreen), CmdParamType::Bool, "fullscreen", '\0', "Force full screen mode", CmdLineMode::Application}, @@ -152,28 +183,35 @@ static const CommandLineParam g_autoParams[] = { {POFF(resolutionScale), CmdParamType::Int, "resolution-scale", '\0', "Set the resolution scale factor"}, {POFF(debuggerPort), CmdParamType::Int, "debugger", '\0', "Enable the WebSocket debugger on this port (0 = pick automatically); see docs/WebSocketDebugger.md"}, {POFF(bootVSH), CmdParamType::Bool, "vsh", '\0', "Boot the VSH (requires files dumped from a PSP in the flash0 directory)"}, + {POFF(memReadAction), CmdParamType::Enum, "memread", '\0', "Set the action for memory read exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, + {POFF(memWriteAction), CmdParamType::Enum, "memwrite", '\0', "Set the action for memory write exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, + {POFF(breakAction), CmdParamType::Enum, "break", '\0', "Set the action for break exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, + // TODO: At some point we should maybe simply expose all config settings to be set directly from the command line automatically? }; -// NOTE: On Windows this prints nothing unfortunately, since PPSSPP is not a "console app". +// NOTE: On Windows this prints nothing unfortunately, since PPSSPP is not a "console app" (PPSSPPHeadless is though, there it works). // A fun trick we could do is AttachConsole(ATTACH_PARENT_PROCESS) which works at least from git bash and powershell, if we also use WriteConsole. // However it's not exactly ideal. -static int printUsage(int argc, const char *argv[], CmdLineMode mode) { +int CommandLineOptions::PrintUsage(const char *progname, const char *situationText) const { // NOTE: by convention, --help outputs to stdout, // not to stderr, since it is intended output in this // case (usage printed under different circumstances, // say in response to error during parsing commandline, // may go to stderr). - const char *progname = argc > 0 ? argv[0] : "ppsspp"; // NOTE: wording largely taken from // https://www.ppsspp.org/docs/reference/command-line/ - if (mode == CmdLineMode::Application) { - PRINT_STDOUT("PPSSPP - a PSP emulator\n"); + if (situationText) { + PRINT_STDOUT("%s\n\n", situationText); } else { - PRINT_STDOUT("PPSSPP Headless\n"); - PRINT_STDOUT("This is primarily meant as a non-interactive test tool.\n\n"); + if (mode == CmdLineMode::Application) { + PRINT_STDOUT("PPSSPP - a PSP emulator\n"); + } else { + PRINT_STDOUT("PPSSPP Headless\n"); + PRINT_STDOUT("This is primarily meant as a non-interactive test tool.\n\n"); + } } - PRINT_STDOUT("PPSSPP - a PSP emulator\n"); + PRINT_STDOUT("Usage: %s [options] [FILE]\n\n", progname); PRINT_STDOUT("Launches FILE (e.g. ISO image) if present.\n"); PRINT_STDOUT("Options (some of these are specific to SDL backend):\n"); @@ -199,6 +237,13 @@ static int printUsage(int argc, const char *argv[], CmdLineMode mode) { PRINT_STDOUT(" --%s%s%s\n", param.longName, param.shortName ? ", -" : "", param.shortName ? std::string(1, param.shortName).c_str() : ""); + if (param.type == CmdParamType::Enum) { + PRINT_STDOUT(" options: "); + for (int i = 0; i < param.enumCount; ++i) { + PRINT_STDOUT("%s%s", param.enumValues[i], i + 1 < param.enumCount ? ", " : ""); + } + PRINT_STDOUT("\n"); + } PRINT_STDOUT(" %s\n", param.docString); } @@ -218,6 +263,7 @@ static int printUsage(int argc, const char *argv[], CmdLineMode mode) { // Error reporting is done with PRINT_STDERR(....). // Actually might want to reconsider given Android... CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], CmdLineMode mode) { + this->mode = mode; constexpr std::string_view gpuBackendStr = "--graphics="; constexpr std::string_view configOption = "--config="; constexpr std::string_view controlsOption = "--controlconfig="; @@ -260,7 +306,7 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C logLevel = LogLevel::LVERBOSE; break; case 'h': - printUsage(argc, argv, mode); + PrintUsage(argv[0], mode, nullptr); return CommandLineParseResult::Exit; // Legacy cpucore options. case 'j': @@ -306,7 +352,7 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C // We already incremented i. continue; } else if (equals(argv[i], "--help")) { - printUsage(argc, argv, mode); + PrintUsage(argv[0], mode, nullptr); return CommandLineParseResult::Exit; } else if (equals(argv[i], "--version")) { printf("%s\n", PPSSPP_GIT_VERSION); @@ -423,7 +469,22 @@ void CommandLineOptions::ApplyToConfig() const { g_Config.DoNotSaveSetting(&g_Config.iInternalResolution); } - // --vsh is applied by the caller. + if (memReadAction.has_value()) { + g_Config.iExceptionActionMemRead = memReadAction.value(); + g_Config.DoNotSaveSetting(&g_Config.iExceptionActionMemRead); + } + + if (memWriteAction.has_value()) { + g_Config.iExceptionActionMemWrite = memWriteAction.value(); + g_Config.DoNotSaveSetting(&g_Config.iExceptionActionMemWrite); + } + + if (breakAction.has_value()) { + g_Config.iExceptionActionBreak = breakAction.value(); + g_Config.DoNotSaveSetting(&g_Config.iExceptionActionBreak); + } + + // --vsh is applied by the caller (by setting their boot file name variable). // Note: dpi is not applied here - it's platform-specific. // Platforms should check cmdLineOptions.dpi.has_value() and handle accordingly. diff --git a/Core/CmdLine.h b/Core/CmdLine.h index 2b045fc865..b2f1b34a53 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -24,6 +24,9 @@ struct CommandLineOptions { // If returns CommandLineParseResult::Exit or ::Error, the program should exit immediately (with an error return code if Error). CommandLineParseResult Parse(int argc, const char *argv[], CmdLineMode mode = CmdLineMode::Application); void ApplyToConfig() const; + int PrintUsage(const char *progname, const char *situationText) const; + + CmdLineMode mode; std::optional fullscreen; std::optional gpuBackend; @@ -52,6 +55,10 @@ struct CommandLineOptions { std::optional root; // mount root, needs more explanation std::optional stateToLoad; + std::optional memReadAction; + std::optional memWriteAction; + std::optional breakAction; + // SDL only: Option to force a specific OpenGL version (42="4.2", // etc.; -1 means "try them all"). // Implemented as a workaround for https://github.com/hrydgard/ppsspp/issues/20687 diff --git a/Core/Config.h b/Core/Config.h index 6afa0f02be..3c58147744 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -213,6 +213,11 @@ public: // Core bool bIgnoreBadMemAccess; + // ExceptionAction enum: 0 = default (obey bIgnoreBadMemAccess), 1 = log, 2 = break, 3 = exit + int iExceptionActionMemRead; // this also includes alignment and other odd memory exceptions. + int iExceptionActionMemWrite; + int iExceptionActionBreak; + bool bFastMemory; int iCpuCore; bool bCheckForNewVersion; diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index 2bd3fb3566..c61dcfff9e 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -180,6 +180,13 @@ enum IOTimingMethods { IOTIMING_UMDSLOWREALISTIC = 3, }; +enum class ExceptionAction { + Default = 0, // Obey the value of "Ignore bad memory accesses" (that corresponds to Ignore vs Crash) + Ignore = 1, + Log = 2, // Ignore, but log details + Break = 3, // Break execution in the PPSSPP debuggers +}; + enum class AutoLoadSaveState { OFF = 0, OLDEST = 1, diff --git a/Core/Core.cpp b/Core/Core.cpp index ce5bc45e2d..fc604bf243 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -550,21 +550,46 @@ const char *ExecExceptionTypeAsString(ExecExceptionType type) { } } -void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type) { +static ExceptionAction ResolveExceptionAction(ExceptionAction action) { + if (action == ExceptionAction::Default) { + return g_Config.bIgnoreBadMemAccess ? ExceptionAction::Ignore : ExceptionAction::Break; + } + return action; +} + +void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string_view additionalInfo, bool forceReport) { const char *desc = MemoryExceptionTypeAsString(type); // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if ((g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) && g_Config.bIgnoreBadMemAccess) { - WARN_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x)", desc, address, accessSize); - } else { - WARN_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); + + char pcDetails[64]; + pcDetails[0] = 0; + if ((CPUCore)g_Config.iCpuCore == CPUCore::INTERPRETER) { + snprintf(pcDetails, sizeof(pcDetails), " PC %08x LR %08x", currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); } - if (!g_Config.bIgnoreBadMemAccess) { - // Try to fetch a call stack, to start with. - std::vector stackFrames = WalkCurrentStack(-1); - std::string stackTrace = FormatStackTrace(stackFrames); - WARN_LOG(Log::MemMap, "\n%s", stackTrace.c_str()); + ExceptionAction action; + switch (type) { + case MemoryExceptionType::WRITE_WORD: + case MemoryExceptionType::WRITE_BLOCK: + action = ResolveExceptionAction((ExceptionAction)g_Config.iExceptionActionMemWrite); + break; + case MemoryExceptionType::READ_WORD: + case MemoryExceptionType::READ_BLOCK: + default: + action = ResolveExceptionAction((ExceptionAction)g_Config.iExceptionActionMemRead); + break; + } + if (action == ExceptionAction::Ignore) { + // Simplest logging and continue. + WARN_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x) %s%.*s", desc, address, accessSize, pcDetails, (int)additionalInfo.length(), additionalInfo.data()); + return; + } + + const std::string stackTrace = FormatStackTrace(WalkCurrentStack(-1)); + // Do the most detailed logging we can. + ERROR_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x) %s%.*s\n%s", desc, address, accessSize, pcDetails, (int)additionalInfo.length(), additionalInfo.data(), stackTrace.c_str()); + if (action == ExceptionAction::Break) { MIPSExceptionInfo &e = g_exceptionInfo; e = {}; e.type = MIPSExceptionType::MEMORY; @@ -578,35 +603,7 @@ void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionTy } } -void Core_MemoryExceptionInfo(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string_view additionalInfo, bool forceReport) { - const char *desc = MemoryExceptionTypeAsString(type); - // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if ((g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) && g_Config.bIgnoreBadMemAccess) { - WARN_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x). %.*s", desc, address, accessSize, (int)additionalInfo.length(), additionalInfo.data()); - } else { - WARN_LOG(Log::MemMap, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x %.*s", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA], (int)additionalInfo.length(), additionalInfo.data()); - } - - if (!g_Config.bIgnoreBadMemAccess || forceReport) { - // Try to fetch a call stack, to start with. - std::vector stackFrames = WalkCurrentStack(-1); - std::string stackTrace = FormatStackTrace(stackFrames); - WARN_LOG(Log::MemMap, "\n%s", stackTrace.c_str()); - - MIPSExceptionInfo &e = g_exceptionInfo; - e = {}; - e.type = MIPSExceptionType::MEMORY; - e.info = additionalInfo; - e.memory_type = type; - e.address = address; - e.accessSize = accessSize; - e.stackTrace = stackTrace; - e.pc = pc; - Core_Break(BreakReason::MemoryException, address); - } -} - -// Can't be ignored +// Can't be ignored, must break. Not sure we can get a meaningful stack trace here (since the PC is invalid). void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) { const char *desc = ExecExceptionTypeAsString(type); WARN_LOG(Log::MemMap, "%s: Invalid exec address %08x pc=%08x ra=%08x", desc, address, pc, currentMIPS->r[MIPS_REG_RA]); @@ -625,15 +622,22 @@ void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) { } void Core_BreakException(u32 pc) { - ERROR_LOG(Log::CPU, "CPU exception: break instruction hit at %08x", pc); - MIPSExceptionInfo &e = g_exceptionInfo; e = {}; e.type = MIPSExceptionType::BREAK; e.info.clear(); e.pc = pc; - if (!g_Config.bIgnoreBadMemAccess) { + const ExceptionAction action = ResolveExceptionAction((ExceptionAction)g_Config.iExceptionActionBreak); + if (action == ExceptionAction::Ignore) { + // Simplest logging and continue. + WARN_LOG(Log::CPU, "CPU exception: break instruction hit at %08x. Ignoring (use --break=log for more details or --break=break to break)", pc); + return; + } + + const std::string stackTrace = FormatStackTrace(WalkCurrentStack(-1)); + ERROR_LOG(Log::CPU, "CPU exception: break instruction hit at %08x (ra=%08x)\n%s", pc, currentMIPS->r[MIPS_REG_RA], stackTrace.c_str()); + if (action == ExceptionAction::Break) { Core_Break(BreakReason::BreakInstruction, currentMIPS->pc); } } diff --git a/Core/Core.h b/Core/Core.h index 008c83408f..1272e1ce2d 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -22,6 +22,7 @@ #include #include "Common/CommonTypes.h" +#include "Core/ConfigValues.h" class GraphicsContext; @@ -166,11 +167,7 @@ enum class ExecExceptionType { THREAD, }; -// Separate one for without info, to avoid having to allocate a string -void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type); - -void Core_MemoryExceptionInfo(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string_view additionalInfo, bool forceReport); - +void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string_view additionalInfo = "", bool forceReport = false); void Core_ExecException(u32 address, u32 pc, ExecExceptionType type); void Core_BreakException(u32 pc); // Call when loading save states, etc. diff --git a/Core/MemFault.cpp b/Core/MemFault.cpp index 4409a21652..514a4879eb 100644 --- a/Core/MemFault.cpp +++ b/Core/MemFault.cpp @@ -319,7 +319,7 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) { uint32_t approximatePC = currentMIPS->pc; // TODO: Determine access size from the disassembled native instruction. We have some partial info already, // just need to clean it up. - Core_MemoryExceptionInfo(guestAddress, 0, approximatePC, type, infoString, true); + Core_MemoryException(guestAddress, 0, approximatePC, type, infoString, true); // There's a small chance we can resume from this type of crash. g_lastCrashAddress = codePtr; From 5ef736f6a77f1f6c80a267ff37f7b4ec230bed1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 17:32:15 +0200 Subject: [PATCH 06/11] More command line improvements --- Common/TimeUtil.cpp | 16 +++++++++++++ Common/TimeUtil.h | 1 + Core/CmdLine.cpp | 18 +++++++++++---- Core/CmdLine.h | 2 +- Core/Config.cpp | 2 +- Windows/main.cpp | 3 ++- headless/Headless.cpp | 54 ++++++++++++++----------------------------- pspautotests | 2 +- 8 files changed, 52 insertions(+), 46 deletions(-) diff --git a/Common/TimeUtil.cpp b/Common/TimeUtil.cpp index de6979d9d1..789abbc5d3 100644 --- a/Common/TimeUtil.cpp +++ b/Common/TimeUtil.cpp @@ -65,6 +65,8 @@ void TimeInit() { // The timer will be automatically deleted on process destruction. Don't need to CloseHandle. Timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + + // TODO: We probably don't need this anymore if we are using the high res waitable timers? #if !PPSSPP_PLATFORM(UWP) TIMECAPS caps; timeGetDevCaps(&caps, sizeof caps); @@ -73,6 +75,12 @@ void TimeInit() { #endif } +void TimeShutdown() { +#if PPSSPP_PLATFORM(WINDOWS) + timeEndPeriod(1); +#endif +} + double time_now_d() { LARGE_INTEGER time; QueryPerformanceCounter(&time); @@ -141,6 +149,10 @@ void TimeInit() { // Nothing to do. } +void TimeShutdown() { + // Nothing to do. +} + // The only intended use is to match the timings in VK_GOOGLE_display_timing uint64_t time_now_raw() { struct timespec tp; @@ -210,6 +222,10 @@ void TimeInit() { // Nothing to do. } +void TimeShutdown() { + // Nothing to do. +} + static time_t start; double time_now_d() { diff --git a/Common/TimeUtil.h b/Common/TimeUtil.h index 6f1a30a14c..95420e6e7f 100644 --- a/Common/TimeUtil.h +++ b/Common/TimeUtil.h @@ -2,6 +2,7 @@ #include void TimeInit(); +void TimeShutdown(); // Not really necessary to call, just for completeness. // Seconds. double time_now_d(); diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index e722bba378..225d60dc7d 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -186,6 +186,7 @@ static const CommandLineParam g_autoParams[] = { {POFF(memReadAction), CmdParamType::Enum, "memread", '\0', "Set the action for memory read exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, {POFF(memWriteAction), CmdParamType::Enum, "memwrite", '\0', "Set the action for memory write exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, {POFF(breakAction), CmdParamType::Enum, "break", '\0', "Set the action for break exceptions", CmdLineMode::Both, g_ExceptionActionValues, ARRAY_SIZE(g_ExceptionActionValues)}, + {POFF(verbose), CmdParamType::Bool, "verbose", '\0', "Enable verbose output", CmdLineMode::Both}, // TODO: At some point we should maybe simply expose all config settings to be set directly from the command line automatically? }; @@ -214,7 +215,7 @@ int CommandLineOptions::PrintUsage(const char *progname, const char *situationTe PRINT_STDOUT("Usage: %s [options] [FILE]\n\n", progname); PRINT_STDOUT("Launches FILE (e.g. ISO image) if present.\n"); - PRINT_STDOUT("Options (some of these are specific to SDL backend):\n"); + PRINT_STDOUT("Options:\n"); PRINT_STDOUT(" -h, --help show this message and exit\n"); PRINT_STDOUT(" --version show version information and exit\n"); @@ -234,17 +235,24 @@ int CommandLineOptions::PrintUsage(const char *progname, const char *situationTe // Skip mode-irrelevant parameters in help. continue; } - PRINT_STDOUT(" --%s%s%s\n", param.longName, + char key[25]{}; + snprintf(key, ARRAY_SIZE(key), " --%s%s%s", param.longName, param.shortName ? ", -" : "", param.shortName ? std::string(1, param.shortName).c_str() : ""); + // Fill key with spacing. + for (size_t j = strlen(key); j < ARRAY_SIZE(key) - 1; ++j) { + key[j] = ' '; + } if (param.type == CmdParamType::Enum) { + PRINT_STDOUT("%s%s\n", key, param.docString); PRINT_STDOUT(" options: "); for (int i = 0; i < param.enumCount; ++i) { PRINT_STDOUT("%s%s", param.enumValues[i], i + 1 < param.enumCount ? ", " : ""); } PRINT_STDOUT("\n"); + } else { + PRINT_STDOUT("%s%s\n", key, param.docString); } - PRINT_STDOUT(" %s\n", param.docString); } // These are only available in SDL. @@ -306,7 +314,7 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C logLevel = LogLevel::LVERBOSE; break; case 'h': - PrintUsage(argv[0], mode, nullptr); + PrintUsage(argv[0], nullptr); return CommandLineParseResult::Exit; // Legacy cpucore options. case 'j': @@ -352,7 +360,7 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C // We already incremented i. continue; } else if (equals(argv[i], "--help")) { - PrintUsage(argv[0], mode, nullptr); + PrintUsage(argv[0], nullptr); return CommandLineParseResult::Exit; } else if (equals(argv[i], "--version")) { printf("%s\n", PPSSPP_GIT_VERSION); diff --git a/Core/CmdLine.h b/Core/CmdLine.h index b2f1b34a53..9387b38632 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -87,8 +87,8 @@ struct CommandLineOptions { std::optional compare; std::optional bench; std::optional verbose; + std::optional timeout; std::optional screenshotFilename; std::optional screenshotFilenameSave; - std::optional timeout; }; diff --git a/Core/Config.cpp b/Core/Config.cpp index 5e0c52fd71..9d99b0d916 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -99,7 +99,7 @@ std::string DefaultLangRegion() { // Unfortunate default. There's no need to use bFirstRun, since this is only a default. static std::string defaultLangRegion = "en_US"; std::string langRegion = System_GetProperty(SYSPROP_LANGREGION); - if (g_i18nrepo.IniExists(langRegion)) { + if (!langRegion.empty() && g_i18nrepo.IniExists(langRegion)) { defaultLangRegion = langRegion; } else if (langRegion.length() >= 3) { // Don't give up. Let's try a fuzzy match - so nl_BE can match nl_NL. diff --git a/Windows/main.cpp b/Windows/main.cpp index 813c07ff33..a2940f7973 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -1310,7 +1310,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin MainWindow::DestroyDebugWindows(); DialogManager::DestroyAll(); - timeEndPeriod(1); + + TimeShutdown(); UnRegisterCMPTMFApis(); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index ab29ab0c3d..dd7d75cc54 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -2,8 +2,12 @@ // Headless version of PPSSPP, for testing using http://code.google.com/p/pspautotests/ . // See headless.txt. // To build on non-windows systems, just run CMake in the SDL directory, it will build both a normal ppsspp and the headless version. +// // Example command line to run a test in the VS debugger (useful to debug failures): // > --root pspautotests/tests/../ --compare --timeout=5 --graphics=software pspautotests/tests/cpu/cpu_alu/cpu_alu.prx +// Example command line for taking screenshots from a frame dump: +// > -l --graphics=vulkan --screenshot-save=vt_ref.bmp "D:\PSP ISO\dump\Depth\11578 Virtua Tennis pause menu ULES00126_0002.zip" --resolution-scale=2 +// // NOTE: In MSVC, don't forget to set the working directory to $ProjectDir\.. in debug settings. #include "ppsspp_config.h" @@ -17,13 +21,11 @@ #include #include "Common/Profiler/Profiler.h" -#include "Common/System/NativeApp.h" #include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/CommonWindows.h" #if PPSSPP_PLATFORM(WINDOWS) -#include #else #include #endif @@ -121,33 +123,18 @@ std::string NativeLoadSecret(std::string_view nameOfSecret) { return ""; } -int printUsage(const char *progname, const char *reason) { - if (reason != NULL) - fprintf(stderr, "Error: %s\n\n", reason); - fprintf(stderr, "PPSSPP Headless\n"); - fprintf(stderr, "This is primarily meant as a non-interactive test tool.\n\n"); - fprintf(stderr, "Usage: %s file.elf... [options]\n\n", progname); - fprintf(stderr, "Options:\n"); +int printUsage(const CommandLineOptions &options, const char *progname, const char *reason) { + options.PrintUsage(progname, reason); fprintf(stderr, " -m, --mount umd.cso mount iso on umd1:\n"); fprintf(stderr, " -r, --root some/path mount path on host0: (elfs must be in here)\n"); fprintf(stderr, " -l, --log full log output, not just emulated printfs\n"); - fprintf(stderr, " --debugger=PORT enable websocket debugger and break at start\n"); - - fprintf(stderr, " --graphics=BACKEND use a different gpu backend\n"); fprintf(stderr, " options: gles, software, directx9, etc.\n"); fprintf(stderr, " --screenshot=FILE compare against a screenshot\n"); fprintf(stderr, " --screenshot-save=FILE save rendered screenshot to a BMP file\n"); fprintf(stderr, " --max-mse=NUMBER maximum allowed MSE error for screenshot\n"); fprintf(stderr, " --timeout=SECONDS abort test it if takes longer than SECONDS\n"); - - fprintf(stderr, " -v, --verbose show the full passed/failed result\n"); - fprintf(stderr, " -i use the interpreter\n"); fprintf(stderr, " --ir use ir interpreter\n"); - fprintf(stderr, " -j use jit (default)\n"); - fprintf(stderr, " -c, --compare compare with output in file.expected\n"); - fprintf(stderr, " --bench run multiple times and output speed\n"); fprintf(stderr, "\nSee headless.txt for details.\n"); - return 1; } @@ -260,9 +247,9 @@ void System_SendDebugScreenshot(const uint8_t *data, int width, int height) { struct AutoTestOptions { double timeout; double maxScreenshotError; - bool compare : 1; - bool verbose : 1; - bool bench : 1; + bool compare; + bool verbose; + bool bench; }; bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const AutoTestOptions &opt) { @@ -464,6 +451,7 @@ int main(int argc, const char* argv[]) { testOptions.compare = cmdLineOptions.compare.value_or(false); testOptions.bench = cmdLineOptions.bench.value_or(false); testOptions.timeout = cmdLineOptions.timeout.value_or(std::numeric_limits::infinity()); + testOptions.verbose = cmdLineOptions.verbose.value_or(false); bool fullLog = false; const char *stateToLoad = 0; @@ -488,32 +476,26 @@ int main(int argc, const char* argv[]) { for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) { if (++i >= argc) - return printUsage(argv[0], "Missing argument after -m"); + return printUsage(cmdLineOptions, argv[0], "Missing argument after -m"); mountIso = argv[i]; } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--odslog")) outputDebugStringLog = true; - else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) - testOptions.verbose = true; else if (!strncmp(argv[i], "--max-mse=", strlen("--max-mse=")) && strlen(argv[i]) > strlen("--max-mse=")) testOptions.maxScreenshotError = strtod(argv[i] + strlen("--max-mse="), nullptr); else if (!strncmp(argv[i], "--state=", strlen("--state=")) && strlen(argv[i]) > strlen("--state=")) stateToLoad = argv[i] + strlen("--state="); else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) - return printUsage(argv[0], NULL); + return printUsage(cmdLineOptions, argv[0], NULL); else if (!strcmp(argv[i], "--ignore")) { if (++i >= argc) - return printUsage(argv[0], "Missing argument after --ignore"); + return printUsage(cmdLineOptions, argv[0], "Missing argument after --ignore"); ignoredTests.push_back(argv[i]); } } - if (!fullLog) { - printf("Pass the -l flag to see full log output.\n"); - } - for (const std::string &filename : cmdLineOptions.bootFilenames) { AddToTestsByPath(&testFilenames, filename); } @@ -683,7 +665,7 @@ int main(int argc, const char* argv[]) { AddToTestsByPath(&testFilenames, (g_Config.flash0Directory / "vsh/module/vshmain.prx").ToString()); } if (testFilenames.empty()) { - return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); + return printUsage(cmdLineOptions, argv[0], argc <= 1 ? NULL : "No executables specified"); } if (cmdLineOptions.debuggerPort.has_value()) { @@ -754,12 +736,10 @@ int main(int argc, const char* argv[]) { g_VFS.Clear(); g_logManager.Shutdown(); - if (cmdLineOptions.debuggerPort.has_value()) + if (cmdLineOptions.debuggerPort.has_value()) { net::Shutdown(); - -#if PPSSPP_PLATFORM(WINDOWS) - timeEndPeriod(1); -#endif + } + TimeShutdown(); g_threadManager.Teardown(); diff --git a/pspautotests b/pspautotests index 23ae650d05..3b281cf05e 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 23ae650d0537890247f49adb117618d715b75311 +Subproject commit 3b281cf05ec1ef5f604ba4f3a9ae0f773e73fee1 From e30b90e709ed9c1f5cacd6204a1478105e5dcdc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 17:51:36 +0200 Subject: [PATCH 07/11] Quiet and improve some logs --- Common/File/FileUtil.cpp | 26 ++++++++++---- Common/File/FileUtil.h | 2 +- Common/Log/LogManager.cpp | 72 +++++++++++++++++++-------------------- Core/CmdLine.cpp | 10 ++++-- Core/HLE/sceReg.cpp | 1 + headless/Headless.cpp | 5 ++- 6 files changed, 67 insertions(+), 49 deletions(-) diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index d0612e61a0..3d6a3e9a25 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -630,7 +630,7 @@ bool Delete(const Path &filename, bool quiet) { } // Returns true if successful, or path already exists. -bool CreateDir(const Path &path) { +bool CreateDir(const Path &path, bool quiet) { if (SIMULATE_SLOW_IO) { sleep_ms(100, "slow-io-sim"); INFO_LOG(Log::IO, "CreateDir %s", path.c_str()); @@ -651,11 +651,15 @@ bool CreateDir(const Path &path) { AndroidContentURI uri(path.ToString()); std::string newDirName = uri.GetLastPart(); if (uri.NavigateUp()) { - INFO_LOG(Log::IO, "Calling Android_CreateDirectory(%s, %s)", uri.ToString().c_str(), newDirName.c_str()); + if (!quiet) { + INFO_LOG(Log::IO, "Calling Android_CreateDirectory(%s, %s)", uri.ToString().c_str(), newDirName.c_str()); + } return Android_CreateDirectory(uri.ToString(), newDirName) == StorageError::SUCCESS; } else { // Bad path - can't create this directory. - WARN_LOG(Log::IO, "CreateDir failed: '%s'", path.c_str()); + if (!quiet) { + WARN_LOG(Log::IO, "CreateDir failed: '%s'", path.c_str()); + } return false; } break; @@ -686,10 +690,14 @@ bool CreateDir(const Path &path) { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { - DEBUG_LOG(Log::IO, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); + if (!quiet) { + DEBUG_LOG(Log::IO, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); + } return true; } - ERROR_LOG(Log::IO, "CreateDir: CreateDirectory failed on %s: %08x %s", path.c_str(), (uint32_t)error, GetStringErrorMsg(error).c_str()); + if (!quiet) { + ERROR_LOG(Log::IO, "CreateDir: CreateDirectory failed on %s: %08x %s", path.c_str(), (uint32_t)error, GetStringErrorMsg(error).c_str()); + } return false; #else if (mkdir(path.ToString().c_str(), 0755) == 0) { @@ -698,11 +706,15 @@ bool CreateDir(const Path &path) { int err = errno; if (err == EEXIST) { - DEBUG_LOG(Log::IO, "CreateDir: mkdir failed on %s: already exists", path.c_str()); + if (!quiet) { + DEBUG_LOG(Log::IO, "CreateDir: mkdir failed on %s: already exists", path.c_str()); + } return true; } - ERROR_LOG(Log::IO, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); + if (!quiet) { + ERROR_LOG(Log::IO, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); + } return false; #endif } diff --git a/Common/File/FileUtil.h b/Common/File/FileUtil.h index 7d078d8167..054b6c9d33 100644 --- a/Common/File/FileUtil.h +++ b/Common/File/FileUtil.h @@ -86,7 +86,7 @@ uint64_t GetFileSize(FILE *f); uint64_t ComputeRecursiveDirectorySize(const Path &path); // Returns true if successful, or path already exists. -bool CreateDir(const Path &filename); +bool CreateDir(const Path &filename, bool quiet = false); void ChangeMTime(const Path &path, time_t mtime); diff --git a/Common/Log/LogManager.cpp b/Common/Log/LogManager.cpp index fc1cdab996..c6e6ca32f0 100644 --- a/Common/Log/LogManager.cpp +++ b/Common/Log/LogManager.cpp @@ -69,50 +69,50 @@ void GenericLog(Log type, LogLevel level, const char *file, int line, const char // NOTE: Needs to be kept in sync with the Log enum. static const char * const g_logTypeNames[] = { - "SYSTEM", - "BOOT", - "COMMON", + "System", + "Boot", + "Common", "CPU", - "FILESYS", + "FileSystem", "G3D", - "TEXCACHE", + "TexCache", "HLE", "JIT", - "LOADER", - "MPEG", - "ATRAC", - "ME", // Rest of the media Engine - "MEMMAP", - "SASMIX", - "SAVESTATE", - "FRAMEBUF", - "AUDIO", + "Loader", + "Mpeg", + "Atrac", + "ME", + "MemMap", + "SasMix", + "SaveState", + "FrameBuf", + "Audio", "IO", - "ACHIEVEMENTS", + "Achievements", "HTTP", - "PRINTF", - "TEXREPLACE", - "DEBUGGER", - "GEDEBUGGER", + "Printf", + "TexReplacement", + "Debugger", + "GeDebugger", "UI", "IAP", - "CWCHEATS", - "NET", - "SCEAUDIO", - "SCECTRL", - "SCEDISP", - "SCEFONT", - "SCEGE", - "SCEINTC", - "SCEIO", - "SCEKERNEL", - "SCEMODULE", - "SCENET", - "SCERTC", - "SCESAS", - "SCEUTIL", - "SCEMISC", - "SCEREG", + "CwCheats", + "Net", + "sceAudio", + "sceCtrl", + "sceDisplay", + "sceFont", + "sceGe", + "sceIntc", + "sceIo", + "sceKernel", + "sceModule", + "sceNet", + "sceRtc", + "sceSas", + "sceUtility", + "sceMisc", + "sceReg", }; const char *LogManager::GetLogTypeName(Log type) { diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index 225d60dc7d..6e7508aa02 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -213,8 +213,14 @@ int CommandLineOptions::PrintUsage(const char *progname, const char *situationTe } } - PRINT_STDOUT("Usage: %s [options] [FILE]\n\n", progname); - PRINT_STDOUT("Launches FILE (e.g. ISO image) if present.\n"); + if (mode == CmdLineMode::Application) { + PRINT_STDOUT("Usage: %s [options] [FILE]\n\n", progname); + } else { + PRINT_STDOUT("Usage: %s [options] [FILE1] [FILE2] [FILE3]...\n\n", progname); + } + + PRINT_STDOUT("Launches FILE (for example, an ISO image) if present.\n"); + PRINT_STDOUT("See headless/README.md for more details.\n\n"); PRINT_STDOUT("Options:\n"); PRINT_STDOUT(" -h, --help show this message and exit\n"); PRINT_STDOUT(" --version show version information and exit\n"); diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index 8eb36ee349..4c8331eaec 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -60,6 +60,7 @@ struct KeyValue { // TODO: /DATA/FONT/PROPERTY could just be generated from our fontRegistry in sceFont.cpp. // Partial dump of the PSP registry using tests/misc/reg.prx in pspautotests +// TODO: We will need something more dynamic if we want to support writes, too. // Dump of /DATA/FONT/PROPERTY/INFO0 static const KeyValue tree_DATA_FONT_PROPERTY_INFO0[] = { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index dd7d75cc54..ecb652749a 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -1,6 +1,6 @@ // Headless version of PPSSPP, for testing using http://code.google.com/p/pspautotests/ . -// See headless.txt. +// See headless/README.md. // To build on non-windows systems, just run CMake in the SDL directory, it will build both a normal ppsspp and the headless version. // // Example command line to run a test in the VS debugger (useful to debug failures): @@ -134,7 +134,6 @@ int printUsage(const CommandLineOptions &options, const char *progname, const ch fprintf(stderr, " --max-mse=NUMBER maximum allowed MSE error for screenshot\n"); fprintf(stderr, " --timeout=SECONDS abort test it if takes longer than SECONDS\n"); fprintf(stderr, " --ir use ir interpreter\n"); - fprintf(stderr, "\nSee headless.txt for details.\n"); return 1; } @@ -615,7 +614,7 @@ int main(int argc, const char* argv[]) { #if PPSSPP_PLATFORM(WINDOWS) // Mount a filesystem g_Config.memStickDirectory = exePath / "memstick"; - File::CreateDir(g_Config.memStickDirectory); + File::CreateDir(g_Config.memStickDirectory, true); CreateSysDirectories(); #elif !PPSSPP_PLATFORM(ANDROID) g_Config.memStickDirectory = Path(std::string(getenv("HOME"))) / ".ppsspp"; From 456cfb0f5a109cbb57dd4406f2ffbe416745c236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 17:53:55 +0200 Subject: [PATCH 08/11] RAIntegration crashfix --- Core/RetroAchievements.cpp | 17 +++++++++++++++-- Core/RetroAchievements.h | 1 + Windows/main.cpp | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 4366d87359..84951deb9c 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -674,6 +674,16 @@ void Initialize() { rc_client_set_encore_mode_enabled(g_rcClient, g_Config.bAchievementsEncoreMode ? 1 : 0); rc_client_set_unofficial_enabled(g_rcClient, g_Config.bAchievementsUnofficial ? 1 : 0); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + if (!g_Config.bAchievementsEnableRAIntegration) { + TryLoginByToken(true); + } +#else + TryLoginByToken(true); +#endif +} + +void InitializeRAIntegration(void *windowHandle) { #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION if (g_Config.bAchievementsEnableRAIntegration) { wchar_t szFilePath[MAX_PATH]; @@ -684,12 +694,15 @@ void Initialize() { break; } } - HWND hWnd = (HWND)System_GetPropertyInt(SYSPROP_MAIN_WINDOW_HANDLE); + HWND hWnd = (HWND)windowHandle; + if (!hWnd) { + ERROR_LOG(Log::Achievements, "RAIntegration is enabled, but no main window handle was found."); + return; + } rc_client_begin_load_raintegration(g_rcClient, szFilePath, hWnd, "PPSSPP", PPSSPP_GIT_VERSION, &load_integration_callback, hWnd); return; } #endif - TryLoginByToken(true); } bool HasToken() { diff --git a/Core/RetroAchievements.h b/Core/RetroAchievements.h index 158c5a322e..aa70fcecba 100644 --- a/Core/RetroAchievements.h +++ b/Core/RetroAchievements.h @@ -71,6 +71,7 @@ bool RAIntegrationDirty(); rc_client_t *GetClient(); void Initialize(); +void InitializeRAIntegration(void *windowHandle); // This must be call after the main window exists. void UpdateSettings(); bool LoginProblems(std::string *errorString); diff --git a/Windows/main.cpp b/Windows/main.cpp index a2940f7973..f59273cbe7 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -1205,6 +1205,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin MainWindow::Show(_hInstance); HWND hwndMain = MainWindow::GetHWND(); + Achievements::InitializeRAIntegration(hwndMain); //initialize custom controls CtrlDisAsmView::init(); From 9949c2bf49855ded4c628f8847cf657185d8f3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 17:59:02 +0200 Subject: [PATCH 09/11] RAIntegration / retroachievements: Improve memory range checks --- Core/RetroAchievements.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 84951deb9c..77b154972b 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -12,6 +12,9 @@ // md5_hash(PSP_GAME/EBOOT.BIN) // hash = md5_finalize() +// To test RAIntegration, get the DLL here: https://github.com/RetroAchievements/RAIntegration/releases +// Then just place it next to PPSSPP and enable RAIntegration in PPSSPP achivement settings, then restart it. + #include #include #include @@ -253,11 +256,15 @@ bool IsActive() { static void raintegration_write_memory_handler(uint32_t address, uint8_t *buffer, uint32_t num_bytes, rc_client_t *client) { // convert_retroachievements_address_to_real_address - uint32_t realAddress = address + PSP_MEMORY_OFFSET; - uint8_t *writePtr = Memory::GetPointerWriteRange(realAddress, num_bytes); - if (writePtr) { - memcpy(writePtr, buffer, num_bytes); + const uint32_t realAddress = address + PSP_MEMORY_OFFSET; + if (!Memory::IsValidRange(realAddress, num_bytes)) { + ERROR_LOG(Log::Achievements, "RAIntegration write memory: Bad address range %08x-%08x (%d bytes) (%08x was passed in)", realAddress, realAddress + num_bytes, num_bytes, address); + return; } + + // We checked the pointer above, this is ok. + uint8_t *writePtr = Memory::GetPointerWriteUnchecked(realAddress); + memcpy(writePtr, buffer, num_bytes); } #endif @@ -265,22 +272,20 @@ static void raintegration_write_memory_handler(uint32_t address, uint8_t *buffer static uint32_t read_memory_callback(uint32_t address, uint8_t *buffer, uint32_t num_bytes, rc_client_t *client) { // Achievements are traditionally defined relative to the base of main memory of the emulated console. // This is some kind of RetroArch-related legacy. In the PSP's case, this is simply a straight offset of 0x08000000. - uint32_t orig_address = address; - address += PSP_MEMORY_OFFSET; + const uint32_t realAddress = address + PSP_MEMORY_OFFSET; - if (!Memory::IsValidRange(address, num_bytes)) { + if (!Memory::IsValidRange(realAddress, num_bytes)) { // Some achievement packs are really, really spammy. // So we'll just count the bad accesses. Achievements::g_stats.badMemoryAccessCount++; if (g_Config.bAchievementsLogBadMemReads) { - WARN_LOG(Log::G3D, "RetroAchievements PeekMemory: Bad address %08x (%d bytes) (%08x was passed in)", address, num_bytes, orig_address); + WARN_LOG(Log::G3D, "RetroAchievements PeekMemory: Bad address %08x (%d bytes) (%08x was passed in)", realAddress, num_bytes, address); } - // This tells rcheevos that the access was bad, which should now be handled properly. return 0; } - Memory::MemcpyUnchecked(buffer, address, num_bytes); + Memory::MemcpyUnchecked(buffer, realAddress, num_bytes); return num_bytes; } From f7c2eb7b4d2f0bc4d986a9d557f19c657360cda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 18:26:21 +0200 Subject: [PATCH 10/11] Add Alpha adhoc server --- assets/adhoc-servers.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/assets/adhoc-servers.json b/assets/adhoc-servers.json index 497d66bf57..5b66aacbe0 100644 --- a/assets/adhoc-servers.json +++ b/assets/adhoc-servers.json @@ -199,6 +199,18 @@ "description": "Dedicated regional relay server providing low-latency matchmaking for MENA players.", "data_mode": "AemuPostoffice", "status_data_json": "http://jeddah-relay.ddns.net/data.json" + }, + { + "name": "Alpha Adhoc Server", + "host": "140.245.237.12", + "discord": "https://discord.gg/fenYRERNRy", + "web": "http://140.245.237.12:8080/", + "location": "India", + "location-emoji": "🇮🇳", + "description": "Indian adhoc relay from alpha community", + "data_mode": "AemuPostoffice", + "status_xml": "", + "icon": "https://raw.githubusercontent.com/MainPiyushHoon/Alpha-Community-Webpage/refs/heads/main/src/images/ALPHA.webp" } ] } From c14959b0b6d8a835f3b3d9fb03b729db9e8ce7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Jul 2026 21:33:14 +0200 Subject: [PATCH 11/11] Buildfix/testfix --- Common/TimeUtil.cpp | 2 +- Core/HLE/sceReg.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Common/TimeUtil.cpp b/Common/TimeUtil.cpp index 789abbc5d3..e01c3108e8 100644 --- a/Common/TimeUtil.cpp +++ b/Common/TimeUtil.cpp @@ -76,7 +76,7 @@ void TimeInit() { } void TimeShutdown() { -#if PPSSPP_PLATFORM(WINDOWS) +#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) timeEndPeriod(1); #endif } diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index 4c8331eaec..62ac4220c6 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -61,6 +61,9 @@ struct KeyValue { // Partial dump of the PSP registry using tests/misc/reg.prx in pspautotests // TODO: We will need something more dynamic if we want to support writes, too. +// NOTE: updating with a new dump can cause tests to fail. These must stay as-is: +// E {"game_exec_count", ValueType::INT, "", (int)0x00000046}, +// E {"usb_connect_count", ValueType::INT, "", (int)0x000000ec}, // Dump of /DATA/FONT/PROPERTY/INFO0 static const KeyValue tree_DATA_FONT_PROPERTY_INFO0[] = { @@ -454,9 +457,9 @@ static const KeyValue tree_DATA_FONT[] = { // Dump of /DATA/COUNT static const KeyValue tree_DATA_COUNT[] = { { "boot_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 - { "game_exec_count", ValueType::INT, "", (int)0x56 }, // decimal: 86 + { "game_exec_count", ValueType::INT, "", (int)0x46 }, // decimal: 70 { "slide_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 - { "usb_connect_count", ValueType::INT, "", (int)0xf8 }, // decimal: 248 + { "usb_connect_count", ValueType::INT, "", (int)0xec }, // decimal: 236 { "wifi_connect_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 { "psn_access_count", ValueType::INT, "", (int)0x0 }, // decimal: 0 };