mirror of
https://github.com/izzy2lost/xenia-edge.git
synced 2026-07-06 00:20:26 -07:00
Merge branch 'edge' of github.com:has207/xenia-edge into edge
This commit is contained in:
+2
-6
@@ -49,13 +49,9 @@ fatalwarnings("All")
|
||||
|
||||
-- TODO(DrChat): Find a way to disable this on other architectures.
|
||||
if ARCH ~= "ppc64" then
|
||||
filter({"architecture:x86_64", "platforms:Windows"})
|
||||
-- Use AVX instead of AVX2 on Windows to prevent MSVC from emitting BMI2 instructions
|
||||
-- MSVC with /arch:AVX2 generates BMI2 unconditionally, breaking Sandy/Ivy Bridge CPUs
|
||||
filter({"architecture:x86_64"})
|
||||
-- AVX2 requires Haswell (2013+) or newer
|
||||
vectorextensions("AVX")
|
||||
filter({"architecture:x86_64", "platforms:not Windows"})
|
||||
-- On non-Windows (Linux/Clang), AVX2 is safe as it can be combined with -mno-bmi2
|
||||
vectorextensions("AVX2")
|
||||
filter({})
|
||||
end
|
||||
|
||||
|
||||
@@ -308,6 +308,11 @@ void copy_and_swap_32_aligned(void* dest_ptr, const void* src_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
// Enable AVX2 for this function even when building with -mavx
|
||||
// The function has runtime detection to only use AVX2 on supported CPUs
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
__attribute__((target("avx2")))
|
||||
#endif
|
||||
void copy_and_swap_32_unaligned(void* dest_ptr, const void* src_ptr,
|
||||
size_t count) {
|
||||
auto dest = reinterpret_cast<uint32_t*>(dest_ptr);
|
||||
|
||||
@@ -162,30 +162,46 @@ void ProfileManager::SyncProfilesWithConfig() {
|
||||
LoadAccount(account_xuid);
|
||||
}
|
||||
|
||||
// Then logout all currently logged in profiles
|
||||
std::vector<uint8_t> 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<uint8_t, uint64_t> desired_profiles;
|
||||
for (uint8_t slot = 0; slot < 4; slot++) {
|
||||
if (!profile_cvars[slot]->empty()) {
|
||||
uint64_t xuid =
|
||||
xe::string_util::from_string<uint64_t>(*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<uint8_t> 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());
|
||||
|
||||
@@ -805,35 +805,80 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
launch_action = context_menu.addAction("Open");
|
||||
}
|
||||
|
||||
// Achievements option (enabled if user is logged in)
|
||||
QAction* achievements_action = nullptr;
|
||||
// Get the primary profile (same one shown in profile button)
|
||||
bool is_signedin = false;
|
||||
uint64_t xuid = 0;
|
||||
|
||||
// TODO: Handle multiple signed-in profiles better
|
||||
// For now, just use the first logged-in profile we find
|
||||
for (uint8_t user_index = 0; user_index < XUserMaxUserCount; user_index++) {
|
||||
const auto profile = profile_manager->GetProfile(user_index);
|
||||
if (profile) {
|
||||
is_signedin = true;
|
||||
xuid = profile->xuid();
|
||||
break;
|
||||
// Use the profile from slot 0 as primary (matches profile button logic)
|
||||
const auto primary_profile =
|
||||
profile_manager->GetProfile(static_cast<uint8_t>(0));
|
||||
if (primary_profile) {
|
||||
is_signedin = true;
|
||||
xuid = primary_profile->xuid();
|
||||
}
|
||||
|
||||
// Saves folder option (enabled if user is logged in, we have a valid
|
||||
// title_id, and saves exist)
|
||||
QAction* saves_action = nullptr;
|
||||
if (title_id != 0) {
|
||||
saves_action = context_menu.addAction("Saves");
|
||||
if (!is_signedin) {
|
||||
saves_action->setEnabled(false);
|
||||
} else {
|
||||
// Check if saves folder exists
|
||||
auto saves_path = profile_manager->GetProfileContentPath(
|
||||
xuid, title_id, XContentType::kSavedGame);
|
||||
if (!std::filesystem::exists(saves_path)) {
|
||||
saves_action->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_signedin && title_id != 0) {
|
||||
// Title Updates folder option (enabled if we have a valid title_id and
|
||||
// updates exist)
|
||||
QAction* title_updates_action = nullptr;
|
||||
if (title_id != 0) {
|
||||
title_updates_action = context_menu.addAction("Title Updates");
|
||||
// Title updates use xuid=0 and content type kInstaller
|
||||
auto tu_path = profile_manager->GetProfileContentPath(
|
||||
0, title_id, XContentType::kInstaller);
|
||||
if (!std::filesystem::exists(tu_path)) {
|
||||
title_updates_action->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// DLC folder option (enabled if we have a valid title_id and DLC exists)
|
||||
QAction* dlc_action = nullptr;
|
||||
if (title_id != 0) {
|
||||
dlc_action = context_menu.addAction("DLC");
|
||||
// DLC uses xuid=0 and content type kMarketplaceContent
|
||||
auto dlc_path = profile_manager->GetProfileContentPath(
|
||||
0, title_id, XContentType::kMarketplaceContent);
|
||||
if (!std::filesystem::exists(dlc_path)) {
|
||||
dlc_action->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements option (enabled if user is logged in and we have a valid
|
||||
// title_id)
|
||||
QAction* achievements_action = nullptr;
|
||||
if (title_id != 0) {
|
||||
achievements_action = context_menu.addAction("Achievements");
|
||||
connect(achievements_action, &QAction::triggered, [=, this]() {
|
||||
// Get the title name from the game entry
|
||||
QString title_name;
|
||||
for (const auto& entry : game_entries_) {
|
||||
if (entry.title_id == title_id) {
|
||||
title_name = QString::fromStdString(entry.title_name);
|
||||
break;
|
||||
if (!is_signedin) {
|
||||
achievements_action->setEnabled(false);
|
||||
} else {
|
||||
connect(achievements_action, &QAction::triggered, [=, this]() {
|
||||
// Get the title name from the game entry
|
||||
QString title_name;
|
||||
for (const auto& entry : game_entries_) {
|
||||
if (entry.title_id == title_id) {
|
||||
title_name = QString::fromStdString(entry.title_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ShowAchievementsDialog(xuid, title_id, title_name);
|
||||
});
|
||||
ShowAchievementsDialog(xuid, title_id, title_name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Game config overrides option (enabled if we have a valid title_id)
|
||||
@@ -868,6 +913,24 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
}
|
||||
} else if (selected == open_folder_action && open_folder_action) {
|
||||
OpenContainingFolder(path);
|
||||
} else if (selected == saves_action && saves_action) {
|
||||
// Open the saves folder for the primary profile
|
||||
auto saves_path = profile_manager->GetProfileContentPath(
|
||||
xuid, title_id, XContentType::kSavedGame);
|
||||
std::thread path_open(LaunchFileExplorer, saves_path);
|
||||
path_open.detach();
|
||||
} else if (selected == title_updates_action && title_updates_action) {
|
||||
// Open the title updates folder
|
||||
auto tu_path = profile_manager->GetProfileContentPath(
|
||||
0, title_id, XContentType::kInstaller);
|
||||
std::thread path_open(LaunchFileExplorer, tu_path);
|
||||
path_open.detach();
|
||||
} else if (selected == dlc_action && dlc_action) {
|
||||
// Open the DLC folder
|
||||
auto dlc_path = profile_manager->GetProfileContentPath(
|
||||
0, title_id, XContentType::kMarketplaceContent);
|
||||
std::thread path_open(LaunchFileExplorer, dlc_path);
|
||||
path_open.detach();
|
||||
} else if (selected == achievements_action && achievements_action) {
|
||||
// Achievements dialog will open in a separate call
|
||||
} else if (selected == config_action && config_action) {
|
||||
|
||||
Reference in New Issue
Block a user