diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index ff9041fbd..4e2ca3370 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -2016,7 +2016,8 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, } draw_util::ViewportInfo viewport_info; draw_util::GetHostViewportInfo(regs, float(pixel_size_x), float(pixel_size_y), - true, float(D3D12_VIEWPORT_BOUNDS_MAX), false, + true, float(D3D12_VIEWPORT_BOUNDS_MAX), + float(D3D12_VIEWPORT_BOUNDS_MAX), false, viewport_info); draw_util::Scissor scissor; draw_util::GetScissor(regs, scissor); diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc index c78d5122a..29072c3e8 100644 --- a/src/xenia/gpu/draw_util.cc +++ b/src/xenia/gpu/draw_util.cc @@ -113,11 +113,12 @@ int32_t FloatToD3D11Fixed16p8(float f32) { void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, float pixel_size_y, bool origin_bottom_left, - float xy_max, bool allow_reverse_z, + float x_max, float y_max, bool allow_reverse_z, ViewportInfo& viewport_info_out) { assert_true(pixel_size_x >= 1.0f); assert_true(pixel_size_y >= 1.0f); - assert_true(xy_max >= 1.0f); + assert_true(x_max >= 1.0f); + assert_true(y_max >= 1.0f); // PA_CL_VTE_CNTL contains whether offsets and scales are enabled. // http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf @@ -167,9 +168,9 @@ void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, // Keep the viewport in the positive quarter-plane for simplicity of // clamping to the maximum supported bounds. float cutoff_left = std::fmax(-viewport_left, 0.0f); - float cutoff_right = std::fmax(viewport_right - xy_max, 0.0f); + float cutoff_right = std::fmax(viewport_right - x_max, 0.0f); viewport_left = std::fmax(viewport_left, 0.0f); - viewport_right = std::fmin(viewport_right, xy_max); + viewport_right = std::fmin(viewport_right, x_max); viewport_width = viewport_right - viewport_left; if (viewport_width > size_min) { ndc_scale_x = @@ -194,7 +195,7 @@ void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, // enabled, via the shader. viewport_left = 0.0f; viewport_width = std::min( - float(xenos::kTexture2DCubeMaxWidthHeight) * pixel_size_x, xy_max); + float(xenos::kTexture2DCubeMaxWidthHeight) * pixel_size_x, x_max); ndc_scale_x = (2.0f * pixel_size_x) / viewport_width; ndc_offset_x = viewport_offset_x * ndc_scale_x - 1.0f; } @@ -205,9 +206,9 @@ void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, viewport_top = viewport_offset_y * pixel_size_y - viewport_scale_y_abs; float viewport_bottom = viewport_top + viewport_scale_y_abs * 2.0f; float cutoff_top = std::fmax(-viewport_top, 0.0f); - float cutoff_bottom = std::fmax(viewport_bottom - xy_max, 0.0f); + float cutoff_bottom = std::fmax(viewport_bottom - y_max, 0.0f); viewport_top = std::fmax(viewport_top, 0.0f); - viewport_bottom = std::fmin(viewport_bottom, xy_max); + viewport_bottom = std::fmin(viewport_bottom, y_max); viewport_height = viewport_bottom - viewport_top; if (viewport_height > size_min) { ndc_scale_y = @@ -227,7 +228,7 @@ void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, } } else { viewport_height = std::min( - float(xenos::kTexture2DCubeMaxWidthHeight) * pixel_size_y, xy_max); + float(xenos::kTexture2DCubeMaxWidthHeight) * pixel_size_y, y_max); ndc_scale_y = (2.0f * pixel_size_y) / viewport_height; ndc_offset_y = viewport_offset_y * ndc_scale_y - 1.0f; } diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h index 2cee26de7..1a9798aeb 100644 --- a/src/xenia/gpu/draw_util.h +++ b/src/xenia/gpu/draw_util.h @@ -52,7 +52,7 @@ struct ViewportInfo { // Direct3D clip space with 0...W Z rather than -W...W. void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, float pixel_size_y, bool origin_bottom_left, - float xy_max, bool allow_reverse_z, + float x_max, float y_max, bool allow_reverse_z, ViewportInfo& viewport_info_out); struct Scissor { diff --git a/src/xenia/kernel/xam/user_profile.h b/src/xenia/kernel/xam/user_profile.h index a5c03f254..309d0e0f8 100644 --- a/src/xenia/kernel/xam/user_profile.h +++ b/src/xenia/kernel/xam/user_profile.h @@ -202,6 +202,7 @@ class UserProfile { uint64_t xuid() const { return xuid_; } std::string name() const { return name_; } uint32_t signin_state() const { return 1; } + uint32_t type() const { return 2; /* online profile? */ } void AddSetting(std::unique_ptr setting); Setting* GetSetting(uint32_t setting_id); diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 9cc2f1dce..8dc8ae492 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -25,25 +25,25 @@ namespace xam { X_HRESULT_result_t XamUserGetXUID(dword_t user_index, dword_t type_mask, lpqword_t xuid_ptr) { + assert_true(type_mask == 1 || type_mask == 2 || type_mask == 3 || + type_mask == 4 || type_mask == 7); if (!xuid_ptr) { return X_E_INVALIDARG; } - - assert_true(type_mask == 1 || type_mask == 2 || type_mask == 3 || - type_mask == 4 || type_mask == 7); uint32_t result = X_E_NO_SUCH_USER; uint64_t xuid = 0; if (user_index < 4) { if (user_index == 0) { const auto& user_profile = kernel_state()->user_profile(); - if (type_mask & (2 | 4)) { + auto type = user_profile->type() & type_mask; + if (type & (2 | 4)) { + // maybe online profile? xuid = user_profile->xuid(); result = X_E_SUCCESS; - } else if (type_mask & 1) { + } else if (type & 1) { + // maybe offline profile? xuid = user_profile->xuid(); result = X_E_SUCCESS; - } else { - result = X_E_INVALIDARG; } } } else { @@ -101,24 +101,44 @@ DECLARE_XAM_EXPORT1(XamUserGetSigninInfo, kUserProfiles, kImplemented); dword_result_t XamUserGetName(dword_t user_index, lpstring_t buffer, dword_t buffer_len) { - if (user_index) { - return X_ERROR_NO_SUCH_USER; + if (user_index >= 4) { + return X_E_INVALIDARG; } - if (!buffer_len) { - return X_ERROR_SUCCESS; + if (user_index) { + return X_E_NO_SUCH_USER; } const auto& user_profile = kernel_state()->user_profile(); const auto& user_name = user_profile->name(); - - // Real XAM will only copy a maximum of 15 characters out. xe::string_util::copy_truncating(buffer, user_name, - std::min(buffer_len.value(), uint32_t(15))); - return X_ERROR_SUCCESS; + std::min(buffer_len.value(), uint32_t(16))); + return X_E_SUCCESS; } DECLARE_XAM_EXPORT1(XamUserGetName, kUserProfiles, kImplemented); +dword_result_t XamUserGetGamerTag(dword_t user_index, lpu16string_t buffer, + dword_t buffer_len) { + if (user_index >= 4) { + return X_E_INVALIDARG; + } + + if (user_index) { + return X_E_NO_SUCH_USER; + } + + if (!buffer || buffer_len < 16) { + return X_E_INVALIDARG; + } + + const auto& user_profile = kernel_state()->user_profile(); + auto user_name = xe::to_utf16(user_profile->name()); + xe::string_util::copy_and_swap_truncating( + buffer, user_name, std::min(buffer_len.value(), uint32_t(16))); + return X_E_SUCCESS; +} +DECLARE_XAM_EXPORT1(XamUserGetGamerTag, kUserProfiles, kImplemented); + typedef struct { xe::be setting_count; xe::be settings_ptr; @@ -404,8 +424,15 @@ DECLARE_XAM_EXPORT1(XamUserWriteProfileSettings, kUserProfiles, kImplemented); dword_result_t XamUserCheckPrivilege(dword_t user_index, dword_t mask, lpdword_t out_value) { - if (user_index) { - return X_ERROR_NO_SUCH_USER; + // checking all users? + if (user_index != 0xFF) { + if (user_index >= 4) { + return X_ERROR_INVALID_PARAMETER; + } + + if (user_index) { + return X_ERROR_NO_SUCH_USER; + } } // If we deny everything, games should hopefully not try to do stuff. @@ -462,6 +489,17 @@ DECLARE_XAM_EXPORT1(XamUserContentRestrictionCheckAccess, kUserProfiles, kStub); dword_result_t XamUserIsOnlineEnabled(dword_t user_index) { return 1; } DECLARE_XAM_EXPORT1(XamUserIsOnlineEnabled, kUserProfiles, kStub); +dword_result_t XamUserGetMembershipTier(dword_t user_index) { + if (user_index >= 4) { + return X_ERROR_INVALID_PARAMETER; + } + if (user_index) { + return X_ERROR_NO_SUCH_USER; + } + return 6 /* 6 appears to be Gold */; +} +DECLARE_XAM_EXPORT1(XamUserGetMembershipTier, kUserProfiles, kStub); + dword_result_t XamUserAreUsersFriends(dword_t user_index, dword_t unk1, dword_t unk2, lpdword_t out_value, dword_t overlapped_ptr) {