Skip to content

Commit 10bfc92

Browse files
AdrianCassarGliniak
authored andcommitted
[XAM] Stubbed XMPCreateUserPlaylistEnumerator
Fixed 545408C0 freezing at main menu.
1 parent 2997b91 commit 10bfc92

File tree

4 files changed

+110
-5
lines changed

4 files changed

+110
-5
lines changed

src/xenia/kernel/xam/xam.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,17 @@ enum class UserContextDevice : uint32_t {
329329
Microphone = 4,
330330
};
331331

332+
constexpr uint32_t XMP_MAX_METADATA_STRING = 40;
333+
constexpr uint32_t XMP_MAX_USER_PLAYLIST_ID = 572;
334+
constexpr uint32_t XMP_USER_PLAYLIST_RESERVED_FIELD_SIZE = 168;
335+
336+
struct XMP_USER_PLAYLIST_INFO {
337+
uint8_t id[XMP_MAX_USER_PLAYLIST_ID];
338+
xe::be<char16_t> title[XMP_MAX_METADATA_STRING];
339+
uint8_t reserved[XMP_USER_PLAYLIST_RESERVED_FIELD_SIZE];
340+
};
341+
static_assert_size(XMP_USER_PLAYLIST_INFO, 0x334);
342+
332343
} // namespace xam
333344
} // namespace kernel
334345
} // namespace xe

src/xenia/kernel/xam/xam_enum.cc

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,63 @@ dword_result_t XamEnumerate_entry(dword_t handle, dword_t flags,
7979
}
8080
DECLARE_XAM_EXPORT1(XamEnumerate, kNone, kImplemented);
8181

82+
static uint32_t XMPCreateUserPlaylistEnumeratorHandle(
83+
uint32_t user_index, uint32_t app_id, uint32_t open_message,
84+
uint32_t close_message, uint32_t extra_size, uint32_t item_count,
85+
uint32_t flags, uint32_t& out_enum_handle) {
86+
auto e = object_ref<XMPCreateUserPlaylistEnumerator>(
87+
new XMPCreateUserPlaylistEnumerator(kernel_state(), item_count));
88+
89+
auto result = e->Initialize(user_index, app_id, open_message, close_message,
90+
flags, extra_size, nullptr);
91+
92+
if (XFAILED(result)) {
93+
return result;
94+
}
95+
96+
std::vector<xam::XMP_USER_PLAYLIST_INFO> user_playlist_info = {};
97+
98+
for (const auto& playlist_info : user_playlist_info) {
99+
e->AppendItem(playlist_info);
100+
}
101+
102+
XELOGI("{}: added {} items to enumerator", __func__, e->item_count());
103+
104+
out_enum_handle = e->handle();
105+
return X_ERROR_SUCCESS;
106+
}
107+
108+
constexpr uint32_t XMPCreateUserPlaylistEnumeratorMessage = 0x70026;
109+
82110
dword_result_t XamCreateEnumeratorHandle_entry(
83111
dword_t user_index, dword_t app_id, dword_t open_message,
84112
dword_t close_message, dword_t extra_size, dword_t item_count,
85113
dword_t flags, lpdword_t out_handle) {
86-
auto e = object_ref<XStaticUntypedEnumerator>(
87-
new XStaticUntypedEnumerator(kernel_state(), item_count, extra_size));
114+
uint32_t enum_handle = 0;
115+
X_STATUS result = 0;
116+
117+
switch (open_message) {
118+
case XMPCreateUserPlaylistEnumeratorMessage: {
119+
result = XMPCreateUserPlaylistEnumeratorHandle(
120+
user_index, app_id, open_message, close_message, extra_size,
121+
item_count, flags, enum_handle);
122+
} break;
123+
default: {
124+
auto e = object_ref<XStaticUntypedEnumerator>(
125+
new XStaticUntypedEnumerator(kernel_state(), item_count, extra_size));
126+
127+
result = e->Initialize(user_index, app_id, open_message, close_message,
128+
flags, extra_size, nullptr);
129+
enum_handle = e->handle();
130+
} break;
131+
}
88132

89-
auto result = e->Initialize(user_index, app_id, open_message, close_message,
90-
flags, extra_size, nullptr);
91133
if (XFAILED(result)) {
92134
return result;
93135
}
94136

95-
*out_handle = e->handle();
137+
*out_handle = enum_handle;
138+
96139
return X_ERROR_SUCCESS;
97140
}
98141
DECLARE_XAM_EXPORT1(XamCreateEnumeratorHandle, kNone, kImplemented);

