From 99361c54e514b8df1f3bd23f4a4c34baa787cdb0 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Sat, 1 Nov 2025 14:16:31 +0900 Subject: [PATCH] [App] Ensure profile state is reloaded on child process exit. If the game was started logged out but the user logs in during the game we want that to be reflected in the main game list windows. --- src/xenia/app/emulator_window.cc | 18 +++++++++--- src/xenia/kernel/xam/profile_manager.cc | 38 ++++++++++++++++++------- src/xenia/ui/game_list_dialog_qt.h | 2 +- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index beacaa11f..7162c4f4b 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -2394,16 +2394,25 @@ void EmulatorWindow::CheckChildProcessStatus() { // Detect transition from having child to no child if (had_child_last_check && !has_child_now) { - XELOGI("Child process exited, remounting profiles and reloading GPDs"); + XELOGI("Child process exited, reloading config and profile state"); - // Remount VFS for all logged-in profiles to pick up file changes from game - // process + // Reload config from disk to pick up any profile login changes made by + // child process + config::ReloadConfig(); + XELOGI("Config reloaded from disk"); + + // Sync profile login state with the reloaded config if (emulator_ && emulator_->kernel_state() && emulator_->kernel_state()->xam_state()) { auto profile_manager = emulator_->kernel_state()->xam_state()->profile_manager(); if (profile_manager) { - // Remount VFS for each logged-in profile + // Sync profiles with config: logout current profiles and login based on + // config cvars + profile_manager->SyncProfilesWithConfig(); + XELOGI("Profile login state synced with config"); + + // Remount VFS for all newly logged-in profiles for (uint8_t i = 0; i < 4; i++) { auto profile = profile_manager->GetProfile(i); if (profile) { @@ -2427,6 +2436,7 @@ void EmulatorWindow::CheckChildProcessStatus() { // Reload the game list dialog if it's open if (game_list_dialog_qt_) { game_list_dialog_qt_->LoadGameList(); + game_list_dialog_qt_->UpdateProfileButtonState(); XELOGI("Game list dialog refreshed"); } diff --git a/src/xenia/kernel/xam/profile_manager.cc b/src/xenia/kernel/xam/profile_manager.cc index 1035a9351..427d381c8 100644 --- a/src/xenia/kernel/xam/profile_manager.cc +++ b/src/xenia/kernel/xam/profile_manager.cc @@ -162,30 +162,46 @@ void ProfileManager::SyncProfilesWithConfig() { LoadAccount(account_xuid); } - // Then logout all currently logged in profiles - std::vector slots_to_logout; - for (const auto& [slot, profile] : logged_profiles_) { - slots_to_logout.push_back(slot); - } - for (uint8_t slot : slots_to_logout) { - Logout(slot, false); - } - - // Now login profiles based on the current cvar values + // Build desired login state from current cvar values const std::string* profile_cvars[4] = { &cvars::logged_profile_slot_0_xuid, &cvars::logged_profile_slot_1_xuid, &cvars::logged_profile_slot_2_xuid, &cvars::logged_profile_slot_3_xuid}; + std::map desired_profiles; for (uint8_t slot = 0; slot < 4; slot++) { if (!profile_cvars[slot]->empty()) { uint64_t xuid = xe::string_util::from_string(*profile_cvars[slot], true); if (xuid != 0) { - Login(xuid, slot, false); + desired_profiles[slot] = xuid; } } } + // Logout profiles that shouldn't be logged in anymore + std::vector slots_to_logout; + for (const auto& [slot, profile] : logged_profiles_) { + auto desired_it = desired_profiles.find(slot); + if (desired_it == desired_profiles.end() || + desired_it->second != profile->xuid()) { + // This slot should be logged out (either empty or different profile) + slots_to_logout.push_back(slot); + } + } + for (uint8_t slot : slots_to_logout) { + Logout(slot, false); + } + + // Login profiles that aren't already logged in + for (const auto& [slot, xuid] : desired_profiles) { + auto current_profile = logged_profiles_.find(slot); + if (current_profile == logged_profiles_.end() || + current_profile->second->xuid() != xuid) { + // This slot needs to be logged in (either empty or different profile) + Login(xuid, slot, false); + } + } + // Send a single notification after all changes kernel_state_->BroadcastNotification(kXNotificationSystemSignInChanged, GetUsedUserSlots().to_ulong()); diff --git a/src/xenia/ui/game_list_dialog_qt.h b/src/xenia/ui/game_list_dialog_qt.h index c2d70f836..338d3f591 100644 --- a/src/xenia/ui/game_list_dialog_qt.h +++ b/src/xenia/ui/game_list_dialog_qt.h @@ -56,6 +56,7 @@ class GameListDialogQt : public QWidget { void LoadGameList(); void RefreshIcons(); + void UpdateProfileButtonState(); private slots: void OnFilterTextChanged(const QString& text); @@ -67,7 +68,6 @@ class GameListDialogQt : public QWidget { void OnProfileContextMenu(const QPoint& pos); void OnSelectionChanged(); void UpdatePlayButtonState(); - void UpdateProfileButtonState(); protected: bool eventFilter(QObject* obj, QEvent* event) override;