[XAM] Stubbed XMPCreateUserPlaylistEnumerator

Fixed 545408C0 freezing at main menu.
This commit is contained in:
Adrian
2025-11-28 14:35:36 +00:00
committed by Radosław Gliński
parent 2997b91493
commit 10bfc92d9a
4 changed files with 112 additions and 7 deletions

View File

@@ -329,6 +329,17 @@ enum class UserContextDevice : uint32_t {
Microphone = 4,
};
constexpr uint32_t XMP_MAX_METADATA_STRING = 40;
constexpr uint32_t XMP_MAX_USER_PLAYLIST_ID = 572;
constexpr uint32_t XMP_USER_PLAYLIST_RESERVED_FIELD_SIZE = 168;
struct XMP_USER_PLAYLIST_INFO {
uint8_t id[XMP_MAX_USER_PLAYLIST_ID];
xe::be<char16_t> title[XMP_MAX_METADATA_STRING];
uint8_t reserved[XMP_USER_PLAYLIST_RESERVED_FIELD_SIZE];
};
static_assert_size(XMP_USER_PLAYLIST_INFO, 0x334);
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@@ -79,20 +79,63 @@ dword_result_t XamEnumerate_entry(dword_t handle, dword_t flags,
}
DECLARE_XAM_EXPORT1(XamEnumerate, kNone, kImplemented);
dword_result_t XamCreateEnumeratorHandle_entry(
dword_t user_index, dword_t app_id, dword_t open_message,
dword_t close_message, dword_t extra_size, dword_t item_count,
dword_t flags, lpdword_t out_handle) {
auto e = object_ref<XStaticUntypedEnumerator>(
new XStaticUntypedEnumerator(kernel_state(), item_count, extra_size));
static uint32_t XMPCreateUserPlaylistEnumeratorHandle(
uint32_t user_index, uint32_t app_id, uint32_t open_message,
uint32_t close_message, uint32_t extra_size, uint32_t item_count,
uint32_t flags, uint32_t& out_enum_handle) {
auto e = object_ref<XMPCreateUserPlaylistEnumerator>(
new XMPCreateUserPlaylistEnumerator(kernel_state(), item_count));
auto result = e->Initialize(user_index, app_id, open_message, close_message,
flags, extra_size, nullptr);
if (XFAILED(result)) {
return result;
}
*out_handle = e->handle();
std::vector<xam::XMP_USER_PLAYLIST_INFO> user_playlist_info = {};
for (const auto& playlist_info : user_playlist_info) {
e->AppendItem(playlist_info);
}
XELOGI("{}: added {} items to enumerator", __func__, e->item_count());
out_enum_handle = e->handle();
return X_ERROR_SUCCESS;
}
constexpr uint32_t XMPCreateUserPlaylistEnumeratorMessage = 0x70026;
dword_result_t XamCreateEnumeratorHandle_entry(
dword_t user_index, dword_t app_id, dword_t open_message,
dword_t close_message, dword_t extra_size, dword_t item_count,
dword_t flags, lpdword_t out_handle) {
uint32_t enum_handle = 0;
X_STATUS result = 0;
switch (open_message) {
case XMPCreateUserPlaylistEnumeratorMessage: {
result = XMPCreateUserPlaylistEnumeratorHandle(
user_index, app_id, open_message, close_message, extra_size,
item_count, flags, enum_handle);
} break;
default: {
auto e = object_ref<XStaticUntypedEnumerator>(
new XStaticUntypedEnumerator(kernel_state(), item_count, extra_size));
result = e->Initialize(user_index, app_id, open_message, close_message,
flags, extra_size, nullptr);
enum_handle = e->handle();
} break;
}
if (XFAILED(result)) {
return result;
}
*out_handle = enum_handle;
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamCreateEnumeratorHandle, kNone, kImplemented);

View File

@@ -40,6 +40,8 @@ X_STATUS XEnumerator::Initialize(uint32_t user_index, uint32_t app_id,
*extra_buffer =
!extra_buffer ? nullptr : &native_object[sizeof(X_KENUMERATOR)];
}
extra_size_ = extra_size;
return X_STATUS_SUCCESS;
}
@@ -175,5 +177,31 @@ uint32_t XUserStatsEnumerator::WriteItems(uint32_t buffer_ptr,
return X_ERROR_SUCCESS;
}
uint32_t XMPCreateUserPlaylistEnumerator::WriteItems(uint32_t buffer_ptr,
uint8_t* buffer_data,
uint32_t* written_count) {
// Fixed 545408C0 freezing at main menu.
std::memset(buffer_data, 0, extra_size());
size_t count = std::min(items_.size() - current_item_, items_per_enumerate());
if (!count) {
return X_ERROR_NO_MORE_FILES;
}
xam::XMP_USER_PLAYLIST_INFO* results =
reinterpret_cast<xam::XMP_USER_PLAYLIST_INFO*>(buffer_data);
for (size_t i = 0, o = current_item_; i < count; ++i, ++current_item_) {
const auto& item = items_[current_item_];
results[i] = item;
}
if (written_count) {
*written_count = static_cast<uint32_t>(count);
}
return X_ERROR_SUCCESS;
}
} // namespace kernel
} // namespace xe

View File

@@ -14,6 +14,7 @@
#include "xenia/kernel/xam/achievement_manager.h"
#include "xenia/kernel/xam/user_tracker.h"
#include "xenia/kernel/xam/xam.h"
#include "xenia/kernel/xobject.h"
namespace xe {
@@ -89,10 +90,12 @@ class XEnumerator : public XObject {
size_t item_size() const { return item_size_; }
size_t items_per_enumerate() const { return items_per_enumerate_; }
size_t extra_size() const { return extra_size_; }
private:
size_t items_per_enumerate_;
size_t item_size_;
size_t extra_size_;
};
class XStaticUntypedEnumerator : public XEnumerator {
@@ -219,6 +222,26 @@ class XUserStatsEnumerator : public XEnumerator {
size_t current_item_ = 0;
};
class XMPCreateUserPlaylistEnumerator : public XEnumerator {
public:
XMPCreateUserPlaylistEnumerator(KernelState* kernel_state,
size_t items_per_enumerate)
: XEnumerator(kernel_state, items_per_enumerate, 0) {}
size_t item_count() const { return items_.size(); }
void AppendItem(const xam::XMP_USER_PLAYLIST_INFO& item) {
items_.push_back(item);
}
uint32_t WriteItems(uint32_t buffer_ptr, uint8_t* buffer_data,
uint32_t* written_count) override;
private:
std::vector<xam::XMP_USER_PLAYLIST_INFO> items_;
size_t current_item_ = 0;
};
} // namespace kernel
} // namespace xe