diff --git a/CMakeLists.txt b/CMakeLists.txt index c37ac2a06..c276d3cd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -844,6 +844,8 @@ set(CORE src/core/aerolib/stubs.cpp src/core/emulator_settings.h src/core/user_manager.cpp src/core/user_manager.h + src/core/emulator_state.cpp + src/core/emulator_state.h ) if (ARCHITECTURE STREQUAL "x86_64") diff --git a/src/common/config.cpp b/src/common/config.cpp index d3571b7c0..4923cf78f 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -146,7 +146,9 @@ static ConfigEntry> userNames({ static ConfigEntry useUnifiedInputConfig(true); // Debug -static ConfigEntry isFpsColor(true); +static ConfigEntry isDebugDump(false); +static ConfigEntry isShaderDebug(false); +static ConfigEntry isSeparateLogFilesEnabled(false); static ConfigEntry showFpsCounter(false); // Settings @@ -161,7 +163,24 @@ static string config_version = Common::g_scm_rev; // These entries aren't stored in the config static bool overrideControllerColor = false; static int controllerCustomColorRGB[3] = {0, 0, 255}; -static bool load_auto_patches = true; + +std::filesystem::path getSysModulesPath() { + if (sys_modules_path.empty()) { + return Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir); + } + return sys_modules_path; +} + +void setSysModulesPath(const std::filesystem::path& path) { + sys_modules_path = path; +} + +int getVolumeSlider() { + return volumeSlider.get(); +} +bool allowHDR() { + return isHDRAllowed.get(); +} bool GetUseUnifiedInputConfig() { return useUnifiedInputConfig.get(); @@ -211,10 +230,6 @@ std::string getUserName(int id) { return userNames.get()[id]; } -bool fpsColor() { - return isFpsColor.get(); -} - bool getShowFpsCounter() { return showFpsCounter.get(); } @@ -231,11 +246,64 @@ u32 GetLanguage() { return m_language.get(); } -bool getLoadAutoPatches() { - return load_auto_patches; +bool getSeparateLogFilesEnabled() { + return isSeparateLogFilesEnabled.get(); } -void setLoadAutoPatches(bool enable) { - load_auto_patches = enable; + +bool getPSNSignedIn() { + return isPSNSignedIn.get(); +} + +void setPSNSignedIn(bool sign, bool is_game_specific) { + isPSNSignedIn.set(sign, is_game_specific); +} + +string getDefaultControllerID() { + return defaultControllerID.get(); +} + +void setDefaultControllerID(string id) { + defaultControllerID.base_value = id; +} + +bool getBackgroundControllerInput() { + return backgroundControllerInput.get(); +} + +void setBackgroundControllerInput(bool enable, bool is_game_specific) { + backgroundControllerInput.set(enable, is_game_specific); +} + +bool getFsrEnabled() { + return fsrEnabled.get(); +} + +void setFsrEnabled(bool enable, bool is_game_specific) { + fsrEnabled.set(enable, is_game_specific); +} + +bool getRcasEnabled() { + return rcasEnabled.get(); +} + +void setRcasEnabled(bool enable, bool is_game_specific) { + rcasEnabled.set(enable, is_game_specific); +} + +int getRcasAttenuation() { + return rcasAttenuation.get(); +} + +void setRcasAttenuation(int value, bool is_game_specific) { + rcasAttenuation.set(value, is_game_specific); +} + +int getUsbDeviceBackend() { + return usbDeviceBackend.get(); +} + +void setUsbDeviceBackend(int value, bool is_game_specific) { + usbDeviceBackend.set(value, is_game_specific); } void load(const std::filesystem::path& path, bool is_game_specific) { @@ -273,7 +341,9 @@ void load(const std::filesystem::path& path, bool is_game_specific) { string current_version = {}; if (data.contains("Debug")) { const toml::value& debug = data.at("Debug"); - isFpsColor.setFromToml(debug, "FPSColor", is_game_specific); + isDebugDump.setFromToml(debug, "DebugDump", is_game_specific); + isSeparateLogFilesEnabled.setFromToml(debug, "isSeparateLogFilesEnabled", is_game_specific); + isShaderDebug.setFromToml(debug, "CollectShader", is_game_specific); showFpsCounter.setFromToml(debug, "showFpsCounter", is_game_specific); current_version = toml::find_or(debug, "ConfigVersion", current_version); } @@ -358,7 +428,9 @@ void save(const std::filesystem::path& path, bool is_game_specific) { // Do not save these entries in the game-specific dialog since they are not in the GUI data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig.base_value; - data["Debug"]["FPSColor"] = isFpsColor.base_value; + data["GPU"]["internalScreenWidth"] = internalScreenWidth.base_value; + data["GPU"]["internalScreenHeight"] = internalScreenHeight.base_value; + data["GPU"]["patchShaders"] = shouldPatchShaders.base_value; data["Debug"]["showFpsCounter"] = showFpsCounter.base_value; } @@ -391,7 +463,6 @@ void setDefaultValues(bool is_game_specific) { controllerCustomColorRGB[2] = 255; // Debug - isFpsColor.base_value = true; showFpsCounter.base_value = false; } } diff --git a/src/common/config.h b/src/common/config.h index e1f8c2e77..04c55d422 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -28,12 +28,18 @@ std::string getTrophyKey(); void setTrophyKey(std::string key); u32 GetLanguage(); void setLanguage(u32 language, bool is_game_specific = false); -bool fpsColor(); // no set +void setUseSpecialPad(bool use); +bool getUseSpecialPad(); +void setSpecialPadClass(int type); +int getSpecialPadClass(); +bool getPSNSignedIn(); +void setPSNSignedIn(bool sign, bool is_game_specific = false); +bool patchShaders(); // no set bool getShowFpsCounter(); void setShowFpsCounter(bool enable, bool is_game_specific = false); void setUserName(const std::string& name, bool is_game_specific = false); -bool getLoadAutoPatches(); -void setLoadAutoPatches(bool enable); +std::filesystem::path getSysModulesPath(); +void setSysModulesPath(const std::filesystem::path& path); // TODO std::string getUserName(int id); diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp index ad737dab4..a7c020246 100644 --- a/src/common/memory_patcher.cpp +++ b/src/common/memory_patcher.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -12,6 +12,7 @@ #include "common/elf_info.h" #include "common/logging/log.h" #include "common/path_util.h" +#include "core/emulator_state.h" #include "core/file_format/psf.h" #include "memory_patcher.h" @@ -192,7 +193,7 @@ void OnGameLoaded() { } else { ApplyPatchesFromXML(file_path); } - } else if (Config::getLoadAutoPatches()) { + } else if (EmulatorState::GetInstance()->IsAutoPatchesLoadEnabled()) { for (auto const& repo : std::filesystem::directory_iterator(patch_dir)) { if (!repo.is_directory()) { continue; diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp index 5a0fdfd4d..d599e9cf0 100644 --- a/src/core/devtools/layer.cpp +++ b/src/core/devtools/layer.cpp @@ -12,6 +12,7 @@ #include "common/types.h" #include "core/debug_state.h" #include "core/emulator_settings.h" +#include "core/emulator_state.h" #include "imgui/imgui_std.h" #include "imgui_internal.h" #include "options.h" @@ -274,14 +275,10 @@ void L::DrawAdvanced() { void L::DrawSimple() { const float frameRate = DebugState.Framerate; - if (Config::fpsColor()) { - if (frameRate < 10) { - PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // Red - } else if (frameRate >= 10 && frameRate < 20) { - PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f)); // Orange - } else { - PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); // White - } + if (frameRate < 10) { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // Red + } else if (frameRate >= 10 && frameRate < 20) { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f)); // Orange } else { PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); // White } diff --git a/src/core/emulator_state.cpp b/src/core/emulator_state.cpp new file mode 100644 index 000000000..1f02043a3 --- /dev/null +++ b/src/core/emulator_state.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2025-2026 shadLauncher4 Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "emulator_state.h" + +std::shared_ptr EmulatorState::s_instance = nullptr; +std::mutex EmulatorState::s_mutex; + +EmulatorState::EmulatorState() {} + +EmulatorState::~EmulatorState() {} + +std::shared_ptr EmulatorState::GetInstance() { + std::lock_guard lock(s_mutex); + if (!s_instance) + s_instance = std::make_shared(); + return s_instance; +} + +void EmulatorState::SetInstance(std::shared_ptr instance) { + std::lock_guard lock(s_mutex); + s_instance = instance; +} + +bool EmulatorState::IsGameRunning() const { + return m_running; +} +void EmulatorState::SetGameRunning(bool running) { + m_running = running; +} + +bool EmulatorState::IsAutoPatchesLoadEnabled() const { + return m_load_patches_auto; +} +void EmulatorState::SetAutoPatchesLoadEnabled(bool enable) { + m_load_patches_auto = enable; +} diff --git a/src/core/emulator_state.h b/src/core/emulator_state.h new file mode 100644 index 000000000..c12af5401 --- /dev/null +++ b/src/core/emulator_state.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2025-2026 shadLauncher4 Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +class EmulatorState { +public: + EmulatorState(); + ~EmulatorState(); + + static std::shared_ptr GetInstance(); + static void SetInstance(std::shared_ptr instance); + + bool IsGameRunning() const; + void SetGameRunning(bool running); + bool IsAutoPatchesLoadEnabled() const; + void SetAutoPatchesLoadEnabled(bool enable); + +private: + static std::shared_ptr s_instance; + static std::mutex s_mutex; + + // state variables + bool m_running = false; + bool m_load_patches_auto = true; +}; \ No newline at end of file diff --git a/src/core/ipc/ipc.cpp b/src/core/ipc/ipc.cpp index 4116bba1d..cf0c1d81e 100644 --- a/src/core/ipc/ipc.cpp +++ b/src/core/ipc/ipc.cpp @@ -15,6 +15,7 @@ #include "core/debug_state.h" #include "core/debugger.h" #include "core/emulator_settings.h" +#include "core/emulator_state.h" #include "core/libraries/audio/audioout.h" #include "input/input_handler.h" #include "sdl_window.h" @@ -72,7 +73,7 @@ void IPC::Init() { return; } - Config::setLoadAutoPatches(false); + EmulatorState::GetInstance()->SetAutoPatchesLoadEnabled(false); input_thread = std::jthread([this] { Common::SetCurrentThreadName("IPC Read thread"); diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index 3b1b121df..4837e65da 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -37,9 +37,11 @@ s32 PS4_SYSV_ABI sceKernelGetMainSocId() { } s32 PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(s32* ver) { - s32 version = Common::ElfInfo::Instance().CompiledSdkVer(); - *ver = version; - return (version >= 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL; + if (!ver) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + *ver = Common::ElfInfo::Instance().CompiledSdkVer(); + return ORBIS_OK; } s32 PS4_SYSV_ABI sceKernelGetCpumode() { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index cb40e8e48..94eb52f47 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -181,8 +181,8 @@ s32 Linker::LoadAndStartModule(const std::filesystem::path& path, u64 args, cons } // Retrieve and verify proc param according to libkernel. - u64* param = module->GetProcParam(); - ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]); + auto* param = module->GetProcParam(); + ASSERT_MSG(!param || param->size >= 0x18, "Invalid module param size: {}", param->size); s32 ret = module->Start(args, argp, param); if (pRes) { *pRes = ret; diff --git a/src/emulator.cpp b/src/emulator.cpp index c16ce5963..cfef7643c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -75,6 +75,25 @@ Emulator::Emulator() { Emulator::~Emulator() {} +s32 ReadCompiledSdkVersion(const std::filesystem::path& file) { + Core::Loader::Elf elf; + elf.Open(file); + if (!elf.IsElfFile()) { + return 0; + } + const auto elf_pheader = elf.GetProgramHeader(); + auto i_procparam = std::find_if(elf_pheader.begin(), elf_pheader.end(), [](const auto& entry) { + return entry.p_type == PT_SCE_PROCPARAM; + }); + + if (i_procparam != elf_pheader.end()) { + Core::OrbisProcParam param{}; + elf.LoadSegment(u64(¶m), i_procparam->p_offset, i_procparam->p_filesz); + return param.sdk_version; + } + return 0; +} + void Emulator::Run(std::filesystem::path file, std::vector args, std::optional p_game_folder) { Common::SetCurrentThreadName("Main Thread"); @@ -163,6 +182,9 @@ void Emulator::Run(std::filesystem::path file, std::vector args, } } + auto guest_eboot_path = "/app0/" + eboot_name.generic_string(); + const auto eboot_path = mnt->GetHostPath(guest_eboot_path); + auto& game_info = Common::ElfInfo::Instance(); game_info.initialized = true; game_info.game_serial = id; @@ -170,7 +192,7 @@ void Emulator::Run(std::filesystem::path file, std::vector args, game_info.app_ver = app_version; game_info.firmware_ver = fw_version & 0xFFF00000; game_info.raw_firmware_ver = fw_version; - game_info.sdk_ver = sdk_version; + game_info.sdk_ver = ReadCompiledSdkVersion(eboot_path); game_info.psf_attributes = psf_attributes; const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); @@ -259,7 +281,8 @@ void Emulator::Run(std::filesystem::path file, std::vector args, if (param_sfo_exists) { LOG_INFO(Loader, "Game id: {} Title: {}", id, title); LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); - LOG_INFO(Loader, "Compiled SDK version: {:#x}", sdk_version); + LOG_INFO(Loader, "param.sfo SDK version: {:#x}", sdk_version); + LOG_INFO(Loader, "eboot SDK version: {:#x}", game_info.sdk_ver); LOG_INFO(Loader, "PSVR Supported: {}", (bool)psf_attributes.support_ps_vr.Value()); LOG_INFO(Loader, "PSVR Required: {}", (bool)psf_attributes.require_ps_vr.Value()); } @@ -358,8 +381,6 @@ void Emulator::Run(std::filesystem::path file, std::vector args, Libraries::InitHLELibs(&linker->GetHLESymbols()); // Load the module with the linker - auto guest_eboot_path = "/app0/" + eboot_name.generic_string(); - const auto eboot_path = mnt->GetHostPath(guest_eboot_path); if (linker->LoadModule(eboot_path) == -1) { LOG_CRITICAL(Loader, "Failed to load game's eboot.bin: {}", Common::FS::PathToUTF8String(std::filesystem::absolute(eboot_path))); diff --git a/src/main.cpp b/src/main.cpp index 515b6a15b..34ed6333b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -8,6 +8,7 @@ #include "system_error" #include "unordered_map" +#include #include #include "common/config.h" #include "common/logging/backend.h" @@ -28,7 +29,9 @@ int main(int argc, char* argv[]) { SetConsoleOutputCP(CP_UTF8); #endif IPC::Instance().Init(); - + // Init emulator state + std::shared_ptr m_emu_state = std::make_shared(); + EmulatorState::SetInstance(m_emu_state); // Load configurations std::shared_ptr emu_settings = std::make_shared(); EmulatorSettings::SetInstance(emu_settings);