[XAM] Stubbed XMPCreateUserPlaylistEnumerator
Fixed 545408C0 freezing at main menu.
This commit is contained in:
@@ -329,6 +329,17 @@ enum class UserContextDevice : uint32_t {
|
|||||||
Microphone = 4,
|
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 xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|||||||
@@ -79,20 +79,63 @@ dword_result_t XamEnumerate_entry(dword_t handle, dword_t flags,
|
|||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamEnumerate, kNone, kImplemented);
|
DECLARE_XAM_EXPORT1(XamEnumerate, kNone, kImplemented);
|
||||||
|
|
||||||
dword_result_t XamCreateEnumeratorHandle_entry(
|
static uint32_t XMPCreateUserPlaylistEnumeratorHandle(
|
||||||
dword_t user_index, dword_t app_id, dword_t open_message,
|
uint32_t user_index, uint32_t app_id, uint32_t open_message,
|
||||||
dword_t close_message, dword_t extra_size, dword_t item_count,
|
uint32_t close_message, uint32_t extra_size, uint32_t item_count,
|
||||||
dword_t flags, lpdword_t out_handle) {
|
uint32_t flags, uint32_t& out_enum_handle) {
|
||||||
auto e = object_ref<XStaticUntypedEnumerator>(
|
auto e = object_ref<XMPCreateUserPlaylistEnumerator>(
|
||||||
new XStaticUntypedEnumerator(kernel_state(), item_count, extra_size));
|
new XMPCreateUserPlaylistEnumerator(kernel_state(), item_count));
|
||||||
|
|
||||||
auto result = e->Initialize(user_index, app_id, open_message, close_message,
|
auto result = e->Initialize(user_index, app_id, open_message, close_message,
|
||||||
flags, extra_size, nullptr);
|
flags, extra_size, nullptr);
|
||||||
|
|
||||||
if (XFAILED(result)) {
|
if (XFAILED(result)) {
|
||||||
return 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;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamCreateEnumeratorHandle, kNone, kImplemented);
|
DECLARE_XAM_EXPORT1(XamCreateEnumeratorHandle, kNone, kImplemented);
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ X_STATUS XEnumerator::Initialize(uint32_t user_index, uint32_t app_id,
|
|||||||
*extra_buffer =
|
*extra_buffer =
|
||||||
!extra_buffer ? nullptr : &native_object[sizeof(X_KENUMERATOR)];
|
!extra_buffer ? nullptr : &native_object[sizeof(X_KENUMERATOR)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extra_size_ = extra_size;
|
||||||
return X_STATUS_SUCCESS;
|
return X_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,5 +177,31 @@ uint32_t XUserStatsEnumerator::WriteItems(uint32_t buffer_ptr,
|
|||||||
return X_ERROR_SUCCESS;
|
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 kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "xenia/kernel/xam/achievement_manager.h"
|
#include "xenia/kernel/xam/achievement_manager.h"
|
||||||
#include "xenia/kernel/xam/user_tracker.h"
|
#include "xenia/kernel/xam/user_tracker.h"
|
||||||
|
#include "xenia/kernel/xam/xam.h"
|
||||||
#include "xenia/kernel/xobject.h"
|
#include "xenia/kernel/xobject.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
@@ -89,10 +90,12 @@ class XEnumerator : public XObject {
|
|||||||
|
|
||||||
size_t item_size() const { return item_size_; }
|
size_t item_size() const { return item_size_; }
|
||||||
size_t items_per_enumerate() const { return items_per_enumerate_; }
|
size_t items_per_enumerate() const { return items_per_enumerate_; }
|
||||||
|
size_t extra_size() const { return extra_size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t items_per_enumerate_;
|
size_t items_per_enumerate_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
|
size_t extra_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XStaticUntypedEnumerator : public XEnumerator {
|
class XStaticUntypedEnumerator : public XEnumerator {
|
||||||
@@ -219,6 +222,26 @@ class XUserStatsEnumerator : public XEnumerator {
|
|||||||
size_t current_item_ = 0;
|
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 kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user