src/xenia/kernel/xenumerator.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ X_STATUS XEnumerator::Initialize(uint32_t user_index, uint32_t app_id,
4040
*extra_buffer =
4141
!extra_buffer ? nullptr : &native_object[sizeof(X_KENUMERATOR)];
4242
}
43+
44+
extra_size_ = extra_size;
4345
return X_STATUS_SUCCESS;
4446
}
4547

@@ -175,5 +177,31 @@ uint32_t XUserStatsEnumerator::WriteItems(uint32_t buffer_ptr,
175177
return X_ERROR_SUCCESS;
176178
}
177179

180+
uint32_t XMPCreateUserPlaylistEnumerator::WriteItems(uint32_t buffer_ptr,
181+
uint8_t* buffer_data,
182+
uint32_t* written_count) {
183+
// Fixed 545408C0 freezing at main menu.
184+
std::memset(buffer_data, 0, extra_size());
185+
186+
size_t count = std::min(items_.size() - current_item_, items_per_enumerate());
187+
if (!count) {
188+
return X_ERROR_NO_MORE_FILES;
189+
}
190+
191+
xam::XMP_USER_PLAYLIST_INFO* results =
192+
reinterpret_cast<xam::XMP_USER_PLAYLIST_INFO*>(buffer_data);
193+
194+
for (size_t i = 0, o = current_item_; i < count; ++i, ++current_item_) {
195+
const auto& item = items_[current_item_];
196+
results[i] = item;
197+
}
198+
199+
if (written_count) {
200+
*written_count = static_cast<uint32_t>(count);
201+
}
202+
203+
return X_ERROR_SUCCESS;
204+
}
205+
178206
} // namespace kernel
179207
} // namespace xe

src/xenia/kernel/xenumerator.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "xenia/kernel/xam/achievement_manager.h"
1616
#include "xenia/kernel/xam/user_tracker.h"
17+
#include "xenia/kernel/xam/xam.h"
1718
#include "xenia/kernel/xobject.h"
1819

1920
namespace xe {
@@ -89,10 +90,12 @@ class XEnumerator : public XObject {
8990

9091
size_t item_size() const { return item_size_; }
9192
size_t items_per_enumerate() const { return items_per_enumerate_; }
93+
size_t extra_size() const { return extra_size_; }
9294

9395
private:
9496
size_t items_per_enumerate_;
9597
size_t item_size_;
98+
size_t extra_size_;
9699
};
97100

98101
class XStaticUntypedEnumerator : public XEnumerator {
@@ -219,6 +222,26 @@ class XUserStatsEnumerator : public XEnumerator {
219222
size_t current_item_ = 0;
220223
};
221224

225+
class XMPCreateUserPlaylistEnumerator : public XEnumerator {
226+
public:
227+
XMPCreateUserPlaylistEnumerator(KernelState* kernel_state,
228+
size_t items_per_enumerate)
229+
: XEnumerator(kernel_state, items_per_enumerate, 0) {}
230+
231+
size_t item_count() const { return items_.size(); }
232+
233+
void AppendItem(const xam::XMP_USER_PLAYLIST_INFO& item) {
234+
items_.push_back(item);
235+
}
236+
237+
uint32_t WriteItems(uint32_t buffer_ptr, uint8_t* buffer_data,
238+
uint32_t* written_count) override;
239+
240+
private:
241+
std::vector<xam::XMP_USER_PLAYLIST_INFO> items_;
242+
size_t current_item_ = 0;
243+
};
244+
222245
} // namespace kernel
223246
} // namespace xe
224247

0 commit comments

Comments
 (0)