160 lines
5.6 KiB
C++
160 lines
5.6 KiB
C++
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2022 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "xenia/base/logging.h"
|
|
#include "xenia/base/math.h"
|
|
#include "xenia/base/string_util.h"
|
|
#include "xenia/kernel/kernel_state.h"
|
|
#include "xenia/kernel/user_module.h"
|
|
#include "xenia/kernel/util/shim_utils.h"
|
|
#include "xenia/kernel/xam/xam_content_device.h"
|
|
#include "xenia/kernel/xam/xam_private.h"
|
|
#include "xenia/kernel/xenumerator.h"
|
|
#include "xenia/vfs/file.h"
|
|
#include "xenia/xbox.h"
|
|
|
|
namespace xe {
|
|
namespace kernel {
|
|
namespace xam {
|
|
|
|
void AddODDContentTest(object_ref<XStaticEnumerator<XCONTENT_AGGREGATE_DATA>> e,
|
|
XContentType content_type) {
|
|
auto root_entry = kernel_state()->file_system()->ResolvePath(
|
|
"GAME:\\Content\\0000000000000000");
|
|
if (!root_entry) {
|
|
return;
|
|
}
|
|
|
|
auto content_type_path = fmt::format("{:08X}", uint32_t(content_type));
|
|
|
|
xe::filesystem::WildcardEngine title_find_engine;
|
|
title_find_engine.SetRule("????????");
|
|
|
|
xe::filesystem::WildcardEngine content_find_engine;
|
|
content_find_engine.SetRule("????????????????");
|
|
|
|
size_t title_find_index = 0;
|
|
vfs::Entry* title_entry;
|
|
for (;;) {
|
|
title_entry =
|
|
root_entry->IterateChildren(title_find_engine, &title_find_index);
|
|
if (!title_entry) {
|
|
break;
|
|
}
|
|
|
|
auto title_id =
|
|
string_util::from_string<uint32_t>(title_entry->name(), true);
|
|
|
|
auto content_root_entry = title_entry->ResolvePath(content_type_path);
|
|
if (content_root_entry) {
|
|
size_t content_find_index = 0;
|
|
vfs::Entry* content_entry;
|
|
for (;;) {
|
|
content_entry = content_root_entry->IterateChildren(
|
|
content_find_engine, &content_find_index);
|
|
if (!content_entry) {
|
|
break;
|
|
}
|
|
|
|
auto item = e->AppendItem();
|
|
assert_not_null(item);
|
|
if (item) {
|
|
item->device_id = static_cast<uint32_t>(DummyDeviceId::ODD);
|
|
item->content_type = content_type;
|
|
item->set_display_name(to_utf16(content_entry->name()));
|
|
item->set_file_name(content_entry->name());
|
|
item->title_id = title_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Alias XContentCreateCrossTitleEnumerator
|
|
dword_result_t XamContentAggregateCreateEnumerator_entry(qword_t xuid,
|
|
dword_t device_id,
|
|
dword_t content_type,
|
|
dword_t title_id,
|
|
lpdword_t handle_out) {
|
|
assert_not_null(handle_out);
|
|
|
|
auto device_info = device_id == 0 ? nullptr : GetDummyDeviceInfo(device_id);
|
|
if ((device_id && device_info == nullptr) || !handle_out) {
|
|
return X_E_INVALIDARG;
|
|
}
|
|
|
|
auto e = make_object<XStaticEnumerator<XCONTENT_CROSS_TITLE_DATA>>(
|
|
kernel_state(), 1);
|
|
X_KENUMERATOR_CONTENT_AGGREGATE* extra;
|
|
auto result = e->Initialize(XUserIndexAny, 0xFE, 0x2000E, 0x20010, 0, &extra);
|
|
if (XFAILED(result)) {
|
|
return result;
|
|
}
|
|
|
|
extra->magic = kXObjSignature;
|
|
extra->handle = e->handle();
|
|
|
|
const XContentType content_type_enum =
|
|
static_cast<XContentType>(content_type.value());
|
|
|
|
if (!device_info || device_info->device_type == DeviceType::HDD) {
|
|
// Fetch any alternate title IDs defined in the XEX header
|
|
// (used by games to load saves from other titles, etc)
|
|
std::vector<uint32_t> title_ids{title_id ? title_id.value()
|
|
: kCurrentlyRunningTitleId};
|
|
auto exe_module = kernel_state()->GetExecutableModule();
|
|
if (exe_module && exe_module->xex_module()) {
|
|
const auto& alt_ids = exe_module->xex_module()->opt_alternate_title_ids();
|
|
std::copy(alt_ids.cbegin(), alt_ids.cend(),
|
|
std::back_inserter(title_ids));
|
|
}
|
|
|
|
for (const auto& title_id : title_ids) {
|
|
// Get all content data.
|
|
auto content_datas = kernel_state()->content_manager()->ListContent(
|
|
static_cast<uint32_t>(DummyDeviceId::HDD),
|
|
xuid == -1 ? 0 : static_cast<uint64_t>(xuid), title_id,
|
|
content_type_enum);
|
|
for (const auto& content_data : content_datas) {
|
|
auto item = e->AppendItem();
|
|
assert_not_null(item);
|
|
if (item) {
|
|
item->content_data.device_id = content_data.device_id;
|
|
item->content_data.content_type = content_data.content_type;
|
|
item->content_data.display_name_raw = content_data.display_name_raw;
|
|
std::memcpy(item->content_data.file_name_raw,
|
|
content_data.file_name_raw,
|
|
sizeof(content_data.file_name_raw));
|
|
item->content_data.padding[0] = 0;
|
|
item->content_data.padding[1] = 0;
|
|
|
|
item->title_id = content_data.title_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if (!device_info || device_info->device_type == DeviceType::ODD) {
|
|
// AddODDContentTest(e, content_type_enum);
|
|
// }
|
|
|
|
XELOGD("XamContentAggregateCreateEnumerator: added {} items to enumerator",
|
|
e->item_count());
|
|
|
|
*handle_out = e->handle();
|
|
return X_ERROR_SUCCESS;
|
|
}
|
|
DECLARE_XAM_EXPORT1(XamContentAggregateCreateEnumerator, kContent, kStub);
|
|
|
|
} // namespace xam
|
|
} // namespace kernel
|
|
} // namespace xe
|
|
|
|
DECLARE_XAM_EMPTY_REGISTER_EXPORTS(ContentAggregate);
|