[Kernel] Move xam_user to new shim convention.
This commit is contained in:
parent
fc0cc89a1d
commit
dc5bd83098
|
@ -21,100 +21,79 @@ namespace xe {
|
|||
namespace kernel {
|
||||
namespace xam {
|
||||
|
||||
SHIM_CALL XamUserGetXUID_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk = SHIM_GET_ARG_32(1);
|
||||
uint32_t xuid_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("XamUserGetXUID(%d, %.8X, %.8X)", user_index, unk, xuid_ptr);
|
||||
|
||||
if (user_index == 0) {
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
if (xuid_ptr) {
|
||||
SHIM_SET_MEM_64(xuid_ptr, user_profile->xuid());
|
||||
}
|
||||
SHIM_SET_RETURN_32(0);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
dword_result_t XamUserGetXUID(dword_t user_index, dword_t unk,
|
||||
lpqword_t xuid_ptr) {
|
||||
if (user_index) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
if (xuid_ptr) {
|
||||
*xuid_ptr = user_profile->xuid();
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserGetXUID,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL XamUserGetSigninState_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XamUserGetSigninState(%d)", user_index);
|
||||
|
||||
dword_result_t XamUserGetSigninState(dword_t user_index) {
|
||||
// Yield, as some games spam this.
|
||||
xe::threading::MaybeYield();
|
||||
|
||||
// Lie and say we are signed in, but local-only.
|
||||
// This should keep games from asking us to sign in and also keep them
|
||||
// from initializing the network.
|
||||
|
||||
if (user_index == 0 || (user_index & 0xFF) == 0xFF) {
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
auto signin_state = user_profile->signin_state();
|
||||
SHIM_SET_RETURN_32(signin_state);
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
return user_profile->signin_state();
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserGetSigninState,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint64_t> xuid;
|
||||
xe::be<uint32_t> unk04; // maybe zero?
|
||||
xe::be<uint32_t> unk08; // maybe zero?
|
||||
xe::be<uint32_t> signin_state;
|
||||
xe::be<uint32_t> unk0C; // ?
|
||||
xe::be<uint32_t> unk10; // ?
|
||||
xe::be<uint32_t> unk14; // ?
|
||||
char name[16];
|
||||
} X_USER_SIGNIN_INFO;
|
||||
static_assert_size(X_USER_SIGNIN_INFO, 40);
|
||||
|
||||
SHIM_CALL XamUserGetSigninInfo_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t flags = SHIM_GET_ARG_32(1);
|
||||
uint32_t info_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("XamUserGetSigninInfo(%d, %.8X, %.8X)", user_index, flags, info_ptr);
|
||||
|
||||
if (!info_ptr) {
|
||||
SHIM_SET_RETURN_32(X_ERROR_INVALID_PARAMETER);
|
||||
return;
|
||||
dword_result_t XamUserGetSigninInfo(dword_t user_index, dword_t flags,
|
||||
pointer_t<X_USER_SIGNIN_INFO> info) {
|
||||
if (!info) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto info = reinterpret_cast<X_USER_SIGNIN_INFO*>(SHIM_MEM_ADDR(info_ptr));
|
||||
std::memset(info, 0, sizeof(X_USER_SIGNIN_INFO));
|
||||
|
||||
if (user_index == 0) {
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
info->xuid = user_profile->xuid();
|
||||
info->signin_state = user_profile->signin_state();
|
||||
std::strncpy(info->name, user_profile->name().data(), 15);
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return X_ERROR_SUCCESS;
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserGetSigninInfo,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL XamUserGetName_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t buffer_len = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("XamUserGetName(%d, %.8X, %d)", user_index, buffer_ptr, buffer_len);
|
||||
|
||||
if (user_index == 0) {
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
char* buffer = reinterpret_cast<char*>(SHIM_MEM_ADDR(buffer_ptr));
|
||||
std::strcpy(buffer, user_profile->name().data());
|
||||
SHIM_SET_RETURN_32(0);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
dword_result_t XamUserGetName(dword_t user_index, lpstring_t buffer,
|
||||
dword_t buffer_len) {
|
||||
if (user_index) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
std::strncpy(buffer, user_profile->name().data(), buffer_len);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserGetName,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint32_t> setting_count;
|
||||
|
@ -134,56 +113,39 @@ typedef struct {
|
|||
static_assert_size(X_USER_READ_PROFILE_SETTING, 40);
|
||||
|
||||
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/xboxtools.cpp
|
||||
SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t title_id = SHIM_GET_ARG_32(0);
|
||||
uint32_t user_index = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk_0 = SHIM_GET_ARG_32(2);
|
||||
uint32_t unk_1 = SHIM_GET_ARG_32(3);
|
||||
uint32_t setting_count = SHIM_GET_ARG_32(4);
|
||||
uint32_t setting_ids_ptr = SHIM_GET_ARG_32(5);
|
||||
uint32_t buffer_size_ptr = SHIM_GET_ARG_32(6);
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(7);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(8);
|
||||
|
||||
uint32_t buffer_size = !buffer_size_ptr ? 0 : SHIM_MEM_32(buffer_size_ptr);
|
||||
|
||||
XELOGD(
|
||||
"XamUserReadProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, "
|
||||
"%.8X)",
|
||||
title_id, user_index, unk_0, unk_1, setting_count, setting_ids_ptr,
|
||||
buffer_size_ptr, buffer_size, buffer_ptr, overlapped_ptr);
|
||||
dword_result_t XamUserReadProfileSettings(
|
||||
dword_t title_id, dword_t user_index, dword_t unk_0, dword_t unk_1,
|
||||
dword_t setting_count, lpdword_t setting_ids, lpdword_t buffer_size_ptr,
|
||||
lpvoid_t buffer_ptr, dword_t overlapped_ptr) {
|
||||
uint32_t buffer_size = !buffer_size_ptr ? 0 : *buffer_size_ptr;
|
||||
|
||||
assert_zero(unk_0);
|
||||
assert_zero(unk_1);
|
||||
|
||||
// TODO(gibbed): why is this a thing?
|
||||
if (user_index == 255) {
|
||||
user_index = 0;
|
||||
uint32_t actual_user_index = user_index;
|
||||
if (actual_user_index == 255) {
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
// Title ID = 0 means us.
|
||||
// 0xfffe07d1 = profile?
|
||||
|
||||
if (user_index) {
|
||||
if (actual_user_index) {
|
||||
// Only support user 0.
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_NOT_FOUND);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_NOT_FOUND);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return;
|
||||
return X_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
|
||||
// First call asks for size (fill buffer_size_ptr).
|
||||
// Second call asks for buffer contents with that size.
|
||||
|
||||
auto setting_ids = (xe::be<uint32_t>*)SHIM_MEM_ADDR(setting_ids_ptr);
|
||||
|
||||
// Compute required base size.
|
||||
uint32_t base_size_needed = sizeof(X_USER_READ_PROFILE_SETTINGS);
|
||||
base_size_needed += setting_count * sizeof(X_USER_READ_PROFILE_SETTING);
|
||||
|
@ -209,34 +171,29 @@ SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_context,
|
|||
if (any_missing) {
|
||||
// TODO(benvanik): don't fail? most games don't even check!
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INVALID_PARAMETER);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_INVALID_PARAMETER);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INVALID_PARAMETER);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return;
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
SHIM_SET_MEM_32(buffer_size_ptr, size_needed);
|
||||
*buffer_size_ptr = size_needed;
|
||||
if (!buffer_ptr || buffer_size < size_needed) {
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INSUFFICIENT_BUFFER);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_INSUFFICIENT_BUFFER);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INSUFFICIENT_BUFFER);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return;
|
||||
return X_ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
auto out_header = reinterpret_cast<X_USER_READ_PROFILE_SETTINGS*>(
|
||||
SHIM_MEM_ADDR(buffer_ptr));
|
||||
out_header->setting_count = setting_count;
|
||||
out_header->settings_ptr = buffer_ptr + 8;
|
||||
auto out_header = buffer_ptr.as<X_USER_READ_PROFILE_SETTINGS*>();
|
||||
out_header->setting_count = static_cast<uint32_t>(setting_count);
|
||||
out_header->settings_ptr = buffer_ptr.guest_address() + 8;
|
||||
|
||||
auto out_setting = reinterpret_cast<X_USER_READ_PROFILE_SETTING*>(
|
||||
SHIM_MEM_ADDR(out_header->settings_ptr));
|
||||
auto out_setting =
|
||||
reinterpret_cast<X_USER_READ_PROFILE_SETTING*>(buffer_ptr + 8);
|
||||
|
||||
size_t buffer_offset = base_size_needed;
|
||||
for (uint32_t n = 0; n < setting_count; ++n) {
|
||||
|
@ -246,13 +203,13 @@ SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_context,
|
|||
std::memset(out_setting, 0, sizeof(X_USER_READ_PROFILE_SETTING));
|
||||
out_setting->from =
|
||||
!setting || !setting->is_set ? 0 : setting->is_title_specific() ? 2 : 1;
|
||||
out_setting->user_index = user_index;
|
||||
out_setting->user_index = actual_user_index;
|
||||
out_setting->setting_id = setting_id;
|
||||
|
||||
if (setting && setting->is_set) {
|
||||
buffer_offset =
|
||||
setting->Append(&out_setting->setting_data[0],
|
||||
SHIM_MEM_ADDR(buffer_ptr), buffer_ptr, buffer_offset);
|
||||
setting->Append(&out_setting->setting_data[0], buffer_ptr,
|
||||
buffer_ptr.guest_address(), buffer_offset);
|
||||
}
|
||||
// TODO(benvanik): why did I do this?
|
||||
/*else {
|
||||
|
@ -263,12 +220,14 @@ SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_context,
|
|||
}
|
||||
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_SUCCESS);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserReadProfileSettings,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint32_t> from;
|
||||
|
@ -293,45 +252,33 @@ typedef struct {
|
|||
};
|
||||
} X_USER_WRITE_PROFILE_SETTING;
|
||||
|
||||
SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t unknown = SHIM_GET_ARG_32(1);
|
||||
uint32_t setting_count = SHIM_GET_ARG_32(2);
|
||||
uint32_t settings_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD("XamUserWriteProfileSettings(%.8X, %d, %d, %.8X, %.8X)", user_index,
|
||||
unknown, setting_count, settings_ptr, overlapped_ptr);
|
||||
|
||||
if (!setting_count || !settings_ptr) {
|
||||
dword_result_t XamUserWriteProfileSettings(
|
||||
dword_t user_index, dword_t unk, dword_t setting_count,
|
||||
pointer_t<X_USER_WRITE_PROFILE_SETTING> settings, dword_t overlapped_ptr) {
|
||||
if (!setting_count || !settings) {
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INVALID_PARAMETER);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_INVALID_PARAMETER);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_INVALID_PARAMETER);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return;
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (user_index == 255) {
|
||||
user_index = 0;
|
||||
uint32_t actual_user_index = user_index;
|
||||
if (actual_user_index == 255) {
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
if (user_index) {
|
||||
if (actual_user_index) {
|
||||
// Only support user 0.
|
||||
SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
|
||||
return;
|
||||
return X_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Update and save settings.
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
auto settings_data_arr = reinterpret_cast<X_USER_WRITE_PROFILE_SETTING*>(
|
||||
SHIM_MEM_ADDR(settings_ptr));
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
|
||||
for (uint32_t n = 0; n < setting_count; ++n) {
|
||||
const X_USER_WRITE_PROFILE_SETTING& settings_data = settings_data_arr[n];
|
||||
const X_USER_WRITE_PROFILE_SETTING& settings_data = settings[n];
|
||||
XELOGD(
|
||||
"XamUserWriteProfileSettings: setting index [%d]:"
|
||||
" from=%d setting_id=%.8X data.type=%d",
|
||||
|
@ -343,14 +290,15 @@ SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
|||
|
||||
switch (settingType) {
|
||||
case UserProfile::Setting::Type::BINARY: {
|
||||
uint8_t* settings_data_ptr = SHIM_MEM_ADDR(settings_data.binary.ptr);
|
||||
uint8_t* settings_data_ptr = kernel_state()->memory()->TranslateVirtual(
|
||||
settings_data.binary.ptr);
|
||||
size_t settings_data_len = settings_data.binary.length;
|
||||
std::vector<uint8_t> data_vec;
|
||||
|
||||
if (settings_data.binary.ptr) {
|
||||
// Copy provided data
|
||||
data_vec.resize(settings_data_len);
|
||||
memcpy(data_vec.data(), settings_data_ptr, settings_data_len);
|
||||
std::memcpy(data_vec.data(), settings_data_ptr, settings_data_len);
|
||||
} else {
|
||||
// Data pointer was NULL, so just fill with zeroes
|
||||
data_vec.resize(settings_data_len, 0);
|
||||
|
@ -377,284 +325,215 @@ SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
|||
}
|
||||
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_SUCCESS);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserWriteProfileSettings,
|
||||
ExportTag::kUserProfiles | ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL XamUserCheckPrivilege_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t mask = SHIM_GET_ARG_32(1);
|
||||
uint32_t out_value_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("XamUserCheckPrivilege(%d, %.8X, %.8X)", user_index, mask,
|
||||
out_value_ptr);
|
||||
|
||||
if ((user_index & 0xFF) == 0xFF) {
|
||||
dword_result_t XamUserCheckPrivilege(dword_t user_index, dword_t mask,
|
||||
lpdword_t out_value) {
|
||||
uint32_t actual_user_index = user_index;
|
||||
if ((actual_user_index & 0xFF) == 0xFF) {
|
||||
// Always pin user to 0.
|
||||
user_index = 0;
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
if (user_index) {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
return;
|
||||
if (actual_user_index) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
// If we deny everything, games should hopefully not try to do stuff.
|
||||
SHIM_SET_MEM_32(out_value_ptr, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
*out_value = 0;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserCheckPrivilege,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamUserContentRestrictionGetFlags_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t out_flags_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XamUserContentRestrictionGetFlags(%d, %.8X)", user_index,
|
||||
out_flags_ptr);
|
||||
|
||||
if ((user_index & 0xFF) == 0xFF) {
|
||||
dword_result_t XamUserContentRestrictionGetFlags(dword_t user_index,
|
||||
lpdword_t out_flags) {
|
||||
uint32_t actual_user_index = user_index;
|
||||
if ((actual_user_index & 0xFF) == 0xFF) {
|
||||
// Always pin user to 0.
|
||||
user_index = 0;
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
if (user_index) {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
return;
|
||||
if (actual_user_index) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
// No restrictions?
|
||||
SHIM_SET_MEM_32(out_flags_ptr, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
*out_flags = 0;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserContentRestrictionGetFlags,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamUserContentRestrictionGetRating_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t out_unk2_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t out_unk3_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("XamUserContentRestrictionGetRating(%d, %.8X, %.8X, %.8X)", user_index,
|
||||
unk1, out_unk2_ptr, out_unk3_ptr);
|
||||
|
||||
if ((user_index & 0xFF) == 0xFF) {
|
||||
dword_result_t XamUserContentRestrictionGetRating(dword_t user_index,
|
||||
dword_t unk1,
|
||||
lpdword_t out_unk2,
|
||||
lpdword_t out_unk3) {
|
||||
uint32_t actual_user_index = user_index;
|
||||
if ((actual_user_index & 0xFF) == 0xFF) {
|
||||
// Always pin user to 0.
|
||||
user_index = 0;
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
if (user_index) {
|
||||
SHIM_SET_RETURN_32(X_ERROR_NO_SUCH_USER);
|
||||
return;
|
||||
if (actual_user_index) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
// Some games have special case paths for 3F that differ from the failure
|
||||
// path, so my guess is that's 'don't care'.
|
||||
SHIM_SET_MEM_32(out_unk2_ptr, 0x3F);
|
||||
SHIM_SET_MEM_32(out_unk3_ptr, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
*out_unk2 = 0x3F;
|
||||
*out_unk3 = 0;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserContentRestrictionGetRating,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamUserContentRestrictionCheckAccess_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t unk3 = SHIM_GET_ARG_32(3);
|
||||
uint32_t unk4 = SHIM_GET_ARG_32(4);
|
||||
uint32_t out_unk5_ptr = SHIM_GET_ARG_32(5);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(6);
|
||||
|
||||
XELOGD(
|
||||
"XamUserContentRestrictionCheckAccess(%d, %.8X, %.8X, %.8X, %.8X, %.8X, "
|
||||
"%.8X)",
|
||||
user_index, unk1, unk2, unk3, unk4, out_unk5_ptr, overlapped_ptr);
|
||||
|
||||
SHIM_SET_MEM_32(out_unk5_ptr, 1);
|
||||
dword_result_t XamUserContentRestrictionCheckAccess(dword_t user_index,
|
||||
dword_t unk1, dword_t unk2,
|
||||
dword_t unk3, dword_t unk4,
|
||||
lpdword_t out_unk5,
|
||||
dword_t overlapped_ptr) {
|
||||
*out_unk5 = 1;
|
||||
|
||||
if (overlapped_ptr) {
|
||||
// TODO(benvanik): does this need the access arg on it?
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserContentRestrictionCheckAccess,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamUserAreUsersFriends_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t out_value_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD("XamUserAreUsersFriends(%d, %.8X, %.8X, %.8X, %.8X)", user_index, unk1,
|
||||
unk2, out_value_ptr, overlapped_ptr);
|
||||
|
||||
if ((user_index & 0xFF) == 0xFF) {
|
||||
dword_result_t XamUserAreUsersFriends(dword_t user_index, dword_t unk1,
|
||||
dword_t unk2, lpdword_t out_value,
|
||||
dword_t overlapped_ptr) {
|
||||
uint32_t actual_user_index = user_index;
|
||||
if ((actual_user_index & 0xFF) == 0xFF) {
|
||||
// Always pin user to 0.
|
||||
user_index = 0;
|
||||
actual_user_index = 0;
|
||||
}
|
||||
|
||||
SHIM_SET_MEM_32(out_value_ptr, 0);
|
||||
*out_value = 0;
|
||||
|
||||
if (user_index) {
|
||||
// Only support user 0.
|
||||
SHIM_SET_RETURN_32(X_ERROR_NOT_LOGGED_ON);
|
||||
return;
|
||||
return X_ERROR_NOT_LOGGED_ON;
|
||||
}
|
||||
|
||||
X_RESULT result = X_ERROR_SUCCESS;
|
||||
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
const auto& user_profile = kernel_state()->user_profile();
|
||||
if (user_profile->signin_state() == 0) {
|
||||
result = X_ERROR_NOT_LOGGED_ON;
|
||||
} else {
|
||||
// No friends!
|
||||
*out_value = 0;
|
||||
}
|
||||
|
||||
// No friends!
|
||||
SHIM_SET_MEM_32(out_value_ptr, 0);
|
||||
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, result);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(result);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, result);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserAreUsersFriends,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamShowSigninUI_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk_0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk_mask = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XamShowSigninUI(%d, %.8X)", unk_0, unk_mask);
|
||||
|
||||
dword_result_t XamShowSigninUI(dword_t unk, dword_t unk_mask) {
|
||||
// Mask values vary. Probably matching user types? Local/remote?
|
||||
// Games seem to sit and loop until we trigger this notification.
|
||||
kernel_state->BroadcastNotification(0x00000009, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
kernel_state()->BroadcastNotification(0x00000009, 0);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamShowSigninUI,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamUserCreateAchievementEnumerator_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t title_id = SHIM_GET_ARG_32(0);
|
||||
uint32_t user_index = SHIM_GET_ARG_32(1);
|
||||
uint32_t xuid = SHIM_GET_ARG_32(2);
|
||||
uint32_t flags = SHIM_GET_ARG_32(3);
|
||||
uint32_t offset = SHIM_GET_ARG_32(4);
|
||||
uint32_t count = SHIM_GET_ARG_32(5);
|
||||
uint32_t buffer_size_ptr = SHIM_GET_ARG_32(6);
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(7);
|
||||
|
||||
XELOGD(
|
||||
"XamUserCreateAchievementEnumerator(%.8X, %d, %.8X, %.8X, %d, %d, %.8X, "
|
||||
"%.8X)",
|
||||
title_id, user_index, xuid, flags, offset, count, buffer_size_ptr,
|
||||
handle_ptr);
|
||||
|
||||
dword_result_t XamUserCreateAchievementEnumerator(dword_t title_id,
|
||||
dword_t user_index,
|
||||
dword_t xuid, dword_t flags,
|
||||
dword_t offset, dword_t count,
|
||||
lpdword_t buffer_size_ptr,
|
||||
lpdword_t handle_ptr) {
|
||||
if (buffer_size_ptr) {
|
||||
// TODO(benvanik): struct size/etc.
|
||||
SHIM_SET_MEM_32(buffer_size_ptr, 64 * count);
|
||||
*buffer_size_ptr = 64 * count;
|
||||
}
|
||||
|
||||
auto e = new XStaticEnumerator(kernel_state, count, 64);
|
||||
auto e = new XStaticEnumerator(kernel_state(), count, 64);
|
||||
e->Initialize();
|
||||
|
||||
SHIM_SET_MEM_32(handle_ptr, e->handle());
|
||||
*handle_ptr = e->handle();
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamUserCreateAchievementEnumerator,
|
||||
ExportTag::kUserProfiles | ExportTag::kSketchy);
|
||||
|
||||
SHIM_CALL XamParseGamerTileKey_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t key_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t out0_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t out1_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t out2_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("XamParseGamerTileKey(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", key_ptr,
|
||||
out0_ptr, out1_ptr, out2_ptr);
|
||||
|
||||
SHIM_SET_MEM_32(out0_ptr, 0xC0DE0001);
|
||||
SHIM_SET_MEM_32(out1_ptr, 0xC0DE0002);
|
||||
SHIM_SET_MEM_32(out2_ptr, 0xC0DE0003);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
dword_result_t XamParseGamerTileKey(lpdword_t key_ptr, lpdword_t out1_ptr,
|
||||
lpdword_t out2_ptr, lpdword_t out3_ptr) {
|
||||
*out1_ptr = 0xC0DE0001;
|
||||
*out2_ptr = 0xC0DE0002;
|
||||
*out3_ptr = 0xC0DE0003;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamParseGamerTileKey,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamReadTileToTexture_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0); // const?
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1); // out0 from XamParseGamerTileKey
|
||||
uint32_t unk2 = SHIM_GET_ARG_32(2); // some variant of out1/out2
|
||||
uint32_t unk3 = SHIM_GET_ARG_32(3); // const?
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(4);
|
||||
uint32_t stride = SHIM_GET_ARG_32(5);
|
||||
uint32_t height = SHIM_GET_ARG_32(6);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(7);
|
||||
|
||||
XELOGD("XamReadTileToTexture(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", unk0, unk1,
|
||||
unk2, unk3, buffer_ptr, stride, height, overlapped_ptr);
|
||||
dword_result_t XamReadTileToTexture(dword_t unk1, dword_t unk2, dword_t unk3,
|
||||
dword_t unk4, lpvoid_t buffer_ptr,
|
||||
dword_t stride, dword_t height,
|
||||
dword_t overlapped_ptr) {
|
||||
// unk1: const?
|
||||
// unk2: out0 from XamParseGamerTileKey
|
||||
// unk3: some variant of out1/out2
|
||||
// unk4: const?
|
||||
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_SUCCESS);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamReadTileToTexture,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamWriteGamerTile_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t arg1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t arg2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t arg3 = SHIM_GET_ARG_32(3);
|
||||
uint32_t arg4 = SHIM_GET_ARG_32(4);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
|
||||
|
||||
XELOGD("XamWriteGamerTile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", arg0, arg1,
|
||||
arg2, arg3, arg4, overlapped_ptr);
|
||||
|
||||
dword_result_t XamWriteGamerTile(dword_t arg1, dword_t arg2, dword_t arg3,
|
||||
dword_t arg4, dword_t arg5,
|
||||
dword_t overlapped_ptr) {
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
kernel_state()->CompleteOverlappedImmediate(overlapped_ptr,
|
||||
X_ERROR_SUCCESS);
|
||||
return X_ERROR_IO_PENDING;
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamWriteGamerTile,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamSessionCreateHandle_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XamSessionCreateHandle(%.8X)", handle_ptr);
|
||||
|
||||
SHIM_SET_MEM_32(handle_ptr, 0xCAFEDEAD);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
dword_result_t XamSessionCreateHandle(lpdword_t handle_ptr) {
|
||||
*handle_ptr = 0xCAFEDEAD;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamSessionCreateHandle,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamSessionRefObjByHandle_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t obj_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XamSessionRefObjByHandle(%.8X, %.8X)", handle, obj_ptr);
|
||||
|
||||
dword_result_t XamSessionRefObjByHandle(dword_t handle, lpdword_t obj_ptr) {
|
||||
assert_true(handle == 0xCAFEDEAD);
|
||||
|
||||
SHIM_SET_MEM_32(obj_ptr, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_FUNCTION_FAILED);
|
||||
*obj_ptr = 0;
|
||||
return X_ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamSessionRefObjByHandle,
|
||||
ExportTag::kUserProfiles | ExportTag::kStub);
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
|
@ -662,22 +541,4 @@ SHIM_CALL XamSessionRefObjByHandle_shim(PPCContext* ppc_context,
|
|||
|
||||
void xe::kernel::xam::RegisterUserExports(
|
||||
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserGetXUID, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserGetSigninState, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserGetSigninInfo, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserGetName, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserReadProfileSettings, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserWriteProfileSettings, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserCheckPrivilege, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserContentRestrictionGetFlags, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserContentRestrictionGetRating, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserContentRestrictionCheckAccess, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserAreUsersFriends, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamShowSigninUI, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamUserCreateAchievementEnumerator, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamParseGamerTileKey, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamReadTileToTexture, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamWriteGamerTile, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamSessionCreateHandle, state);
|
||||
SHIM_SET_MAPPING("xam.xex", XamSessionRefObjByHandle, state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue