From 95ba5918dd62e7337632f9243b7dcd1396c81fc5 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 16 Apr 2026 20:55:55 +0300 Subject: [PATCH] Shadnet preparations (#4269) * replace psn_signed_in settings with shad_net_enabled and added shadnet_server setting * improved user manager to update new fields and add new variables * clang * better message :D --- src/core/emulator_settings.cpp | 1 - src/core/emulator_settings.h | 12 +++-- src/core/libraries/np/np_auth.cpp | 12 ++--- src/core/libraries/np/np_manager.cpp | 52 +++++++++---------- src/core/libraries/np/np_matching2.cpp | 2 +- src/core/libraries/np/np_web_api2.cpp | 4 +- src/core/libraries/np/np_web_api_internal.cpp | 6 +-- src/core/user_manager.cpp | 20 +++++++ src/core/user_manager.h | 13 +++-- src/core/user_settings.cpp | 43 +++++++++------ src/core/user_settings.h | 2 +- src/emulator.cpp | 2 +- src/imgui/settings_dialog_imgui.cpp | 8 +-- 13 files changed, 107 insertions(+), 70 deletions(-) diff --git a/src/core/emulator_settings.cpp b/src/core/emulator_settings.cpp index e7934696e..5388995d9 100644 --- a/src/core/emulator_settings.cpp +++ b/src/core/emulator_settings.cpp @@ -499,7 +499,6 @@ bool EmulatorSettingsImpl::TransferSettings() { setFromToml(s.volume_slider, general, "volumeSlider"); setFromToml(s.neo_mode, general, "isPS4Pro"); setFromToml(s.dev_kit_mode, general, "isDevKit"); - setFromToml(s.psn_signed_in, general, "isPSNSignedIn"); setFromToml(s.trophy_popup_disabled, general, "isTrophyPopupDisabled"); setFromToml(s.trophy_notification_duration, general, "trophyNotificationDuration"); setFromToml(s.discord_rpc_enabled, general, "enableDiscordRPC"); diff --git a/src/core/emulator_settings.h b/src/core/emulator_settings.h index 211f2e478..e5ee81a32 100644 --- a/src/core/emulator_settings.h +++ b/src/core/emulator_settings.h @@ -179,7 +179,7 @@ struct GeneralSettings { Setting neo_mode{false}; Setting dev_kit_mode{false}; Setting extra_dmem_in_mbytes{0}; - Setting psn_signed_in{false}; + Setting shad_net_enabled{false}; Setting trophy_popup_disabled{false}; Setting trophy_notification_duration{6.0}; Setting trophy_notification_side{"right"}; @@ -192,6 +192,7 @@ struct GeneralSettings { Setting show_fps_counter{false}; Setting console_language{1}; Setting big_picture_scale{1000}; + Setting shadnet_server{""}; // return a vector of override descriptors (runtime, but tiny) std::vector GetOverrideableFields() const { @@ -201,7 +202,7 @@ struct GeneralSettings { make_override("dev_kit_mode", &GeneralSettings::dev_kit_mode), make_override("extra_dmem_in_mbytes", &GeneralSettings::extra_dmem_in_mbytes), - make_override("psn_signed_in", &GeneralSettings::psn_signed_in), + make_override("shad_net_enabled", &GeneralSettings::shad_net_enabled), make_override("trophy_popup_disabled", &GeneralSettings::trophy_popup_disabled), make_override("trophy_notification_duration", @@ -219,11 +220,11 @@ struct GeneralSettings { }; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(GeneralSettings, install_dirs, addon_install_dir, home_dir, sys_modules_dir, font_dir, volume_slider, neo_mode, dev_kit_mode, - extra_dmem_in_mbytes, psn_signed_in, trophy_popup_disabled, + extra_dmem_in_mbytes, shad_net_enabled, trophy_popup_disabled, trophy_notification_duration, log_filter, log_type, show_splash, identical_log_grouped, trophy_notification_side, connected_to_network, discord_rpc_enabled, show_fps_counter, - console_language, big_picture_scale) + console_language, big_picture_scale, shadnet_server) // ------------------------------- // Debug settings @@ -550,7 +551,7 @@ public: SETTING_FORWARD_BOOL(m_general, Neo, neo_mode) SETTING_FORWARD_BOOL(m_general, DevKit, dev_kit_mode) SETTING_FORWARD(m_general, ExtraDmemInMBytes, extra_dmem_in_mbytes) - SETTING_FORWARD_BOOL(m_general, PSNSignedIn, psn_signed_in) + SETTING_FORWARD_BOOL(m_general, ShadNetEnabled, shad_net_enabled) SETTING_FORWARD_BOOL(m_general, TrophyPopupDisabled, trophy_popup_disabled) SETTING_FORWARD(m_general, TrophyNotificationDuration, trophy_notification_duration) SETTING_FORWARD(m_general, TrophyNotificationSide, trophy_notification_side) @@ -563,6 +564,7 @@ public: SETTING_FORWARD_BOOL(m_general, ShowFpsCounter, show_fps_counter) SETTING_FORWARD(m_general, ConsoleLanguage, console_language) SETTING_FORWARD(m_general, BigPictureScale, big_picture_scale) + SETTING_FORWARD(m_general, ShadNetServer, shadnet_server) // Audio settings SETTING_FORWARD(m_audio, AudioBackend, audio_backend) diff --git a/src/core/libraries/np/np_auth.cpp b/src/core/libraries/np/np_auth.cpp index a9c2181b9..fa6752488 100644 --- a/src/core/libraries/np/np_auth.cpp +++ b/src/core/libraries/np/np_auth.cpp @@ -13,7 +13,7 @@ namespace Libraries::Np::NpAuth { -static bool g_signed_in = false; +static bool g_shadnet_enabled = false; static s32 g_active_auth_requests = 0; static std::mutex g_auth_request_mutex; @@ -110,7 +110,7 @@ s32 GetAuthorizationCode(s32 req_id, const OrbisNpAuthGetAuthorizationCodeParame } request.state = NpAuthRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -141,7 +141,7 @@ sceNpAuthGetAuthorizationCode(s32 req_id, const OrbisNpAuthGetAuthorizationCodeP if (param->online_id == nullptr || param->client_id == nullptr || param->scope == nullptr) { return ORBIS_NP_AUTH_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { // Calls sceNpManagerIntGetUserIdByOnlineId to get a user id, returning any errors. // This call will not succeed while signed out because games cannot retrieve an online id. return ORBIS_NP_ERROR_USER_NOT_FOUND; @@ -207,7 +207,7 @@ s32 GetIdToken(s32 req_id, const OrbisNpAuthGetIdTokenParameterA* param, s32 fla } request.state = NpAuthRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -235,7 +235,7 @@ s32 PS4_SYSV_ABI sceNpAuthGetIdToken(s32 req_id, const OrbisNpAuthGetIdTokenPara param->client_secret == nullptr || param->scope == nullptr) { return ORBIS_NP_AUTH_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { // Calls sceNpManagerIntGetUserIdByOnlineId to get a user id, returning any errors. // This call will not succeed while signed out because games cannot retrieve an online id. return ORBIS_NP_ERROR_USER_NOT_FOUND; @@ -363,7 +363,7 @@ s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 req_id) { } void RegisterLib(Core::Loader::SymbolsResolver* sym) { - g_signed_in = EmulatorSettings.IsPSNSignedIn(); + g_shadnet_enabled = EmulatorSettings.IsShadNetEnabled(); LIB_FUNCTION("6bwFkosYRQg", "libSceNpAuth", 1, "libSceNpAuth", sceNpAuthCreateRequest); LIB_FUNCTION("N+mr7GjTvr8", "libSceNpAuth", 1, "libSceNpAuth", sceNpAuthCreateAsyncRequest); diff --git a/src/core/libraries/np/np_manager.cpp b/src/core/libraries/np/np_manager.cpp index 0ffbb682a..b6851cbdb 100644 --- a/src/core/libraries/np/np_manager.cpp +++ b/src/core/libraries/np/np_manager.cpp @@ -16,7 +16,7 @@ namespace Libraries::Np::NpManager { -static bool g_signed_in = false; +static bool g_shadnet_enabled = false; static s32 g_active_requests = 0; static std::mutex g_request_mutex; @@ -110,7 +110,7 @@ s32 PS4_SYSV_ABI sceNpCheckNpAvailability(s32 req_id, OrbisNpOnlineId* online_id } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -146,7 +146,7 @@ s32 PS4_SYSV_ABI sceNpCheckNpAvailabilityA(s32 req_id, } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -182,7 +182,7 @@ s32 PS4_SYSV_ABI sceNpCheckNpReachability(s32 req_id, } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -233,7 +233,7 @@ s32 PS4_SYSV_ABI sceNpCheckPlus(s32 req_id, const OrbisNpCheckPlusParameter* par } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -277,7 +277,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountLanguage(s32 req_id, OrbisNpOnlineId* online_id, } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -320,7 +320,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountLanguageA(s32 req_id, } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -362,7 +362,7 @@ s32 PS4_SYSV_ABI sceNpGetParentalControlInfo(s32 req_id, OrbisNpOnlineId* online } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -407,7 +407,7 @@ sceNpGetParentalControlInfoA(s32 req_id, Libraries::UserService::OrbisUserServic } request.state = NpRequestState::Complete; - if (!g_signed_in) { + if (!g_shadnet_enabled) { request.result = ORBIS_NP_ERROR_SIGNED_OUT; // If the request is processed in some form, and it's an async request, then it returns OK. if (request.async) { @@ -518,7 +518,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountCountry(OrbisNpOnlineId* online_id, if (online_id == nullptr || country_code == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } std::memset(country_code, 0, sizeof(OrbisNpCountryCode)); @@ -532,7 +532,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountCountryA(Libraries::UserService::OrbisUserServic if (country_code == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } std::memset(country_code, 0, sizeof(OrbisNpCountryCode)); @@ -546,7 +546,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountDateOfBirth(OrbisNpOnlineId* online_id, if (online_id == nullptr || date_of_birth == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } @@ -562,7 +562,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountDateOfBirthA(Libraries::UserService::OrbisUserSe if (date_of_birth == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } @@ -580,7 +580,7 @@ s32 PS4_SYSV_ABI sceNpGetGamePresenceStatus(OrbisNpOnlineId* online_id, } *game_status = - g_signed_in ? OrbisNpGamePresenseStatus::Online : OrbisNpGamePresenseStatus::Offline; + g_shadnet_enabled ? OrbisNpGamePresenseStatus::Online : OrbisNpGamePresenseStatus::Offline; return ORBIS_OK; } @@ -591,7 +591,7 @@ s32 PS4_SYSV_ABI sceNpGetGamePresenceStatusA(Libraries::UserService::OrbisUserSe } *game_status = - g_signed_in ? OrbisNpGamePresenseStatus::Online : OrbisNpGamePresenseStatus::Offline; + g_shadnet_enabled ? OrbisNpGamePresenseStatus::Online : OrbisNpGamePresenseStatus::Offline; return ORBIS_OK; } @@ -600,7 +600,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id) if (online_id == nullptr || account_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { *account_id = 0; return ORBIS_NP_ERROR_SIGNED_OUT; } @@ -614,7 +614,7 @@ s32 PS4_SYSV_ABI sceNpGetAccountIdA(Libraries::UserService::OrbisUserServiceUser if (account_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { *account_id = 0; return ORBIS_NP_ERROR_SIGNED_OUT; } @@ -628,7 +628,7 @@ s32 PS4_SYSV_ABI sceNpGetNpId(Libraries::UserService::OrbisUserServiceUserId use if (np_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } memset(np_id, 0, sizeof(OrbisNpId)); @@ -643,7 +643,7 @@ s32 PS4_SYSV_ABI sceNpGetOnlineId(Libraries::UserService::OrbisUserServiceUserId if (online_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } memset(online_id, 0, sizeof(OrbisNpOnlineId)); @@ -658,8 +658,8 @@ s32 PS4_SYSV_ABI sceNpGetNpReachabilityState(Libraries::UserService::OrbisUserSe return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - *state = - g_signed_in ? OrbisNpReachabilityState::Reachable : OrbisNpReachabilityState::Unavailable; + *state = g_shadnet_enabled ? OrbisNpReachabilityState::Reachable + : OrbisNpReachabilityState::Unavailable; return ORBIS_OK; } @@ -668,8 +668,8 @@ s32 PS4_SYSV_ABI sceNpGetState(Libraries::UserService::OrbisUserServiceUserId us if (state == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - *state = g_signed_in ? OrbisNpState::SignedIn : OrbisNpState::SignedOut; - LOG_DEBUG(Lib_NpManager, "Signed {}", g_signed_in ? "in" : "out"); + *state = g_shadnet_enabled ? OrbisNpState::SignedIn : OrbisNpState::SignedOut; + LOG_DEBUG(Lib_NpManager, "Signed {}", g_shadnet_enabled ? "in" : "out"); return ORBIS_OK; } @@ -678,7 +678,7 @@ sceNpGetUserIdByAccountId(u64 account_id, Libraries::UserService::OrbisUserServi if (user_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - if (!g_signed_in) { + if (!g_shadnet_enabled) { return ORBIS_NP_ERROR_SIGNED_OUT; } *user_id = 1; @@ -692,7 +692,7 @@ s32 PS4_SYSV_ABI sceNpHasSignedUp(Libraries::UserService::OrbisUserServiceUserId if (has_signed_up == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } - *has_signed_up = g_signed_in ? true : false; + *has_signed_up = g_shadnet_enabled ? true : false; return ORBIS_OK; } @@ -787,7 +787,7 @@ void DeregisterNpCallback(std::string key) { } void RegisterLib(Core::Loader::SymbolsResolver* sym) { - g_signed_in = EmulatorSettings.IsPSNSignedIn(); + g_shadnet_enabled = EmulatorSettings.IsShadNetEnabled(); LIB_FUNCTION("GpLQDNKICac", "libSceNpManager", 1, "libSceNpManager", sceNpCreateRequest); LIB_FUNCTION("eiqMCt9UshI", "libSceNpManager", 1, "libSceNpManager", sceNpCreateAsyncRequest); diff --git a/src/core/libraries/np/np_matching2.cpp b/src/core/libraries/np/np_matching2.cpp index dcd2a9c23..199f1acfc 100644 --- a/src/core/libraries/np/np_matching2.cpp +++ b/src/core/libraries/np/np_matching2.cpp @@ -376,7 +376,7 @@ int PS4_SYSV_ABI sceNpMatching2ContextStart(OrbisNpMatching2ContextId ctxId, u64 } std::scoped_lock lk{g_events_mutex}; - if (EmulatorSettings.IsConnectedToNetwork() && EmulatorSettings.IsPSNSignedIn()) { + if (EmulatorSettings.IsConnectedToNetwork() && EmulatorSettings.IsShadNetEnabled()) { g_ctx_events.emplace_back(ctxId, ORBIS_NP_MATCHING2_CONTEXT_EVENT_STARTED, ORBIS_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0); } else { diff --git a/src/core/libraries/np/np_web_api2.cpp b/src/core/libraries/np/np_web_api2.cpp index a7c7ee3f3..855251097 100644 --- a/src/core/libraries/np/np_web_api2.cpp +++ b/src/core/libraries/np/np_web_api2.cpp @@ -207,8 +207,8 @@ s32 PS4_SYSV_ABI sceNpWebApi2SendMultipartRequest() { } s32 PS4_SYSV_ABI sceNpWebApi2SendRequest() { - if (!EmulatorSettings.IsPSNSignedIn()) { - LOG_INFO(Lib_NpWebApi2, "called, returning PSN signed out."); + if (!EmulatorSettings.IsShadNetEnabled()) { + LOG_INFO(Lib_NpWebApi2, "called, returning shadNet signed out."); return ORBIS_NP_WEBAPI2_ERROR_NOT_SIGNED_IN; } LOG_ERROR(Lib_NpWebApi2, "(STUBBED) called"); diff --git a/src/core/libraries/np/np_web_api_internal.cpp b/src/core/libraries/np/np_web_api_internal.cpp index 66a09b493..eb80d137f 100644 --- a/src/core/libraries/np/np_web_api_internal.cpp +++ b/src/core/libraries/np/np_web_api_internal.cpp @@ -606,7 +606,7 @@ s32 sendRequest(s64 requestId, s32 partIndex, const void* pData, u64 dataSize, s unlockContext(context); // Stubbing sceNpManagerIntGetSigninState call with a config check. - if (!EmulatorSettings.IsPSNSignedIn()) { + if (!EmulatorSettings.IsShadNetEnabled()) { releaseRequest(request); releaseUserContext(user_context); releaseContext(context); @@ -1025,7 +1025,7 @@ s32 createServicePushEventFilterInternal( auto& handle = context->handles[handleId]; handle->userCount++; - if (pNpServiceName != nullptr && !EmulatorSettings.IsPSNSignedIn()) { + if (pNpServiceName != nullptr && !EmulatorSettings.IsShadNetEnabled()) { // Seems sceNpManagerIntGetUserList fails? LOG_DEBUG(Lib_NpWebApi, "Cannot create service push event while PSN is disabled"); handle->userCount--; @@ -1202,7 +1202,7 @@ s32 createExtendedPushEventFilterInternal( auto& handle = context->handles[handleId]; handle->userCount++; - if (pNpServiceName != nullptr && !EmulatorSettings.IsPSNSignedIn()) { + if (pNpServiceName != nullptr && !EmulatorSettings.IsShadNetEnabled()) { // Seems sceNpManagerIntGetUserList fails? LOG_DEBUG(Lib_NpWebApi, "Cannot create extended push event while PSN is disabled"); handle->userCount--; diff --git a/src/core/user_manager.cpp b/src/core/user_manager.cpp index 73e881e8e..d952d3d52 100644 --- a/src/core/user_manager.cpp +++ b/src/core/user_manager.cpp @@ -93,24 +93,44 @@ Users UserManager::CreateDefaultUsers() { .user_name = "shadPS4", .user_color = 1, .player_index = 1, + .shadnet_npid = "", + .shadnet_password = "", + .shadnet_token = "", + .shadnet_email = "", + .shadnet_enabled = false, }, { .user_id = 1001, .user_name = "shadPS4-2", .user_color = 2, .player_index = 2, + .shadnet_npid = "", + .shadnet_password = "", + .shadnet_token = "", + .shadnet_email = "", + .shadnet_enabled = false, }, { .user_id = 1002, .user_name = "shadPS4-3", .user_color = 3, .player_index = 3, + .shadnet_npid = "", + .shadnet_password = "", + .shadnet_token = "", + .shadnet_email = "", + .shadnet_enabled = false, }, { .user_id = 1003, .user_name = "shadPS4-4", .user_color = 4, .player_index = 4, + .shadnet_npid = "", + .shadnet_password = "", + .shadnet_token = "", + .shadnet_email = "", + .shadnet_enabled = false, }, }; diff --git a/src/core/user_manager.h b/src/core/user_manager.h index 9273ef0cb..bf79c8573 100644 --- a/src/core/user_manager.h +++ b/src/core/user_manager.h @@ -13,16 +13,23 @@ struct User { std::string user_name = ""; u32 user_color; int player_index = 0; // 1-4 - bool logged_in = false; + // ShadNet settings + std::string shadnet_npid = ""; // account identifier + std::string shadnet_password = ""; // account password + std::string shadnet_token = ""; // 2FA/validation token (future use) + std::string shadnet_email = ""; // email address (furute use) + bool shadnet_enabled = false; // enable shadnet for user }; struct Users { std::vector user{}; std::string commit_hash{}; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(User, user_id, user_color, user_name, player_index) -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Users, user, commit_hash) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(User, user_id, user_color, user_name, player_index, + shadnet_npid, shadnet_password, shadnet_token, + shadnet_email, shadnet_enabled) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Users, user, commit_hash) using LoggedInUsers = std::array; diff --git a/src/core/user_settings.cpp b/src/core/user_settings.cpp index cf569a68a..5b8d1c246 100644 --- a/src/core/user_settings.cpp +++ b/src/core/user_settings.cpp @@ -20,7 +20,8 @@ std::mutex UserSettingsImpl::s_mutex; UserSettingsImpl::UserSettingsImpl() = default; UserSettingsImpl::~UserSettingsImpl() { - Save(); + if (m_loaded) + Save(); } std::shared_ptr UserSettingsImpl::GetInstance() { @@ -42,12 +43,26 @@ bool UserSettingsImpl::Save() const { j["Users"] = m_userManager.GetUsers(); j["Users"]["commit_hash"] = std::string(Common::g_scm_rev); + json existing = json::object(); + if (std::ifstream existingIn{path}; existingIn.good()) { + try { + existingIn >> existing; + } catch (...) { + existing = json::object(); + } + } + + if (existing.contains("Users") && existing["Users"].is_object()) + existing["Users"].update(j["Users"]); + else + existing["Users"] = j["Users"]; + std::ofstream out(path); if (!out) { LOG_ERROR(Config, "Failed to open user settings for writing: {}", path.string()); return false; } - out << std::setw(2) << j; + out << std::setw(2) << existing; return !out.fail(); } catch (const std::exception& e) { LOG_ERROR(Config, "Error saving user settings: {}", e.what()); @@ -60,11 +75,10 @@ bool UserSettingsImpl::Load() { try { if (!std::filesystem::exists(path)) { LOG_DEBUG(Config, "User settings file not found: {}", path.string()); - // Create default user if no file exists - if (m_userManager.GetUsers().user.empty()) { + if (m_userManager.GetUsers().user.empty()) m_userManager.GetUsers() = m_userManager.CreateDefaultUsers(); - } - Save(); // Save default users + m_loaded = true; + Save(); return false; } @@ -77,14 +91,10 @@ bool UserSettingsImpl::Load() { json j; in >> j; - // Create a default Users object auto default_users = m_userManager.CreateDefaultUsers(); - - // Convert default_users to json for merging json default_json; default_json["Users"] = default_users; - // Merge the loaded json with defaults (preserves existing data, adds missing fields) if (j.contains("Users")) { json current = default_json["Users"]; current.update(j["Users"]); @@ -93,18 +103,17 @@ bool UserSettingsImpl::Load() { m_userManager.GetUsers() = default_users; } - if (m_userManager.GetUsers().commit_hash != Common::g_scm_rev) { - Save(); - } - LOG_DEBUG(Config, "User settings loaded successfully"); + + m_loaded = true; + if (m_userManager.GetUsers().commit_hash != Common::g_scm_rev) + Save(); + return true; } catch (const std::exception& e) { LOG_ERROR(Config, "Error loading user settings: {}", e.what()); - // Fall back to defaults - if (m_userManager.GetUsers().user.empty()) { + if (m_userManager.GetUsers().user.empty()) m_userManager.GetUsers() = m_userManager.CreateDefaultUsers(); - } return false; } } \ No newline at end of file diff --git a/src/core/user_settings.h b/src/core/user_settings.h index 45cfa91dd..cf9a6d2f8 100644 --- a/src/core/user_settings.h +++ b/src/core/user_settings.h @@ -40,7 +40,7 @@ public: private: UserManager m_userManager; - + bool m_loaded{false}; static std::shared_ptr s_instance; static std::mutex s_mutex; }; \ No newline at end of file diff --git a/src/emulator.cpp b/src/emulator.cpp index d9d0103e0..ac21c9759 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -271,7 +271,7 @@ void Emulator::Run(std::filesystem::path file, std::vector args, LOG_INFO(Config, "General isNeo: {}", EmulatorSettings.IsNeo()); LOG_INFO(Config, "General isDevKit: {}", EmulatorSettings.IsDevKit()); LOG_INFO(Config, "General isConnectedToNetwork: {}", EmulatorSettings.IsConnectedToNetwork()); - LOG_INFO(Config, "General isPsnSignedIn: {}", EmulatorSettings.IsPSNSignedIn()); + LOG_INFO(Config, "General isShadNetEnabled: {}", EmulatorSettings.IsShadNetEnabled()); LOG_INFO(Config, "GPU isNullGpu: {}", EmulatorSettings.IsNullGPU()); LOG_INFO(Config, "GPU readbacksMode: {}", EmulatorSettings.GetReadbacksMode()); LOG_INFO(Config, "GPU readbackLinearImages: {}", diff --git a/src/imgui/settings_dialog_imgui.cpp b/src/imgui/settings_dialog_imgui.cpp index 73aeb88f2..ed290f5d3 100644 --- a/src/imgui/settings_dialog_imgui.cpp +++ b/src/imgui/settings_dialog_imgui.cpp @@ -100,7 +100,7 @@ bool readbackLinearImagesSetting; bool directMemoryAccessSetting; bool devkitConsoleSetting; bool neoModeSetting; -bool psnSignedInSetting; +bool shadnetEnabledSetting; bool connectedNetworkSetting; bool pipelineCacheEnabledSetting; bool pipelineCacheArchiveSetting; @@ -389,7 +389,7 @@ void LoadCategory(SettingsCategory category) { AddSettingBool("Enable Direct Memory Access", directMemoryAccessSetting); AddSettingBool("Enable Devkit Console Mode", devkitConsoleSetting); AddSettingBool("Enable PS4 Neo Mode", neoModeSetting); - AddSettingBool("Set PSN Sign-in to True", psnSignedInSetting); + AddSettingBool("Enable ShadNet", shadnetEnabledSetting); AddSettingBool("Set Network Connected to True", connectedNetworkSetting); AddSettingBool("Enable Shader Cache", pipelineCacheEnabledSetting); @@ -460,7 +460,7 @@ void SaveSettings(std::string profile) { EmulatorSettings.SetDirectMemoryAccessEnabled(directMemoryAccessSetting, true); EmulatorSettings.SetDevKit(devkitConsoleSetting, true); EmulatorSettings.SetNeo(neoModeSetting, true); - EmulatorSettings.SetPSNSignedIn(psnSignedInSetting, true); + EmulatorSettings.SetShadNetEnabled(shadnetEnabledSetting, true); EmulatorSettings.SetConnectedToNetwork(connectedNetworkSetting, true); EmulatorSettings.SetPipelineCacheEnabled(pipelineCacheEnabledSetting, true); EmulatorSettings.SetPipelineCacheArchived(pipelineCacheArchiveSetting, true); @@ -531,7 +531,7 @@ void LoadSettings(std::string profile) { directMemoryAccessSetting = EmulatorSettings.IsDirectMemoryAccessEnabled(); devkitConsoleSetting = EmulatorSettings.IsDevKit(); neoModeSetting = EmulatorSettings.IsNeo(); - psnSignedInSetting = EmulatorSettings.IsPSNSignedIn(); + shadnetEnabledSetting = EmulatorSettings.IsShadNetEnabled(); connectedNetworkSetting = EmulatorSettings.IsConnectedToNetwork(); pipelineCacheEnabledSetting = EmulatorSettings.IsPipelineCacheEnabled(); pipelineCacheArchiveSetting = EmulatorSettings.IsPipelineCacheArchived();