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
This commit is contained in:
georgemoralis 2026-04-16 20:55:55 +03:00 committed by GitHub
parent 396d397ec6
commit 95ba5918dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 107 additions and 70 deletions

View File

@ -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");

View File

@ -179,7 +179,7 @@ struct GeneralSettings {
Setting<bool> neo_mode{false};
Setting<bool> dev_kit_mode{false};
Setting<int> extra_dmem_in_mbytes{0};
Setting<bool> psn_signed_in{false};
Setting<bool> shad_net_enabled{false};
Setting<bool> trophy_popup_disabled{false};
Setting<double> trophy_notification_duration{6.0};
Setting<std::string> trophy_notification_side{"right"};
@ -192,6 +192,7 @@ struct GeneralSettings {
Setting<bool> show_fps_counter{false};
Setting<int> console_language{1};
Setting<int> big_picture_scale{1000};
Setting<std::string> shadnet_server{""};
// return a vector of override descriptors (runtime, but tiny)
std::vector<OverrideItem> GetOverrideableFields() const {
@ -201,7 +202,7 @@ struct GeneralSettings {
make_override<GeneralSettings>("dev_kit_mode", &GeneralSettings::dev_kit_mode),
make_override<GeneralSettings>("extra_dmem_in_mbytes",
&GeneralSettings::extra_dmem_in_mbytes),
make_override<GeneralSettings>("psn_signed_in", &GeneralSettings::psn_signed_in),
make_override<GeneralSettings>("shad_net_enabled", &GeneralSettings::shad_net_enabled),
make_override<GeneralSettings>("trophy_popup_disabled",
&GeneralSettings::trophy_popup_disabled),
make_override<GeneralSettings>("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)

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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");

View File

@ -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--;

View File

@ -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,
},
};

View File

@ -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> 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<User*, 4>;

View File

@ -20,7 +20,8 @@ std::mutex UserSettingsImpl::s_mutex;
UserSettingsImpl::UserSettingsImpl() = default;
UserSettingsImpl::~UserSettingsImpl() {
Save();
if (m_loaded)
Save();
}
std::shared_ptr<UserSettingsImpl> 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;
}
}

View File

@ -40,7 +40,7 @@ public:
private:
UserManager m_userManager;
bool m_loaded{false};
static std::shared_ptr<UserSettingsImpl> s_instance;
static std::mutex s_mutex;
};

View File

@ -271,7 +271,7 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> 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: {}",

View File

@ -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();