[XAM] Multiple Profile/Dashboard related changes.

- Replaced multiple unknown parameters with proper named ones
- Added code to support creation of profile from dashboard initial run
- Added flag to remove ODD from being enumerated in devices (probably valid but not sure)
This commit is contained in:
Gliniak 2025-05-06 23:10:18 +02:00
parent d18f80457d
commit dd112ed462
10 changed files with 98 additions and 15 deletions

View file

@ -489,6 +489,23 @@ bool ProfileManager::CreateProfile(const std::string gamertag, bool autologin,
return is_account_created; return is_account_created;
} }
bool ProfileManager::CreateProfile(const X_XAMACCOUNTINFO* account_info,
uint64_t xuid) {
if (!xuid) {
xuid = GenerateXuid();
}
if (!std::filesystem::create_directories(GetProfilePath(xuid))) {
return false;
}
if (!MountProfile(xuid)) {
return false;
}
return CreateAccount(xuid, account_info);
}
const X_XAMACCOUNTINFO* ProfileManager::GetAccount(const uint64_t xuid) { const X_XAMACCOUNTINFO* ProfileManager::GetAccount(const uint64_t xuid) {
if (!accounts_.count(xuid)) { if (!accounts_.count(xuid)) {
return nullptr; return nullptr;
@ -505,15 +522,26 @@ bool ProfileManager::CreateAccount(const uint64_t xuid,
string_util::copy_truncating(account.gamertag, gamertag_u16, string_util::copy_truncating(account.gamertag, gamertag_u16,
sizeof(account.gamertag)); sizeof(account.gamertag));
UpdateAccount(xuid, &account); const bool result = UpdateAccount(xuid, &account);
DismountProfile(xuid); DismountProfile(xuid);
if (result) {
accounts_.insert({xuid, account}); accounts_.insert({xuid, account});
return true; }
return result;
}
bool ProfileManager::CreateAccount(const uint64_t xuid,
const X_XAMACCOUNTINFO* account) {
const bool result = UpdateAccount(xuid, account);
if (result) {
accounts_.insert({xuid, *account});
}
return result;
} }
bool ProfileManager::UpdateAccount(const uint64_t xuid, bool ProfileManager::UpdateAccount(const uint64_t xuid,
X_XAMACCOUNTINFO* account) { const X_XAMACCOUNTINFO* account) {
const std::string guest_path = const std::string guest_path =
fmt::format(kDefaultMountFormat, xuid) + ":\\Account"; fmt::format(kDefaultMountFormat, xuid) + ":\\Account";

View file

@ -64,7 +64,8 @@ class ProfileManager {
bool CreateProfile(const std::string gamertag, bool autologin, bool CreateProfile(const std::string gamertag, bool autologin,
bool default_xuid = false); bool default_xuid = false);
// bool CreateProfile(const X_XAMACCOUNTINFO* account_info); bool CreateProfile(const X_XAMACCOUNTINFO* account_info, uint64_t xuid);
bool DeleteProfile(const uint64_t xuid); bool DeleteProfile(const uint64_t xuid);
void ModifyGamertag(const uint64_t xuid, std::string gamertag); void ModifyGamertag(const uint64_t xuid, std::string gamertag);
@ -105,7 +106,8 @@ class ProfileManager {
private: private:
void UpdateConfig(const uint64_t xuid, const uint8_t slot); void UpdateConfig(const uint64_t xuid, const uint8_t slot);
bool CreateAccount(const uint64_t xuid, const std::string gamertag); bool CreateAccount(const uint64_t xuid, const std::string gamertag);
bool UpdateAccount(const uint64_t xuid, X_XAMACCOUNTINFO* account); bool CreateAccount(const uint64_t xuid, const X_XAMACCOUNTINFO* account);
bool UpdateAccount(const uint64_t xuid, const X_XAMACCOUNTINFO* account);
std::filesystem::path GetProfilePath(const uint64_t xuid) const; std::filesystem::path GetProfilePath(const uint64_t xuid) const;
std::filesystem::path GetProfilePath(const std::string xuid) const; std::filesystem::path GetProfilePath(const std::string xuid) const;

View file

@ -91,11 +91,13 @@ class UserProfile {
std::span<const uint8_t> GetProfileIcon(XTileType icon_type) { std::span<const uint8_t> GetProfileIcon(XTileType icon_type) {
// Overwrite same types? // Overwrite same types?
if (icon_type == XTileType::kPersonalGamerTile) { if (icon_type == XTileType::kPersonalGamerTile ||
icon_type == XTileType::kLocalGamerTile) {
icon_type = XTileType::kGamerTile; icon_type = XTileType::kGamerTile;
} }
if (icon_type == XTileType::kPersonalGamerTileSmall) { if (icon_type == XTileType::kPersonalGamerTileSmall ||
icon_type == XTileType::kLocalGamerTileSmall) {
icon_type = XTileType::kGamerTileSmall; icon_type = XTileType::kGamerTileSmall;
} }

View file

@ -770,6 +770,8 @@ std::span<const uint8_t> UserTracker::GetIcon(uint64_t xuid, uint32_t title_id,
} }
case XTileType::kGamerTile: case XTileType::kGamerTile:
case XTileType::kGamerTileSmall: case XTileType::kGamerTileSmall:
case XTileType::kLocalGamerTile:
case XTileType::kLocalGamerTileSmall:
case XTileType::kPersonalGamerTile: case XTileType::kPersonalGamerTile:
case XTileType::kPersonalGamerTileSmall: case XTileType::kPersonalGamerTileSmall:
return user->GetProfileIcon(tile_type); return user->GetProfileIcon(tile_type);

View file

@ -15,6 +15,7 @@
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/xam_private.h" #include "xenia/kernel/xam/xam_private.h"
#include "xenia/kernel/xenumerator.h" #include "xenia/kernel/xenumerator.h"
#include "xenia/vfs/devices/stfs_xbox.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
namespace xe { namespace xe {
@ -171,6 +172,11 @@ dword_result_t XamContentCreateDeviceEnumerator_entry(dword_t content_type,
} }
for (const auto& device_info : dummy_device_infos_) { for (const auto& device_info : dummy_device_infos_) {
if (device_info->device_type == DeviceType::ODD &&
(content_flags & vfs::XContentFlag::kExcludeReadOnlyDevices)) {
continue;
}
// Copy our dummy device into the enumerator // Copy our dummy device into the enumerator
auto device_data = e->AppendItem(); auto device_data = e->AppendItem();
assert_not_null(device_data); assert_not_null(device_data);

View file

@ -19,6 +19,7 @@ namespace xam {
enum class DeviceType : uint32_t { enum class DeviceType : uint32_t {
Invalid = 0, Invalid = 0,
HDD = 1, HDD = 1,
MU = 2,
ODD = 4, ODD = 4,
}; };

View file

@ -62,11 +62,40 @@ dword_result_t XamProfileCreate_entry(dword_t flags, lpdword_t device_id,
pointer_t<X_XAMACCOUNTINFO> account, pointer_t<X_XAMACCOUNTINFO> account,
dword_t unk1, dword_t unk2, dword_t unk3, dword_t unk1, dword_t unk2, dword_t unk3,
dword_t unk4) { dword_t unk4) {
// **unk4 if (device_id) {
*device_id = 0x1;
}
if (xuid != 0) {
assert_always();
return X_E_INVALIDARG;
}
X_XAMACCOUNTINFO account_info_data;
memcpy(&account_info_data, account, sizeof(X_XAMACCOUNTINFO));
xe::copy_and_swap<char16_t>(account_info_data.gamertag,
account_info_data.gamertag, 16);
bool result = kernel_state()->xam_state()->profile_manager()->CreateProfile(
&account_info_data, xuid);
return result ? X_ERROR_SUCCESS : X_ERROR_INVALID_PARAMETER;
}
DECLARE_XAM_EXPORT1(XamProfileCreate, kNone, kSketchy);
dword_result_t XamProfileClose_entry(lpstring_t mount_name) {
std::string guest_name = mount_name.value();
const bool result =
kernel_state()->file_system()->UnregisterDevice(guest_name + ':');
return result ? X_ERROR_SUCCESS : X_ERROR_FUNCTION_FAILED;
}
DECLARE_XAM_EXPORT1(XamProfileClose, kNone, kStub);
dword_result_t XamProfileGetCreationStatus_entry(lpdword_t r3, lpdword_t r4) {
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
DECLARE_XAM_EXPORT1(XamProfileCreate, kNone, kStub); DECLARE_XAM_EXPORT1(XamProfileGetCreationStatus, kNone, kStub);
} // namespace xam } // namespace xam
} // namespace kernel } // namespace kernel

View file

@ -2086,15 +2086,19 @@ dword_result_t XamShowCreateProfileUI_entry(dword_t user_index, dword_t unkn) {
DECLARE_XAM_EXPORT1(XamShowCreateProfileUI, kUserProfiles, kImplemented); DECLARE_XAM_EXPORT1(XamShowCreateProfileUI, kUserProfiles, kImplemented);
dword_result_t XamShowAchievementsUI_entry(dword_t user_index, dword_result_t XamShowAchievementsUI_entry(dword_t user_index,
dword_t unk_mask) { dword_t title_id) {
auto user = kernel_state()->xam_state()->GetUserProfile(user_index); auto user = kernel_state()->xam_state()->GetUserProfile(user_index);
if (!user) { if (!user) {
return X_ERROR_NO_SUCH_USER; return X_ERROR_NO_SUCH_USER;
} }
uint32_t proper_title_id =
title_id ? title_id.value()
: kernel_state()->xam_state()->spa_info()->title_id();
const auto info = const auto info =
kernel_state()->xam_state()->user_tracker()->GetUserTitleInfo( kernel_state()->xam_state()->user_tracker()->GetUserTitleInfo(
user->xuid(), kernel_state()->xam_state()->spa_info()->title_id()); user->xuid(), proper_title_id);
if (!info) { if (!info) {
return X_ERROR_NO_SUCH_USER; return X_ERROR_NO_SUCH_USER;

View file

@ -637,9 +637,12 @@ dword_result_t XamReadTile_entry(dword_t tile_type, dword_t title_id,
lpdword_t buffer_size_ptr, lpdword_t buffer_size_ptr,
dword_t overlapped_ptr) { dword_t overlapped_ptr) {
auto user = kernel_state()->xam_state()->GetUserProfile(user_index); auto user = kernel_state()->xam_state()->GetUserProfile(user_index);
if (!user) {
user = kernel_state()->xam_state()->GetUserProfile(item_id);
if (!user) { if (!user) {
return X_ERROR_INVALID_PARAMETER; return X_ERROR_INVALID_PARAMETER;
} }
}
if (!buffer_size_ptr) { if (!buffer_size_ptr) {
return X_ERROR_INVALID_PARAMETER; return X_ERROR_INVALID_PARAMETER;
@ -802,7 +805,7 @@ dword_result_t XamReadTileToTexture_entry(dword_t tile_type, dword_t title_id,
} }
DECLARE_XAM_EXPORT1(XamReadTileToTexture, kUserProfiles, kStub); DECLARE_XAM_EXPORT1(XamReadTileToTexture, kUserProfiles, kStub);
dword_result_t XamWriteGamerTile_entry(dword_t arg1, dword_t arg2, dword_result_t XamWriteGamerTile_entry(dword_t user_index, dword_t title_id,
dword_t small_tile_id, dword_t small_tile_id,
dword_t big_tile_id, dword_t arg5, dword_t big_tile_id, dword_t arg5,
dword_t overlapped_ptr) { dword_t overlapped_ptr) {

View file

@ -89,7 +89,13 @@ enum XContentFlag : uint32_t {
kForceUI = 0x200, kForceUI = 0x200,
// Enumeration // Enumeration
kExcludeCommon = 0x1000 kExcludeCommon = 0x1000,
// Other
kEnumerateAllProfiles = 0x10000000,
// Device enumerator?
kExcludeReadOnlyDevices = 0x80000000,
}; };
/* STFS structures */ /* STFS structures */