diff --git a/src/common/config.cpp b/src/common/config.cpp index 246644e2d..9e2cc0020 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -100,7 +100,7 @@ void setTrophyKey(std::string key) { trophyKey = key; } -bool isNeoMode() { +bool isNeoModeConsole() { return isNeo; } diff --git a/src/common/config.h b/src/common/config.h index 9d943008b..2b9a35449 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -18,7 +18,7 @@ void saveMainWindow(const std::filesystem::path& path); std::string getTrophyKey(); void setTrophyKey(std::string key); -bool isNeoMode(); +bool isNeoModeConsole(); bool isFullscreenMode(); bool getPlayBGM(); int getBGMvolume(); diff --git a/src/common/elf_info.h b/src/common/elf_info.h index 6eb144e9a..02eefbb7a 100644 --- a/src/common/elf_info.h +++ b/src/common/elf_info.h @@ -7,6 +7,7 @@ #include #include "assert.h" +#include "bit_field.h" #include "singleton.h" #include "types.h" @@ -16,6 +17,46 @@ class Emulator; namespace Common { +union PSFAttributes { + /// Supports initial user's logout + BitField<0, 1, u32> support_initial_user_logout; + /// Enter button for the common dialog is cross. + BitField<1, 1, u32> enter_button_cross; + /// Warning dialog for PS Move is displayed in the options menu. + BitField<2, 1, u32> ps_move_warning; + /// Supports stereoscopic 3D. + BitField<3, 1, u32> support_stereoscopic_3d; + /// Suspends when PS button is pressed. + BitField<4, 1, u32> ps_button_suspend; + /// Enter button for the common dialog is assigned by the system software. + BitField<5, 1, u32> enter_button_system; + /// Overrides share menu behavior. + BitField<6, 1, u32> override_share_menu; + /// Suspends when PS button is pressed and special output resolution is set. + BitField<8, 1, u32> special_res_ps_button_suspend; + /// Enable HDCP. + BitField<9, 1, u32> enable_hdcp; + /// Disable HDCP for non-game. + BitField<10, 1, u32> disable_hdcp_non_game; + /// Supports PS VR. + BitField<14, 1, u32> support_ps_vr; + /// CPU mode (6 CPU) + BitField<15, 1, u32> six_cpu_mode; + /// CPU mode (7 CPU) + BitField<16, 1, u32> seven_cpu_mode; + /// Supports PS4 Pro (Neo) mode. + BitField<23, 1, u32> support_neo_mode; + /// Requires PS VR. + BitField<26, 1, u32> require_ps_vr; + /// Supports HDR. + BitField<29, 1, u32> support_hdr; + /// Display location. + BitField<31, 1, u32> display_location; + + u32 raw{}; +}; +static_assert(sizeof(PSFAttributes) == 4); + class ElfInfo { friend class Core::Emulator; @@ -26,6 +67,7 @@ class ElfInfo { std::string app_ver{}; u32 firmware_ver = 0; u32 raw_firmware_ver = 0; + PSFAttributes psf_attributes{}; public: static constexpr u32 FW_15 = 0x1500000; @@ -68,6 +110,11 @@ public: ASSERT(initialized); return raw_firmware_ver; } + + [[nodiscard]] const PSFAttributes& PSFAttributes() const { + ASSERT(initialized); + return psf_attributes; + } }; } // namespace Common diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index 97cc01ebc..2fa597d4d 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -14,7 +14,7 @@ namespace Libraries::Kernel { int PS4_SYSV_ABI sceKernelIsNeoMode() { LOG_DEBUG(Kernel_Sce, "called"); - return Config::isNeoMode(); + return Config::isNeoModeConsole() && Common::ElfInfo::Instance().PSFAttributes().support_neo_mode; } int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) { diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 0a69ad773..1327ede5f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -7,6 +7,7 @@ #include "common/debug.h" #include "core/libraries/kernel/memory.h" #include "core/libraries/kernel/orbis_error.h" +#include "core/libraries/kernel/process.h" #include "core/memory.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" @@ -35,7 +36,7 @@ MemoryManager::~MemoryManager() = default; void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2) { - const bool is_neo = Config::isNeoMode(); + const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode(); auto total_size = is_neo ? SCE_KERNEL_TOTAL_MEM_PRO : SCE_KERNEL_TOTAL_MEM; if (!use_extended_mem1 && is_neo) { total_size -= 256_MB; diff --git a/src/emulator.cpp b/src/emulator.cpp index 4f0c61236..5d037e26c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -28,8 +28,6 @@ #include "core/file_format/trp.h" #include "core/file_sys/fs.h" #include "core/libraries/disc_map/disc_map.h" -#include "core/libraries/fiber/fiber.h" -#include "core/libraries/jpeg/jpegenc.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" @@ -59,8 +57,8 @@ Emulator::Emulator() { LOG_INFO(Loader, "Branch {}", Common::g_scm_branch); LOG_INFO(Loader, "Description {}", Common::g_scm_desc); - LOG_INFO(Config, "General Logtype: {}", Config::getLogType()); - LOG_INFO(Config, "General isNeo: {}", Config::isNeoMode()); + LOG_INFO(Config, "General LogType: {}", Config::getLogType()); + LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole()); LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu()); LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders()); LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv()); @@ -101,19 +99,12 @@ Emulator::~Emulator() { } void Emulator::Run(const std::filesystem::path& file) { - - // Use the eboot from the separated updates folder if it's there - std::filesystem::path game_patch_folder = file.parent_path(); - game_patch_folder += "-UPDATE"; - std::filesystem::path eboot_path = std::filesystem::exists(game_patch_folder / file.filename()) - ? game_patch_folder / file.filename() - : file; - // Applications expect to be run from /app0 so mount the file's parent path as app0. auto* mnt = Common::Singleton::Instance(); - mnt->Mount(file.parent_path(), "/app0"); + const auto game_folder = file.parent_path(); + mnt->Mount(game_folder, "/app0"); // Certain games may use /hostapp as well such as CUSA001100 - mnt->Mount(file.parent_path(), "/hostapp"); + mnt->Mount(game_folder, "/hostapp"); auto& game_info = Common::ElfInfo::Instance(); @@ -122,50 +113,52 @@ void Emulator::Run(const std::filesystem::path& file) { std::string title; std::string app_version; u32 fw_version; + Common::PSFAttributes psf_attributes{}; - std::filesystem::path sce_sys_folder = eboot_path.parent_path() / "sce_sys"; - if (std::filesystem::is_directory(sce_sys_folder)) { - for (const auto& entry : std::filesystem::directory_iterator(sce_sys_folder)) { - if (entry.path().filename() == "param.sfo") { - auto* param_sfo = Common::Singleton::Instance(); - const bool success = param_sfo->Open(sce_sys_folder / "param.sfo"); - ASSERT_MSG(success, "Failed to open param.sfo"); - const auto content_id = param_sfo->GetString("CONTENT_ID"); - ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID"); - id = std::string(*content_id, 7, 9); - Libraries::NpTrophy::game_serial = id; - const auto trophyDir = - Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles"; - if (!std::filesystem::exists(trophyDir)) { - TRP trp; - if (!trp.Extract(eboot_path.parent_path(), id)) { - LOG_ERROR(Loader, "Couldn't extract trophies"); - } - } + const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo"); + if (std::filesystem::exists(param_sfo_path)) { + auto* param_sfo = Common::Singleton::Instance(); + const bool success = param_sfo->Open(param_sfo_path); + ASSERT_MSG(success, "Failed to open param.sfo"); + const auto content_id = param_sfo->GetString("CONTENT_ID"); + ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID"); + id = std::string(*content_id, 7, 9); + Libraries::NpTrophy::game_serial = id; + const auto trophyDir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles"; + if (!std::filesystem::exists(trophyDir)) { + TRP trp; + if (!trp.Extract(game_folder, id)) { + LOG_ERROR(Loader, "Couldn't extract trophies"); + } + } #ifdef ENABLE_QT_GUI - MemoryPatcher::g_game_serial = id; + MemoryPatcher::g_game_serial = id; - // Timer for 'Play Time' - QTimer* timer = new QTimer(); - QObject::connect(timer, &QTimer::timeout, [this, id]() { - UpdatePlayTime(id); - start_time = std::chrono::steady_clock::now(); - }); - timer->start(60000); // 60000 ms = 1 minute + // Timer for 'Play Time' + QTimer* timer = new QTimer(); + QObject::connect(timer, &QTimer::timeout, [this, id]() { + UpdatePlayTime(id); + start_time = std::chrono::steady_clock::now(); + }); + timer->start(60000); // 60000 ms = 1 minute #endif - title = param_sfo->GetString("TITLE").value_or("Unknown title"); - LOG_INFO(Loader, "Game id: {} Title: {}", id, title); - fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); - app_version = param_sfo->GetString("APP_VER").value_or("Unknown version"); - LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); - } else if (entry.path().filename() == "pic1.png") { - auto* splash = Common::Singleton::Instance(); - if (splash->IsLoaded()) { - continue; - } - if (!splash->Open(entry.path())) { - LOG_ERROR(Loader, "Game splash: unable to open file"); - } + title = param_sfo->GetString("TITLE").value_or("Unknown title"); + LOG_INFO(Loader, "Game id: {} Title: {}", id, title); + fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); + app_version = param_sfo->GetString("APP_VER").value_or("Unknown version"); + LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); + if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) { + psf_attributes.raw = *raw_attributes; + } + } + + const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); + if (std::filesystem::exists(pic1_path)) { + auto* splash = Common::Singleton::Instance(); + if (!splash->IsLoaded()) { + if (!splash->Open(pic1_path)) { + LOG_ERROR(Loader, "Game splash: unable to open file"); } } } @@ -176,6 +169,7 @@ void Emulator::Run(const std::filesystem::path& file) { game_info.app_ver = app_version; game_info.firmware_ver = fw_version & 0xFFF00000; game_info.raw_firmware_ver = fw_version; + game_info.psf_attributes = psf_attributes; std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version); std::string window_title = ""; @@ -219,6 +213,7 @@ void Emulator::Run(const std::filesystem::path& file) { Libraries::InitHLELibs(&linker->GetHLESymbols()); // Load the module with the linker + const auto eboot_path = mnt->GetHostPath("/app0/" + file.filename().string()); linker->LoadModule(eboot_path); // check if we have system modules to load @@ -236,6 +231,8 @@ void Emulator::Run(const std::filesystem::path& file) { } // Load all prx from separate update's sce_module folder + std::filesystem::path game_patch_folder = game_folder; + game_patch_folder += "-UPDATE"; std::filesystem::path update_module_folder = game_patch_folder / "sce_module"; if (std::filesystem::is_directory(update_module_folder)) { for (const auto& entry : std::filesystem::directory_iterator(update_module_folder)) { diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 8ea9267fd..2f69410cd 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -3,6 +3,7 @@ #include "common/assert.h" #include "common/config.h" +#include "core/libraries/kernel/process.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/texture_cache/image_info.h" @@ -252,7 +253,7 @@ ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group, if (!props.is_tiled) { guest_size = pitch * size.height * 4; } else { - if (Config::isNeoMode()) { + if (Libraries::Kernel::sceKernelIsNeoMode()) { guest_size = pitch * ((size.height + 127) & (~127)) * 4; } else { guest_size = pitch * ((size.height + 63) & (~63)) * 4;