Browse Source

[core] Add overridable game setting functionality (#2963)

Adds a place to override specific game settings for specific vendors

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2963
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: Kleidis <kleidis1@protonmail.com>
Co-committed-by: Kleidis <kleidis1@protonmail.com>
pull/3174/head
Kleidis 5 days ago
committed by crueter
parent
commit
b9530ae80f
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 2
      src/core/CMakeLists.txt
  2. 46
      src/core/core.cpp
  3. 140
      src/core/game_settings.cpp
  4. 60
      src/core/game_settings.h

2
src/core/CMakeLists.txt

@ -17,6 +17,8 @@ add_library(core STATIC
constants.h constants.h
core.cpp core.cpp
core.h core.h
game_settings.cpp
game_settings.h
core_timing.cpp core_timing.cpp
core_timing.h core_timing.h
cpu_manager.cpp cpu_manager.cpp

46
src/core/core.cpp

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "game_settings.h"
#include "audio_core/audio_core.h" #include "audio_core/audio_core.h"
#include "common/fs/fs.h" #include "common/fs/fs.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -292,48 +293,6 @@ struct System::Impl {
return SystemResultStatus::Success; 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<u64, 10> 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, SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath, const std::string& filepath,
Service::AM::FrontendAppletParameters& params) { Service::AM::FrontendAppletParameters& params) {
@ -419,7 +378,8 @@ struct System::Impl {
LOG_ERROR(Core, "Failed to find program id for ROM"); LOG_ERROR(Core, "Failed to find program id for ROM");
} }
LoadOverrides(program_id);
GameSettings::LoadOverrides(program_id, gpu_core->Renderer());
if (auto room_member = Network::GetRoomMember().lock()) { if (auto room_member = Network::GetRoomMember().lock()) {
Network::GameInfo game_info; Network::GameInfo game_info;
game_info.name = name; game_info.name = name;

140
src/core/game_settings.cpp

@ -0,0 +1,140 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/game_settings.h"
#include <algorithm>
#include <cctype>
#include "common/logging/log.h"
#include "common/settings.h"
#include "video_core/renderer_base.h"
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
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(__FIREOS__)
return OS::FireOS;
#elif defined(__ANDROID__)
return OS::Android;
#elif defined(__OHOS__)
return OS::HarmonyOS;
#elif defined(__HAIKU__)
return OS::HaikuOS;
#elif defined(__DragonFly__)
return OS::DragonFlyBSD;
#elif defined(__NetBSD__)
return OS::NetBSD;
#elif defined(__OpenBSD__)
return OS::OpenBSD;
#elif defined(_AIX)
return OS::AIX;
#elif defined(__managarm__)
return OS::Managarm;
#elif defined(__redox__)
return OS::RedoxOS;
#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
return OS::IOS;
#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<TitleID>(program_id)) {
case TitleID::NinjaGaidenRagebound:
Settings::values.use_squashed_iterated_blend = true;
break;
default:
break;
}
LOG_INFO(Core, "Applied game settings for title ID {:016X} on OS {}, GPU vendor {} ({})",
program_id,
static_cast<int>(env.os),
static_cast<int>(env.vendor),
env.vendor_string);
}
} // namespace Core::GameSettings

60
src/core/game_settings.h

@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <cstdint>
#include <string>
namespace VideoCore { class RendererBase; }
namespace Core::GameSettings {
enum class OS {
Windows,
Linux,
MacOS,
IOS,
Android,
FireOS,
HarmonyOS,
FreeBSD,
DragonFlyBSD,
NetBSD,
OpenBSD,
HaikuOS,
AIX,
Managarm,
RedoxOS,
Solaris,
Unknown,
};
enum class GPUVendor {
Nvidia,
AMD,
Intel,
Apple,
Qualcomm,
ARM,
Imagination,
Microsoft,
Unknown,
};
enum class TitleID : std::uint64_t {
NinjaGaidenRagebound = 0x0100781020710000ULL
};
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
Loading…
Cancel
Save