diff --git a/src/xenia/kernel/xam_user.cc b/src/xenia/kernel/xam_user.cc index e1e015222..49cc87658 100644 --- a/src/xenia/kernel/xam_user.cc +++ b/src/xenia/kernel/xam_user.cc @@ -53,7 +53,68 @@ SHIM_CALL XamUserGetSigninState_shim( } -// XamUserReadProfileSettings +// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/xboxtools.cpp +SHIM_CALL XamUserReadProfileSettings_shim( + PPCContext* ppc_state, KernelState* 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); + // arg8 is in stack! + uint64_t sp = ppc_state->r[1]; + uint32_t overlapped_ptr = SHIM_MEM_32(sp - 16); + + uint32_t buffer_size = SHIM_MEM_32(buffer_size_ptr); + + XELOGD( + "XamUserReadProfileSettings(%d, %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); + + // Title ID = 0 means us. + XEASSERTZERO(title_id); + + // TODO(benvanik): implement overlapped support + XEASSERTZERO(overlapped_ptr); + + // First call asks for size (fill buffer_size_ptr). + // Second call asks for buffer contents with that size. + + // Result buffer is: + // uint32_t setting_count + // [repeated X_USER_PROFILE_SETTING structs] + + typedef union { + struct { + uint32_t id : 14; + uint32_t unk : 2; + uint32_t size : 12; + uint32_t type : 4; + }; + uint32_t value; + } x_profile_setting_t; + + // Compute sizes. + uint32_t size_needed = 4; + for (uint32_t n = 0; n < setting_count; n++) { + x_profile_setting_t setting; + setting.value = SHIM_MEM_32(setting_ids_ptr + n * 4); + size_needed += setting.size; + } + SHIM_SET_MEM_32(buffer_size_ptr, size_needed); + if (buffer_size < size_needed) { + SHIM_SET_RETURN(X_ERROR_INSUFFICIENT_BUFFER); + return; + } + + // TODO(benvanik): read profile data. + // For now, just return signed out. + SHIM_SET_RETURN(X_ERROR_NOT_FOUND); +} } // namespace kernel @@ -64,4 +125,5 @@ void xe::kernel::xam::RegisterUserExports( ExportResolver* export_resolver, KernelState* state) { SHIM_SET_MAPPING("xam.xex", XamUserGetXUID, state); SHIM_SET_MAPPING("xam.xex", XamUserGetSigninState, state); + SHIM_SET_MAPPING("xam.xex", XamUserReadProfileSettings, state); } diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 8e679192e..6f1d23d50 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -54,11 +54,13 @@ typedef uint32_t X_STATUS; // Adding as needed. typedef uint32_t X_RESULT; #define X_ERROR_SUCCESS ((uint32_t)0x00000000L) -#define X_ERROR_ACCESS_DENIED ((uint32_t)0x80070005L) -#define X_ERROR_BAD_ARGUMENTS ((uint32_t)0x800700A0L) -#define X_ERROR_BUSY ((uint32_t)0x800700AAL) -#define X_ERROR_DEVICE_NOT_CONNECTED ((uint32_t)0x8007048FL) -#define X_ERROR_CANCELLED ((uint32_t)0x800704C7L) +#define X_ERROR_ACCESS_DENIED ((uint32_t)0x00000005L) +#define X_ERROR_INSUFFICIENT_BUFFER ((uint32_t)0x0000007AL) +#define X_ERROR_BAD_ARGUMENTS ((uint32_t)0x000000A0L) +#define X_ERROR_BUSY ((uint32_t)0x000000AAL) +#define X_ERROR_DEVICE_NOT_CONNECTED ((uint32_t)0x0000048FL) +#define X_ERROR_NOT_FOUND ((uint32_t)0x00000490L) +#define X_ERROR_CANCELLED ((uint32_t)0x000004C7L) #define X_ERROR_EMPTY ((uint32_t)0x000010D2L) // MEM_*, used by NtAllocateVirtualMemory