diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index a49cd0f5e..075389d33 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -318,12 +318,17 @@ void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) { } } -void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, - uint32_t length) { +void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result) { + CompleteOverlappedEx(overlapped_ptr, result, result, 0); +} + +void KernelState::CompleteOverlappedEx(uint32_t overlapped_ptr, X_RESULT result, + uint32_t extended_error, + uint32_t length) { auto ptr = memory()->TranslateVirtual(overlapped_ptr); XOverlappedSetResult(ptr, result); + XOverlappedSetExtendedError(ptr, extended_error); XOverlappedSetLength(ptr, length); - XOverlappedSetExtendedError(ptr, result); X_HANDLE event_handle = XOverlappedGetEvent(ptr); if (event_handle) { XEvent* ev = nullptr; @@ -347,11 +352,17 @@ void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, } void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr, - X_RESULT result, - uint32_t length) { + X_RESULT result) { + CompleteOverlappedImmediateEx(overlapped_ptr, result, result, 0); +} + +void KernelState::CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, + X_RESULT result, + uint32_t extended_error, + uint32_t length) { auto ptr = memory()->TranslateVirtual(overlapped_ptr); XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle()); - CompleteOverlapped(overlapped_ptr, result, length); + CompleteOverlappedEx(overlapped_ptr, result, extended_error, length); } } // namespace kernel diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index f718b182f..5e705eb08 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -85,10 +85,12 @@ class KernelState { void UnregisterNotifyListener(XNotifyListener* listener); void BroadcastNotification(XNotificationID id, uint32_t data); - void CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, - uint32_t length = 0); - void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result, - uint32_t length = 0); + void CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result); + void CompleteOverlappedEx(uint32_t overlapped_ptr, X_RESULT result, + uint32_t extended_error, uint32_t length); + void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result); + void CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, X_RESULT result, + uint32_t extended_error, uint32_t length); private: Emulator* emulator_; diff --git a/src/xenia/kernel/xam_content.cc b/src/xenia/kernel/xam_content.cc index f7c92322f..de173c79e 100644 --- a/src/xenia/kernel/xam_content.cc +++ b/src/xenia/kernel/xam_content.cc @@ -116,10 +116,9 @@ SHIM_CALL XamContentGetDeviceState_shim(PPCContext* ppc_state, if ((device_id & 0xFFFF0000) != dummy_device_info_.device_id) { if (overlapped_ptr) { - state->CompleteOverlappedImmediate(overlapped_ptr, - X_ERROR_FUNCTION_FAILED); - XOverlappedSetExtendedError(SHIM_MEM_BASE + overlapped_ptr, - X_ERROR_DEVICE_NOT_CONNECTED); + state->CompleteOverlappedImmediateEx(overlapped_ptr, + X_ERROR_FUNCTION_FAILED, + X_ERROR_DEVICE_NOT_CONNECTED, 0); SHIM_SET_RETURN_32(X_ERROR_IO_PENDING); } else { SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); @@ -292,12 +291,13 @@ void XamContentCreateCore(PPCContext* ppc_state, KernelState* state, break; } + uint32_t disposition = create ? 1 : 2; if (disposition_ptr) { if (overlapped_ptr) { // If async always set to zero, but don't set to a real value. SHIM_SET_MEM_32(disposition_ptr, 0); } else { - SHIM_SET_MEM_32(disposition_ptr, create ? 1 : 2); + SHIM_SET_MEM_32(disposition_ptr, disposition); } } @@ -308,7 +308,8 @@ void XamContentCreateCore(PPCContext* ppc_state, KernelState* state, } if (overlapped_ptr) { - state->CompleteOverlappedImmediate(overlapped_ptr, result); + state->CompleteOverlappedImmediateEx(overlapped_ptr, disposition, result, + 0); SHIM_SET_RETURN_32(X_ERROR_IO_PENDING); } else { SHIM_SET_RETURN_32(result); diff --git a/src/xenia/kernel/xam_info.cc b/src/xenia/kernel/xam_info.cc index 9411fafa9..1976b2cf7 100644 --- a/src/xenia/kernel/xam_info.cc +++ b/src/xenia/kernel/xam_info.cc @@ -175,7 +175,8 @@ SHIM_CALL XamEnumerate_shim(PPCContext* ppc_state, KernelState* state) { SHIM_SET_MEM_32(item_count_ptr, item_count); } else if (overlapped_ptr) { assert_zero(item_count_ptr); - state->CompleteOverlappedImmediate(overlapped_ptr, result, item_count); + state->CompleteOverlappedImmediateEx(overlapped_ptr, result, result, + item_count); result = X_ERROR_IO_PENDING; } else { assert_always(); diff --git a/src/xenia/kernel/xam_user.cc b/src/xenia/kernel/xam_user.cc index d180e8592..b4aa0d57f 100644 --- a/src/xenia/kernel/xam_user.cc +++ b/src/xenia/kernel/xam_user.cc @@ -236,7 +236,14 @@ SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_state, user_index, unknown, setting_count, settings_ptr, overlapped_ptr); if (!setting_count || !settings_ptr) { - SHIM_SET_RETURN_32(X_ERROR_INVALID_PARAMETER); + if (overlapped_ptr) { + 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); + } + return; } if (user_index == 255) { diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 0dc52f471..a9aa33fee 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -212,10 +212,18 @@ enum X_FILE_INFORMATION_CLASS { XFileMaximumInformation }; +inline uint32_t XOverlappedGetResult(void* ptr) { + auto p = reinterpret_cast(ptr); + return xe::load_and_swap(&p[0]); +} inline void XOverlappedSetResult(void* ptr, uint32_t value) { auto p = reinterpret_cast(ptr); xe::store_and_swap(&p[0], value); } +inline uint32_t XOverlappedGetLength(void* ptr) { + auto p = reinterpret_cast(ptr); + return xe::load_and_swap(&p[1]); +} inline void XOverlappedSetLength(void* ptr, uint32_t value) { auto p = reinterpret_cast(ptr); xe::store_and_swap(&p[1], value);