Merge remote-tracking branch 'upstream/main' into reduce-clamp-threshold

This commit is contained in:
Stephen Miller 2025-06-03 15:12:12 -05:00
commit a74b8edca3
17 changed files with 167 additions and 55 deletions

View File

@ -29,7 +29,7 @@ sudo dnf install clang git cmake libatomic alsa-lib-devel \
openssl-devel libevdev-devel libudev-devel libXext-devel \ openssl-devel libevdev-devel libudev-devel libXext-devel \
qt6-qtbase-devel qt6-qtbase-private-devel \ qt6-qtbase-devel qt6-qtbase-private-devel \
qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \ qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \
vulkan-devel vulkan-validation-layers libpng-devel vulkan-devel vulkan-validation-layers libpng-devel libuuid-devel
``` ```
#### Arch Linux #### Arch Linux

View File

@ -69,7 +69,7 @@ static bool vkGuestMarkers = false;
static bool rdocEnable = false; static bool rdocEnable = false;
static bool isFpsColor = true; static bool isFpsColor = true;
static bool isSeparateLogFilesEnabled = false; static bool isSeparateLogFilesEnabled = false;
static s16 cursorState = HideCursorState::Idle; static int cursorState = HideCursorState::Idle;
static int cursorHideTimeout = 5; // 5 seconds (default) static int cursorHideTimeout = 5; // 5 seconds (default)
static double trophyNotificationDuration = 6.0; static double trophyNotificationDuration = 6.0;
static bool useUnifiedInputConfig = true; static bool useUnifiedInputConfig = true;
@ -78,6 +78,7 @@ static int controllerCustomColorRGB[3] = {0, 0, 255};
static bool compatibilityData = false; static bool compatibilityData = false;
static bool checkCompatibilityOnStartup = false; static bool checkCompatibilityOnStartup = false;
static std::string trophyKey; static std::string trophyKey;
static bool isPSNSignedIn = false;
// Gui // Gui
static bool load_game_size = true; static bool load_game_size = true;
@ -730,6 +731,14 @@ void setShowBackgroundImage(bool show) {
showBackgroundImage = show; showBackgroundImage = show;
} }
bool getPSNSignedIn() {
return isPSNSignedIn;
}
void setPSNSignedIn(bool sign) {
isPSNSignedIn = sign;
}
void load(const std::filesystem::path& path) { void load(const std::filesystem::path& path) {
// If the configuration file does not exist, create it and return // If the configuration file does not exist, create it and return
std::error_code error; std::error_code error;
@ -754,6 +763,7 @@ void load(const std::filesystem::path& path) {
isNeo = toml::find_or<bool>(general, "isPS4Pro", false); isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
isDevKit = toml::find_or<bool>(general, "isDevKit", false); isDevKit = toml::find_or<bool>(general, "isDevKit", false);
isPSNSignedIn = toml::find_or<bool>(general, "isPSNSignedIn", false);
playBGM = toml::find_or<bool>(general, "playBGM", false); playBGM = toml::find_or<bool>(general, "playBGM", false);
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false); isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
trophyNotificationDuration = trophyNotificationDuration =
@ -953,6 +963,7 @@ void save(const std::filesystem::path& path) {
data["General"]["isPS4Pro"] = isNeo; data["General"]["isPS4Pro"] = isNeo;
data["General"]["isDevKit"] = isDevKit; data["General"]["isDevKit"] = isDevKit;
data["General"]["isPSNSignedIn"] = isPSNSignedIn;
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled; data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration; data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
data["General"]["playBGM"] = playBGM; data["General"]["playBGM"] = playBGM;
@ -1098,6 +1109,7 @@ void setDefaultValues() {
isHDRAllowed = false; isHDRAllowed = false;
isNeo = false; isNeo = false;
isDevKit = false; isDevKit = false;
isPSNSignedIn = false;
isFullscreen = false; isFullscreen = false;
isTrophyPopupDisabled = false; isTrophyPopupDisabled = false;
playBGM = false; playBGM = false;

View File

@ -14,7 +14,7 @@ struct GameInstallDir {
bool enabled; bool enabled;
}; };
enum HideCursorState : s16 { Never, Idle, Always }; enum HideCursorState : int { Never, Idle, Always };
void load(const std::filesystem::path& path); void load(const std::filesystem::path& path);
void save(const std::filesystem::path& path); void save(const std::filesystem::path& path);
@ -39,6 +39,7 @@ bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup(); bool getCheckCompatibilityOnStartup();
int getBackgroundImageOpacity(); int getBackgroundImageOpacity();
bool getShowBackgroundImage(); bool getShowBackgroundImage();
bool getPSNSignedIn();
std::string getLogFilter(); std::string getLogFilter();
std::string getLogType(); std::string getLogType();
@ -111,6 +112,7 @@ void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);
void setBackgroundImageOpacity(int opacity); void setBackgroundImageOpacity(int opacity);
void setShowBackgroundImage(bool show); void setShowBackgroundImage(bool show);
void setPSNSignedIn(bool sign);
void setCursorState(s16 cursorState); void setCursorState(s16 cursorState);
void setCursorHideTimeout(int newcursorHideTimeout); void setCursorHideTimeout(int newcursorHideTimeout);

View File

@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <string>
#include "common/scm_rev.h" #include "common/scm_rev.h"
namespace Common { namespace Common {
@ -15,5 +17,26 @@ constexpr char g_scm_remote_name[] = "@GIT_REMOTE_NAME@";
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@"; constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
constexpr char g_scm_date[] = "@BUILD_DATE@"; constexpr char g_scm_date[] = "@BUILD_DATE@";
const std::string GetRemoteNameFromLink() {
std::string remote_url(Common::g_scm_remote_url);
std::string remote_host;
try {
if (remote_url.starts_with("http")) {
if (*remote_url.rbegin() == '/') {
remote_url.pop_back();
}
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
} else if (remote_url.starts_with("git@")) {
auto after_comma_pos = remote_url.find(':') + 1, slash_pos = remote_url.find('/');
remote_host = remote_url.substr(after_comma_pos, slash_pos - after_comma_pos);
} else {
remote_host = "unknown";
}
} catch (...) {
remote_host = "unknown";
}
return remote_host;
}
} // namespace } // namespace

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <string>
namespace Common { namespace Common {
extern const char g_version[]; extern const char g_version[];
@ -15,4 +17,6 @@ extern const char g_scm_remote_name[];
extern const char g_scm_remote_url[]; extern const char g_scm_remote_url[];
extern const char g_scm_date[]; extern const char g_scm_date[];
const std::string GetRemoteNameFromLink();
} // namespace Common } // namespace Common

View File

@ -145,6 +145,8 @@ bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) {
if (event.event.ident == ident && event.event.filter == filter) { if (event.event.ident == ident && event.event.filter == filter) {
if (filter == SceKernelEvent::Filter::VideoOut) { if (filter == SceKernelEvent::Filter::VideoOut) {
event.TriggerDisplay(trigger_data); event.TriggerDisplay(trigger_data);
} else if (filter == SceKernelEvent::Filter::User) {
event.TriggerUser(trigger_data);
} else { } else {
event.Trigger(trigger_data); event.Trigger(trigger_data);
} }

View File

@ -98,6 +98,12 @@ struct EqueueEvent {
event.data = reinterpret_cast<uintptr_t>(data); event.data = reinterpret_cast<uintptr_t>(data);
} }
void TriggerUser(void* data) {
is_triggered = true;
event.fflags++;
event.udata = data;
}
void TriggerDisplay(void* data) { void TriggerDisplay(void* data) {
is_triggered = true; is_triggered = true;
if (data != nullptr) { if (data != nullptr) {

View File

@ -264,6 +264,8 @@ int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void**
} }
s32 PS4_SYSV_ABI sceKernelMprotect(const void* addr, u64 size, s32 prot) { s32 PS4_SYSV_ABI sceKernelMprotect(const void* addr, u64 size, s32 prot) {
LOG_INFO(Kernel_Vmm, "called addr = {}, size = {:#x}, prot = {:#x}", fmt::ptr(addr), size,
prot);
Core::MemoryManager* memory_manager = Core::Memory::Instance(); Core::MemoryManager* memory_manager = Core::Memory::Instance();
Core::MemoryProt protection_flags = static_cast<Core::MemoryProt>(prot); Core::MemoryProt protection_flags = static_cast<Core::MemoryProt>(prot);
return memory_manager->Protect(std::bit_cast<VAddr>(addr), size, protection_flags); return memory_manager->Protect(std::bit_cast<VAddr>(addr), size, protection_flags);
@ -279,6 +281,8 @@ s32 PS4_SYSV_ABI posix_mprotect(const void* addr, u64 size, s32 prot) {
} }
s32 PS4_SYSV_ABI sceKernelMtypeprotect(const void* addr, u64 size, s32 mtype, s32 prot) { s32 PS4_SYSV_ABI sceKernelMtypeprotect(const void* addr, u64 size, s32 mtype, s32 prot) {
LOG_INFO(Kernel_Vmm, "called addr = {}, size = {:#x}, prot = {:#x}", fmt::ptr(addr), size,
prot);
Core::MemoryManager* memory_manager = Core::Memory::Instance(); Core::MemoryManager* memory_manager = Core::Memory::Instance();
Core::MemoryProt protection_flags = static_cast<Core::MemoryProt>(prot); Core::MemoryProt protection_flags = static_cast<Core::MemoryProt>(prot);
return memory_manager->Protect(std::bit_cast<VAddr>(addr), size, protection_flags); return memory_manager->Protect(std::bit_cast<VAddr>(addr), size, protection_flags);

View File

@ -576,8 +576,19 @@ int PS4_SYSV_ABI posix_pthread_getaffinity_np(PthreadT thread, size_t cpusetsize
if (thread == nullptr || cpusetp == nullptr) { if (thread == nullptr || cpusetp == nullptr) {
return POSIX_EINVAL; return POSIX_EINVAL;
} }
auto* thread_state = ThrState::Instance();
if (thread == g_curthread) {
g_curthread->lock.lock();
} else if (auto ret = thread_state->FindThread(thread, /*include dead*/ 0); ret != 0) {
return ret;
}
auto* attr_ptr = &thread->attr; auto* attr_ptr = &thread->attr;
return posix_pthread_attr_getaffinity_np(&attr_ptr, cpusetsize, cpusetp); auto ret = posix_pthread_attr_getaffinity_np(&attr_ptr, cpusetsize, cpusetp);
thread->lock.unlock();
return ret;
} }
int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize, int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize,
@ -585,11 +596,23 @@ int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize
if (thread == nullptr || cpusetp == nullptr) { if (thread == nullptr || cpusetp == nullptr) {
return POSIX_EINVAL; return POSIX_EINVAL;
} }
auto* attr_ptr = &thread->attr;
if (const auto ret = posix_pthread_attr_setaffinity_np(&attr_ptr, cpusetsize, cpusetp)) { auto* thread_state = ThrState::Instance();
if (thread == g_curthread) {
g_curthread->lock.lock();
} else if (auto ret = thread_state->FindThread(thread, /*include dead*/ 0); ret != 0) {
return ret; return ret;
} }
return thread->SetAffinity(thread->attr.cpuset);
auto* attr_ptr = &thread->attr;
auto ret = posix_pthread_attr_setaffinity_np(&attr_ptr, cpusetsize, cpusetp);
if (ret == ORBIS_OK) {
ret = thread->SetAffinity(thread->attr.cpuset);
}
thread->lock.unlock();
return ret;
} }
int PS4_SYSV_ABI scePthreadGetaffinity(PthreadT thread, u64* mask) { int PS4_SYSV_ABI scePthreadGetaffinity(PthreadT thread, u64* mask) {

View File

@ -306,6 +306,8 @@ void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym) {
posix_pthread_attr_getdetachstate); posix_pthread_attr_getdetachstate);
LIB_FUNCTION("JKyG3SWyA10", "libScePosix", 1, "libkernel", 1, 1, LIB_FUNCTION("JKyG3SWyA10", "libScePosix", 1, "libkernel", 1, 1,
posix_pthread_attr_setguardsize); posix_pthread_attr_setguardsize);
LIB_FUNCTION("qlk9pSLsUmM", "libScePosix", 1, "libkernel", 1, 1,
posix_pthread_attr_getschedparam);
// Orbis // Orbis
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1,

View File

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
@ -10,6 +11,8 @@
namespace Libraries::NpManager { namespace Libraries::NpManager {
#define SIGNEDIN_STATUS (Config::getPSNSignedIn() ? ORBIS_OK : ORBIS_NP_ERROR_SIGNED_OUT)
int PS4_SYSV_ABI Func_EF4378573542A508() { int PS4_SYSV_ABI Func_EF4378573542A508() {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_ERROR(Lib_NpManager, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
@ -921,9 +924,16 @@ int PS4_SYSV_ABI sceNpGetAccountCountry() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetAccountCountryA() { int PS4_SYSV_ABI sceNpGetAccountCountryA(OrbisUserServiceUserId user_id,
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); OrbisNpCountryCode* country_code) {
return ORBIS_OK; LOG_INFO(Lib_NpManager, "(STUBBED) called, user_id = {}", user_id);
if (country_code == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
::memset(country_code, 0, sizeof(OrbisNpCountryCode));
// TODO: get NP country code from config
::memcpy(country_code->country_code, "us", 2);
return SIGNEDIN_STATUS;
} }
int PS4_SYSV_ABI sceNpGetAccountDateOfBirth() { int PS4_SYSV_ABI sceNpGetAccountDateOfBirth() {
@ -941,8 +951,8 @@ int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id)
if (online_id == nullptr || account_id == nullptr) { if (online_id == nullptr || account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT;
} }
*account_id = 0; *account_id = 0xFEEDFACE;
return ORBIS_NP_ERROR_SIGNED_OUT; return SIGNEDIN_STATUS;
} }
int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id) { int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id) {
@ -950,8 +960,8 @@ int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account
if (account_id == nullptr) { if (account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT;
} }
*account_id = 0; *account_id = 0xFEEDFACE;
return ORBIS_NP_ERROR_SIGNED_OUT; return SIGNEDIN_STATUS;
} }
int PS4_SYSV_ABI sceNpGetAccountLanguage() { int PS4_SYSV_ABI sceNpGetAccountLanguage() {
@ -984,7 +994,9 @@ int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id)
if (np_id == nullptr) { if (np_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT;
} }
return ORBIS_NP_ERROR_SIGNED_OUT; memset(np_id, 0, sizeof(OrbisNpId));
strncpy(np_id->handle.data, Config::getUserName().c_str(), sizeof(np_id->handle.data));
return SIGNEDIN_STATUS;
} }
int PS4_SYSV_ABI sceNpGetNpReachabilityState() { int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
@ -997,7 +1009,9 @@ int PS4_SYSV_ABI sceNpGetOnlineId(OrbisUserServiceUserId user_id, OrbisNpOnlineI
if (online_id == nullptr) { if (online_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT;
} }
return ORBIS_NP_ERROR_SIGNED_OUT; memset(online_id, 0, sizeof(OrbisNpOnlineId));
strncpy(online_id->data, Config::getUserName().c_str(), sizeof(online_id->data));
return SIGNEDIN_STATUS;
} }
int PS4_SYSV_ABI sceNpGetParentalControlInfo() { int PS4_SYSV_ABI sceNpGetParentalControlInfo() {
@ -1014,8 +1028,8 @@ int PS4_SYSV_ABI sceNpGetState(OrbisUserServiceUserId user_id, OrbisNpState* sta
if (state == nullptr) { if (state == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT;
} }
*state = OrbisNpState::SignedOut; *state = Config::getPSNSignedIn() ? OrbisNpState::SignedIn : OrbisNpState::SignedOut;
LOG_DEBUG(Lib_NpManager, "Signed out"); LOG_DEBUG(Lib_NpManager, "Signed {}", Config::getPSNSignedIn() ? "in" : "out");
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -32,6 +32,12 @@ struct OrbisNpId {
u8 reserved[8]; u8 reserved[8];
}; };
struct OrbisNpCountryCode {
char country_code[2];
char end;
char pad;
};
int PS4_SYSV_ABI Func_EF4378573542A508(); int PS4_SYSV_ABI Func_EF4378573542A508();
int PS4_SYSV_ABI _sceNpIpcCreateMemoryFromKernel(); int PS4_SYSV_ABI _sceNpIpcCreateMemoryFromKernel();
int PS4_SYSV_ABI _sceNpIpcCreateMemoryFromPool(); int PS4_SYSV_ABI _sceNpIpcCreateMemoryFromPool();
@ -215,7 +221,8 @@ int PS4_SYSV_ABI sceNpCreateRequest();
int PS4_SYSV_ABI sceNpDeleteRequest(int reqId); int PS4_SYSV_ABI sceNpDeleteRequest(int reqId);
int PS4_SYSV_ABI sceNpGetAccountAge(); int PS4_SYSV_ABI sceNpGetAccountAge();
int PS4_SYSV_ABI sceNpGetAccountCountry(); int PS4_SYSV_ABI sceNpGetAccountCountry();
int PS4_SYSV_ABI sceNpGetAccountCountryA(); int PS4_SYSV_ABI sceNpGetAccountCountryA(OrbisUserServiceUserId user_id,
OrbisNpCountryCode* country_code);
int PS4_SYSV_ABI sceNpGetAccountDateOfBirth(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirth();
int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA();
int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id); int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id);

View File

@ -117,6 +117,18 @@ void Linker::Execute(const std::vector<std::string> args) {
Common::SetCurrentThreadName("GAME_MainThread"); Common::SetCurrentThreadName("GAME_MainThread");
LoadSharedLibraries(); LoadSharedLibraries();
// Simulate libSceGnmDriver initialization, which maps a chunk of direct memory.
// Some games fail without accurately emulating this behavior.
s64 phys_addr{};
s32 result = Libraries::Kernel::sceKernelAllocateDirectMemory(
0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr);
if (result == 0) {
void* addr{reinterpret_cast<void*>(0xfe0000000)};
result = Libraries::Kernel::sceKernelMapNamedDirectMemory(
&addr, 0x10000, 0x13, 0, phys_addr, 0x10000, "SceGnmDriver");
}
ASSERT_MSG(result == 0, "Unable to emulate libSceGnmDriver initialization");
// Start main module. // Start main module.
EntryParams params{}; EntryParams params{};
params.argc = 1; params.argc = 1;

View File

@ -557,18 +557,6 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t s
return adjusted_size; return adjusted_size;
} }
// Validate protection flags
constexpr static MemoryProt valid_flags = MemoryProt::NoAccess | MemoryProt::CpuRead |
MemoryProt::CpuReadWrite | MemoryProt::GpuRead |
MemoryProt::GpuWrite | MemoryProt::GpuReadWrite;
MemoryProt invalid_flags = prot & ~valid_flags;
if (u32(invalid_flags) != 0 && u32(invalid_flags) != u32(MemoryProt::NoAccess)) {
LOG_ERROR(Kernel_Vmm, "Invalid protection flags: prot = {:#x}, invalid flags = {:#x}",
u32(prot), u32(invalid_flags));
return ORBIS_KERNEL_ERROR_EINVAL;
}
// Change protection // Change protection
vma_base.prot = prot; vma_base.prot = prot;
@ -598,11 +586,25 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t s
s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) { s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
std::scoped_lock lk{mutex}; std::scoped_lock lk{mutex};
s64 protected_bytes = 0;
// Validate protection flags
constexpr static MemoryProt valid_flags = MemoryProt::NoAccess | MemoryProt::CpuRead |
MemoryProt::CpuReadWrite | MemoryProt::GpuRead |
MemoryProt::GpuWrite | MemoryProt::GpuReadWrite;
MemoryProt invalid_flags = prot & ~valid_flags;
if (invalid_flags != MemoryProt::NoAccess) {
LOG_ERROR(Kernel_Vmm, "Invalid protection flags");
return ORBIS_KERNEL_ERROR_EINVAL;
}
// Align addr and size to the nearest page boundary.
auto aligned_addr = Common::AlignDown(addr, 16_KB); auto aligned_addr = Common::AlignDown(addr, 16_KB);
auto aligned_size = Common::AlignUp(size + addr - aligned_addr, 16_KB); auto aligned_size = Common::AlignUp(size + addr - aligned_addr, 16_KB);
do {
// Protect all VMAs between aligned_addr and aligned_addr + aligned_size.
s64 protected_bytes = 0;
while (protected_bytes < aligned_size) {
auto it = FindVMA(aligned_addr + protected_bytes); auto it = FindVMA(aligned_addr + protected_bytes);
auto& vma_base = it->second; auto& vma_base = it->second;
ASSERT_MSG(vma_base.Contains(addr + protected_bytes, 0), "Address {:#x} is out of bounds", ASSERT_MSG(vma_base.Contains(addr + protected_bytes, 0), "Address {:#x} is out of bounds",
@ -615,7 +617,7 @@ s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
return result; return result;
} }
protected_bytes += result; protected_bytes += result;
} while (protected_bytes < aligned_size); }
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <filesystem>
#include <set> #include <set>
#include <fmt/core.h> #include <fmt/core.h>
@ -62,8 +63,13 @@ Emulator::~Emulator() {
Config::saveMainWindow(config_dir / "config.toml"); Config::saveMainWindow(config_dir / "config.toml");
} }
void Emulator::Run(const std::filesystem::path& file, const std::vector<std::string> args) { void Emulator::Run(std::filesystem::path file, const std::vector<std::string> args) {
if (std::filesystem::is_directory(file)) {
file /= "eboot.bin";
}
const auto eboot_name = file.filename().string(); const auto eboot_name = file.filename().string();
auto game_folder = file.parent_path(); auto game_folder = file.parent_path();
if (const auto game_folder_name = game_folder.filename().string(); if (const auto game_folder_name = game_folder.filename().string();
game_folder_name.ends_with("-UPDATE") || game_folder_name.ends_with("-patch")) { game_folder_name.ends_with("-UPDATE") || game_folder_name.ends_with("-patch")) {
@ -114,6 +120,11 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
Common::Log::Initialize(); Common::Log::Initialize();
} }
Common::Log::Start(); Common::Log::Start();
if (!std::filesystem::exists(file)) {
LOG_CRITICAL(Loader, "eboot.bin does not exist: {}",
std::filesystem::absolute(file).string());
std::quick_exit(0);
}
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::g_version); LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::g_version);
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev); LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
@ -194,15 +205,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version); std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version);
std::string window_title = ""; std::string window_title = "";
std::string remote_url(Common::g_scm_remote_url); std::string remote_url(Common::g_scm_remote_url);
std::string remote_host; std::string remote_host = Common::GetRemoteNameFromLink();
try {
if (*remote_url.rbegin() == '/') {
remote_url.pop_back();
}
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
} catch (...) {
remote_host = "unknown";
}
if (Common::g_is_release) { if (Common::g_is_release) {
if (remote_host == "shadps4-emu" || remote_url.length() == 0) { if (remote_host == "shadps4-emu" || remote_url.length() == 0) {
window_title = fmt::format("shadPS4 v{} | {}", Common::g_version, game_title); window_title = fmt::format("shadPS4 v{} | {}", Common::g_version, game_title);
@ -258,7 +261,11 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
// Load the module with the linker // Load the module with the linker
const auto eboot_path = mnt->GetHostPath("/app0/" + eboot_name); const auto eboot_path = mnt->GetHostPath("/app0/" + eboot_name);
linker->LoadModule(eboot_path); if (linker->LoadModule(eboot_path) == -1) {
LOG_CRITICAL(Loader, "Failed to load game's eboot.bin: {}",
std::filesystem::absolute(eboot_path).string());
std::quick_exit(0);
}
// check if we have system modules to load // check if we have system modules to load
LoadSystemModules(game_info.game_serial); LoadSystemModules(game_info.game_serial);

View File

@ -25,7 +25,7 @@ public:
Emulator(); Emulator();
~Emulator(); ~Emulator();
void Run(const std::filesystem::path& file, const std::vector<std::string> args = {}); void Run(std::filesystem::path file, const std::vector<std::string> args = {});
void UpdatePlayTime(const std::string& serial); void UpdatePlayTime(const std::string& serial);
private: private:

View File

@ -56,15 +56,7 @@ bool MainWindow::Init() {
setMinimumSize(720, 405); setMinimumSize(720, 405);
std::string window_title = ""; std::string window_title = "";
std::string remote_url(Common::g_scm_remote_url); std::string remote_url(Common::g_scm_remote_url);
std::string remote_host; std::string remote_host = Common::GetRemoteNameFromLink();
try {
if (*remote_url.rbegin() == '/') {
remote_url.pop_back();
}
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
} catch (...) {
remote_host = "unknown";
}
if (Common::g_is_release) { if (Common::g_is_release) {
if (remote_host == "shadps4-emu" || remote_url.length() == 0) { if (remote_host == "shadps4-emu" || remote_url.length() == 0) {
window_title = fmt::format("shadPS4 v{}", Common::g_version); window_title = fmt::format("shadPS4 v{}", Common::g_version);