From 707fb5205f3c1d9ba3bcc113269cc76dd164bdab Mon Sep 17 00:00:00 2001 From: kleidis Date: Wed, 5 Nov 2025 22:52:35 +0100 Subject: [PATCH] [core] Add overridable game setting functionality --- src/core/CMakeLists.txt | 2 + src/core/GameSettings.cpp | 119 ++++++++++++++++++++++++++++++++++++++ src/core/GameSettings.h | 50 ++++++++++++++++ src/core/core.cpp | 45 -------------- 4 files changed, 171 insertions(+), 45 deletions(-) create mode 100644 src/core/GameSettings.cpp create mode 100644 src/core/GameSettings.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 83aabdbc72..c32f3941bc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -17,6 +17,8 @@ add_library(core STATIC constants.h core.cpp core.h + GameSettings.cpp + GameSettings.h core_timing.cpp core_timing.h cpu_manager.cpp diff --git a/src/core/GameSettings.cpp b/src/core/GameSettings.cpp new file mode 100644 index 0000000000..f5ce34bb14 --- /dev/null +++ b/src/core/GameSettings.cpp @@ -0,0 +1,119 @@ +// Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/GameSettings.h" + +#include +#include + +#include "common/logging/log.h" +#include "common/settings.h" +#include "video_core/renderer_base.h" + +namespace Core::GameSettings { + +static GPUVendor GetGPU(const std::string& gpu_vendor_string) { + struct Entry { const char* name; GPUVendor vendor; }; + static constexpr Entry GpuVendor[] = { + // NVIDIA + {"NVIDIA", GPUVendor::Nvidia}, + {"Nouveau", GPUVendor::Nvidia}, + {"NVK", GPUVendor::Nvidia}, + {"Tegra", GPUVendor::Nvidia}, + // AMD + {"AMD", GPUVendor::AMD}, + {"RadeonSI", GPUVendor::AMD}, + {"RADV", GPUVendor::AMD}, + {"AMDVLK", GPUVendor::AMD}, + {"R600", GPUVendor::AMD}, + // Intel + {"Intel", GPUVendor::Intel}, + {"ANV", GPUVendor::Intel}, + {"i965", GPUVendor::Intel}, + {"i915", GPUVendor::Intel}, + {"OpenSWR", GPUVendor::Intel}, + // Apple + {"Apple", GPUVendor::Apple}, + {"MoltenVK", GPUVendor::Apple}, + // Qualcomm / Adreno + {"Qualcomm", GPUVendor::Qualcomm}, + {"Turnip", GPUVendor::Qualcomm}, + // ARM / Mali + {"Mali", GPUVendor::ARM}, + {"PanVK", GPUVendor::ARM}, + // Imagination / PowerVR + {"PowerVR", GPUVendor::Imagination}, + {"PVR", GPUVendor::Imagination}, + // Microsoft / WARP / D3D12 GL + {"D3D12", GPUVendor::Microsoft}, + {"Microsoft", GPUVendor::Microsoft}, + {"WARP", GPUVendor::Microsoft}, + }; + + for (const auto& entry : GpuVendor) { + if (gpu_vendor_string == entry.name) { + return entry.vendor; + } + } + + // legacy (shouldn't be needed anymore, but just in case) + std::string gpu = gpu_vendor_string; + std::transform(gpu.begin(), gpu.end(), gpu.begin(), [](unsigned char c){ return (char)std::tolower(c); }); + if (gpu.find("geforce") != std::string::npos) { + return GPUVendor::Nvidia; + } + if (gpu.find("radeon") != std::string::npos || gpu.find("ati") != std::string::npos) { + return GPUVendor::AMD; + } + + return GPUVendor::Unknown; +} + +static OS DetectOS() { +#if defined(_WIN32) + return OS::Windows; +#elif defined(__ANDROID__) + return OS::Android; +#elif defined(__APPLE__) + return OS::MacOS; +#elif defined(__FreeBSD__) + return OS::FreeBSD; +#elif defined(__sun) && defined(__SVR4) + return OS::Solaris; +#elif defined(__linux__) + return OS::Linux; +#else + return OS::Unknown; +#endif +} + +EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer) { + EnvironmentInfo env{}; + env.os = DetectOS(); + env.vendor_string = renderer.GetDeviceVendor(); + env.vendor = GetGPU(env.vendor_string); + return env; +} + +void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer) { + const auto env = DetectEnvironment(renderer); + + switch (static_cast(program_id)) { + case TitleID::SuperMario3DWorld: + // examples + /*if (env.os == OS::Android || env.vendor == GPUVendor::ARM) { + Settings::values.aspect_ratio = Settings::AspectRatio::R21_9; + } + break;*/ + default: + break; + } + + LOG_INFO(Core, "Applied game settings for title ID {:016X} on OS {}, GPU vendor {} ({})", + program_id, + static_cast(env.os), + static_cast(env.vendor), + env.vendor_string); +} + +} // namespace Core::GameSettings diff --git a/src/core/GameSettings.h b/src/core/GameSettings.h new file mode 100644 index 0000000000..e50743d87f --- /dev/null +++ b/src/core/GameSettings.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include + +namespace VideoCore { class RendererBase; } + +namespace Core::GameSettings { + +enum class OS { + Windows, + Linux, + MacOS, + Android, + FreeBSD, + Solaris, + Unknown, +}; + +enum class GPUVendor { + Nvidia, + AMD, + Intel, + Apple, + Qualcomm, + ARM, + Imagination, + Microsoft, + Unknown, +}; + +enum class TitleID : std::uint64_t { + SuperMario3DWorld = 0x010028600EBDA000ULL, +}; + +struct EnvironmentInfo { + OS os{OS::Unknown}; + GPUVendor vendor{GPUVendor::Unknown}; + std::string vendor_string; // raw string from driver +}; + +EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer); + +void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer); + +} // namespace Core::GameSettings diff --git a/src/core/core.cpp b/src/core/core.cpp index 6c321afdbb..4a5a73a2fe 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -292,48 +292,6 @@ struct System::Impl { return SystemResultStatus::Success; } - - void LoadOverrides(u64 programId) const { - std::string vendor = gpu_core->Renderer().GetDeviceVendor(); - LOG_INFO(Core, "GPU Vendor: {}", vendor); - - // Reset all per-game flags - Settings::values.use_squashed_iterated_blend = false; - - // Insert PC overrides here - - #ifdef ANDROID - // Example on how to set a setting based on the program ID and vendor - if (programId == 0x010028600EBDA000 && vendor == "Mali") { // Mario 3d World - // Settings::values.example = true; - } - - // Example array of program IDs - const std::array example_array = { - //0xprogramId - 0x0004000000033400, // Game 1 - 0x0004000000033500 // Game 2 - // And so on - }; - - for (auto id : example_array) { - if (programId == id) { - // Settings::values.example = true; - break; - } - } - - #endif - - // Ninja Gaiden Ragebound - constexpr u64 ngr = 0x0100781020710000ULL; - - if (programId == ngr) { - LOG_INFO(Core, "Enabling game specifc override: use_squashed_iterated_blend"); - Settings::values.use_squashed_iterated_blend = true; - } - } - SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) { @@ -435,9 +393,6 @@ struct System::Impl { void ShutdownMainProcess() { SetShuttingDown(true); - // Reset per-game flags - Settings::values.use_squashed_iterated_blend = false; - is_powered_on = false; exit_locked = false; exit_requested = false;