From a7f1a3f18a53f67528e5601f33600b2ec69635e4 Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Wed, 25 Feb 2026 21:46:01 +0000 Subject: [PATCH] [XAM] Added profile and create content enumerator wrappers --- src/xenia/kernel/xam/xam_content.cc | 8 ++--- src/xenia/kernel/xam/xam_enum.cc | 9 ++--- src/xenia/kernel/xenumerator.cc | 51 ++++++++++++++++++++++++++++- src/xenia/kernel/xenumerator.h | 42 +++++++++++++++++++++++- 4 files changed, 98 insertions(+), 12 deletions(-) diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index c7e48da4e..10d27268b 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -157,8 +157,9 @@ dword_result_t XamContentCreateEnumerator_entry( xuid = user->xuid(); } - auto e = make_object>(kernel_state(), - items_per_enumerate); + auto e = object_ref( + new ContentEnumerator(kernel_state(), items_per_enumerate)); + auto result = e->Initialize(XUserIndexAny, 0xFE, 0x20005, 0x20007, 0); if (XFAILED(result)) { return result; @@ -206,8 +207,7 @@ dword_result_t XamContentCreateEnumerator_entry( } for (const auto& content_data : enumerated_content) { - auto item = e->AppendItem(); - *item = content_data; + e->AppendItem(content_data); XELOGI("{}: Adding: {} (Filename: {}) to enumerator result", __func__, xe::to_utf8(content_data.display_name()), content_data.file_name()); } diff --git a/src/xenia/kernel/xam/xam_enum.cc b/src/xenia/kernel/xam/xam_enum.cc index a80431caf..1a5afb370 100644 --- a/src/xenia/kernel/xam/xam_enum.cc +++ b/src/xenia/kernel/xam/xam_enum.cc @@ -165,7 +165,8 @@ dword_result_t XamProfileCreateEnumerator_entry(dword_t device_id, return X_ERROR_INVALID_PARAMETER; } - auto e = new XStaticEnumerator(kernel_state(), 1); + auto e = + object_ref(new ProfileEnumerator(kernel_state(), 1)); auto result = e->Initialize(XUserIndexAny, 0xFE, 0x23001, 0x23003, 0, 0x28, nullptr); @@ -178,11 +179,7 @@ dword_result_t XamProfileCreateEnumerator_entry(dword_t device_id, kernel_state()->xam_state()->profile_manager()->GetAccounts(); for (const auto& [xuid, account] : *accounts) { - X_PROFILEENUMRESULT* profile = e->AppendItem(); - - profile->xuid_offline = xuid; - profile->device_id = 1; - memcpy(&profile->account, &account, sizeof(X_XAMACCOUNTINFO)); + e->AppendItem({xuid, account, 1}); } *handle_ptr = e->handle(); diff --git a/src/xenia/kernel/xenumerator.cc b/src/xenia/kernel/xenumerator.cc index e55b4200c..e3c17a760 100644 --- a/src/xenia/kernel/xenumerator.cc +++ b/src/xenia/kernel/xenumerator.cc @@ -68,7 +68,6 @@ uint32_t XStaticUntypedEnumerator::WriteItems(uint8_t* buffer_data, return X_ERROR_NO_MORE_FILES; } - // 4E4D07F0 does not respect buffer_size for XContentCreateEnumerator. assert_false(buffer_size < item_size()); const size_t available_count = buffer_size / item_size(); @@ -215,6 +214,8 @@ uint32_t XMPCreateUserPlaylistEnumerator::WriteItems(uint8_t* buffer_data, std::copy_n(items_.begin() + current_item_, valid_count, results); + current_item_ += valid_count; + if (written_count) { *written_count = static_cast(valid_count); } @@ -222,5 +223,53 @@ uint32_t XMPCreateUserPlaylistEnumerator::WriteItems(uint8_t* buffer_data, return X_ERROR_SUCCESS; } +uint32_t ProfileEnumerator::WriteItems(uint8_t* buffer_data, + uint32_t buffer_size, + uint32_t* written_count) { + const size_t actual_count = + std::min(items_.size() - current_item_, items_per_enumerate()); + if (!actual_count) { + return X_ERROR_NO_MORE_FILES; + } + + // FFFE07D1 provides buffer_size of 0. + xam::X_PROFILEENUMRESULT* profiles = + reinterpret_cast(buffer_data); + + std::copy_n(items_.begin() + current_item_, actual_count, profiles); + + current_item_ += actual_count; + + if (written_count) { + *written_count = static_cast(actual_count); + } + + return X_ERROR_SUCCESS; +} + +uint32_t ContentEnumerator::WriteItems(uint8_t* buffer_data, + uint32_t buffer_size, + uint32_t* written_count) { + const size_t actual_count = + std::min(items_.size() - current_item_, items_per_enumerate()); + if (!actual_count) { + return X_ERROR_NO_MORE_FILES; + } + + // 4E4D07F0 does not respect buffer_size, possibly bug? + xam::XCONTENT_DATA* contents = + reinterpret_cast(buffer_data); + + std::copy_n(items_.begin() + current_item_, actual_count, contents); + + current_item_ += actual_count; + + if (written_count) { + *written_count = static_cast(actual_count); + } + + return X_ERROR_SUCCESS; +} + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xenumerator.h b/src/xenia/kernel/xenumerator.h index 7f8a8b8a7..816a1e840 100644 --- a/src/xenia/kernel/xenumerator.h +++ b/src/xenia/kernel/xenumerator.h @@ -13,6 +13,7 @@ #include #include "xenia/kernel/xam/achievement_manager.h" +#include "xenia/kernel/xam/content_manager.h" #include "xenia/kernel/xam/user_tracker.h" #include "xenia/kernel/xam/xam.h" #include "xenia/kernel/xobject.h" @@ -224,7 +225,8 @@ class XMPCreateUserPlaylistEnumerator : public XEnumerator { public: XMPCreateUserPlaylistEnumerator(KernelState* kernel_state, size_t items_per_enumerate) - : XEnumerator(kernel_state, items_per_enumerate, 0) {} + : XEnumerator(kernel_state, items_per_enumerate, + sizeof(xam::XMP_USER_PLAYLIST_INFO)) {} size_t item_count() const { return items_.size(); } @@ -240,6 +242,44 @@ class XMPCreateUserPlaylistEnumerator : public XEnumerator { size_t current_item_ = 0; }; +class ProfileEnumerator : public XEnumerator { + public: + ProfileEnumerator(KernelState* kernel_state, size_t items_per_enumerate) + : XEnumerator(kernel_state, items_per_enumerate, + sizeof(xam::X_PROFILEENUMRESULT)) {} + + size_t item_count() const { return items_.size(); } + + void AppendItem(const xam::X_PROFILEENUMRESULT& item) { + items_.push_back(item); + } + + uint32_t WriteItems(uint8_t* buffer_data, uint32_t buffer_size, + uint32_t* written_count) override; + + private: + std::vector items_; + size_t current_item_ = 0; +}; + +class ContentEnumerator : public XEnumerator { + public: + ContentEnumerator(KernelState* kernel_state, size_t items_per_enumerate) + : XEnumerator(kernel_state, items_per_enumerate, + sizeof(xam::XCONTENT_DATA)) {} + + size_t item_count() const { return items_.size(); } + + void AppendItem(const xam::XCONTENT_DATA& item) { items_.push_back(item); } + + uint32_t WriteItems(uint8_t* buffer_data, uint32_t buffer_size, + uint32_t* written_count) override; + + private: + std::vector items_; + size_t current_item_ = 0; +}; + } // namespace kernel } // namespace xe