From 1e92a4e06c1077d034757253dc03ac564dbf2601 Mon Sep 17 00:00:00 2001 From: gibbed Date: Tue, 8 Aug 2017 04:53:01 -0500 Subject: [PATCH] XAM: Write as many items possible when enumerating. Fixes Nier not detecting system save data (and possibly other games). --- src/xenia/kernel/xam/xam_content.cc | 2 +- src/xenia/kernel/xam/xam_info.cc | 31 +++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index b34ecd9b6..8cfc54a59 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -173,7 +173,7 @@ dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id, } if (buffer_size_ptr) { - *buffer_size_ptr = (uint32_t)XCONTENT_DATA::kSize; + *buffer_size_ptr = (uint32_t)XCONTENT_DATA::kSize * max_count; } auto e = diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 698500456..604c8027a 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -199,23 +199,38 @@ dword_result_t XamEnumerate(dword_t handle, dword_t flags, lpvoid_t buffer, } buffer.Zero(buffer_length); - X_RESULT result = - e->WriteItem(buffer) ? X_ERROR_SUCCESS : X_ERROR_NO_MORE_FILES; + + X_RESULT result; + uint32_t item_count = 0; + + if (buffer_length < e->item_size()) { + result = X_ERROR_INSUFFICIENT_BUFFER; + } else if (e->current_item() >= e->item_count()) { + result = X_ERROR_NO_MORE_FILES; + } else { + auto item_buffer = buffer.as(); + auto max_items = buffer_length / e->item_size(); + while (max_items--) { + if (!e->WriteItem(item_buffer)) { + break; + } + item_buffer += e->item_size(); + item_count++; + } + result = X_ERROR_SUCCESS; + } // Return X_ERROR_NO_MORE_FILES in HRESULT form. - X_HRESULT extended_result = - result != 0 ? X_HRESULT_FROM_WIN32(X_ERROR_NO_MORE_FILES) : 0; + X_HRESULT extended_result = result != 0 ? X_HRESULT_FROM_WIN32(result) : 0; if (items_returned) { assert_true(!overlapped); - *items_returned = result == X_ERROR_SUCCESS ? 1 : 0; - + *items_returned = result == X_ERROR_SUCCESS ? item_count : 0; return result; } else if (overlapped) { assert_true(!items_returned); kernel_state()->CompleteOverlappedImmediateEx( overlapped, result, extended_result, - result == X_ERROR_SUCCESS ? e->item_count() : 0); - + result == X_ERROR_SUCCESS ? item_count : 0); return X_ERROR_IO_PENDING; } else { assert_always();