From a92bd2cd9f3af213d68caa17b231537cc9da72cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 12 Nov 2026 11:26:55 +0100 Subject: [PATCH] Reporting: Send the OS, device model and disc format, and the HLE flags Renames played_seconds to seconds_played. On SDL, the OS build is now uname's sysname and release on Linux and Mac. Co-Authored-By: Claude Opus 5.5 --- Core/Config.cpp | 4 ++-- Core/Reporting.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++- SDL/SDLMain.cpp | 12 ++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 2a7118362b..b33ab3339c 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -382,8 +382,8 @@ static constexpr ConfigSetting generalSettings[] = { ConfigSetting("RemoteScrollPosition", SETTING(g_Config, fRemoteScrollPosition), 0.0f, CfgFlag::DEFAULT), ConfigSetting("DebugOverlay", SETTING(g_Config, iDebugOverlay), 0, CfgFlag::DONT_SAVE), ConfigSetting("DefaultTab", SETTING(g_Config, iDefaultTab), 0, CfgFlag::DEFAULT), - ConfigSetting("DisableHLEFlags", SETTING(g_Config, iDisableHLE), 0, CfgFlag::PER_GAME), - ConfigSetting("ForceEnableHLEFlags", SETTING(g_Config, iForceEnableHLE), 0, CfgFlag::PER_GAME), + ConfigSetting("DisableHLEFlags", SETTING(g_Config, iDisableHLE), 0, CfgFlag::PER_GAME | CfgFlag::REPORT), + ConfigSetting("ForceEnableHLEFlags", SETTING(g_Config, iForceEnableHLE), 0, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("ScreenshotMode", SETTING(g_Config, iScreenshotMode), 0, CfgFlag::DEFAULT) .Label(I18NCat::SYSTEM, "Screenshot mode").Choices(screenshotModeNames), diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index b209945b96..65c08afc77 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include // for crc32 extern "C" { @@ -38,6 +40,7 @@ extern "C" { #include "Common/Serialize/SerializeFuncs.h" #include "Common/StringUtils.h" #include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Data/Text/I18n.h" #include "Common/Net/HTTPClient.h" #include "Common/Net/Resolve.h" @@ -424,9 +427,42 @@ namespace Reporting return disc_id + "_" + disc_version; } + // The container the game image is in, from its header: "cso", "chd", "pbp" or "iso". Empty for + // a directory. Cached, since it only changes with the game. + static std::string DiscContainer(const Path &path) { + static std::mutex cacheLock; + static Path cachedPath; + static std::string cachedContainer; + + std::lock_guard guard(cacheLock); + if (path == cachedPath) { + return cachedContainer; + } + cachedPath = path; + cachedContainer.clear(); + + std::unique_ptr loader(ConstructFileLoader(path)); + char header[8]{}; + if (!loader || !loader->Exists() || loader->IsDirectory() || loader->ReadAt(0, 1, 8, header) != 8) { + return cachedContainer; + } + if (!memcmp(header, "CISO", 4)) { + cachedContainer = "cso"; + } else if (!memcmp(header, "MComprHD", 8)) { + cachedContainer = "chd"; + } else if (!memcmp(header, "\0PBP", 4)) { + cachedContainer = "pbp"; + } else { + cachedContainer = "iso"; + } + return cachedContainer; + } + void AddGameInfo(UrlEncoder &postdata) { postdata.Add("game", CurrentGameID()); + postdata.Add("file_type", IdentifiedFileTypeToString(PSP_CoreParameter().fileType)); + postdata.Add("disc_container", DiscContainer(PSP_CoreParameter().fileToStart)); postdata.Add("game_title", StripTrailingNull(g_paramSFO.GetValueString("TITLE"))); postdata.Add("sdkver", sceKernelGetCompiledSdkVersion()); postdata.Add("module_name", lastModuleName); @@ -445,6 +481,15 @@ namespace Reporting postdata.Add("gpu_full", gpuFull); postdata.Add("cpu", cpu_info.Summarize()); postdata.Add("platform", GetPlatformIdentifer()); +#if PPSSPP_PLATFORM(ANDROID) + // On Android, SYSPROP_NAME is the device: "MANUFACTURER:MODEL". + postdata.Add("os", StringFromFormat("Android API %d", (int)System_GetPropertyInt(SYSPROP_SYSTEMVERSION))); + postdata.Add("device_model", System_GetProperty(SYSPROP_NAME)); +#else + postdata.Add("os", System_GetProperty(SYSPROP_NAME)); + postdata.Add("device_model", System_GetProperty(SYSPROP_DEVICE_MODEL)); +#endif + postdata.Add("os_build", System_GetProperty(SYSPROP_SYSTEMBUILD)); // Empty when there's no full firmware install (nothing, or just fonts pulled off a disc). InstalledFirmwareInfo firmware; @@ -466,7 +511,7 @@ namespace Reporting if (PSP_GetBootState() == BootState::Complete) { postdata.Add("ticks", (const uint64_t)CoreTiming::GetTicks(currentMIPS)); // Emulated seconds. Ticks alone don't say this, since games change the CPU clock. - postdata.Add("played_seconds", (double)CoreTiming::PeekGlobalTimeUs() / 1000000.0); + postdata.Add("seconds_played", (double)CoreTiming::PeekGlobalTimeUs() / 1000000.0); } float vps, fps; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 33b6a4e837..9773936ff2 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -2,6 +2,9 @@ #include #include #include +#if defined(__linux__) || defined(__APPLE__) +#include +#endif #include "ppsspp_config.h" #include @@ -1121,6 +1124,15 @@ std::string System_GetProperty(SystemProperty prop) { #if PPSSPP_PLATFORM(MAC) case SYSPROP_DEVICE_MODEL: return "Mac"; +#endif +#if defined(__linux__) || defined(__APPLE__) + case SYSPROP_SYSTEMBUILD: { + struct utsname name; + if (uname(&name) != 0) { + return ""; + } + return std::string(name.sysname) + " " + name.release; + } #endif case SYSPROP_NAME: #ifdef _WIN32