Most of XamContent* methods, besides enumeration.

Progress on #152.
This commit is contained in:
Ben Vanik
2015-02-12 14:16:43 -08:00
parent 53eaeff690
commit dc731f6a31
25 changed files with 849 additions and 14 deletions

View File

@@ -57,7 +57,7 @@ SHIM_CALL XamShowDeviceSelectorUI_shim(PPCContext* ppc_state,
uint32_t device_id_ptr = SHIM_GET_ARG_32(4);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
XELOGD("XamShowDeviceSelectorUI(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
XELOGD("XamShowDeviceSelectorUI(%d, %.8X, %.8X, %.8X, %.8X, %.8X)",
user_index, content_type, content_flags, total_requested,
device_id_ptr, overlapped_ptr);
@@ -159,6 +159,29 @@ SHIM_CALL XamContentGetDeviceData_shim(PPCContext* ppc_state,
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamContentResolve_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t content_data_ptr = SHIM_GET_ARG_32(1);
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
uint32_t buffer_size = SHIM_GET_ARG_32(3);
uint32_t unk1 = SHIM_GET_ARG_32(4); // 1
uint32_t unk2 = SHIM_GET_ARG_32(5); // 0
uint32_t unk3 = SHIM_GET_ARG_32(6); // 0
auto content_data = XCONTENT_DATA(SHIM_MEM_ADDR(content_data_ptr));
XELOGD("XamContentResolve(%d, %.8X, %.8X, %d, %.8X, %.8X, %.8X)", user_index,
content_data_ptr, buffer_ptr, buffer_size, unk1, unk2, unk3);
// Result of buffer_ptr is sent to RtlInitAnsiString.
// buffer_size is usually 260 (max path).
// Games expect zero if resolve was successful.
assert_always();
XELOGW("XamContentResolve unimplemented!");
SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
}
// http://gameservice.googlecode.com/svn-history/r14/trunk/ContentManager.cpp
SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state,
KernelState* state) {
@@ -170,7 +193,7 @@ SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state,
uint32_t buffer_size_ptr = SHIM_GET_ARG_32(5);
uint32_t handle_ptr = SHIM_GET_ARG_32(6);
XELOGD("XamContentCreateEnumerator(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
XELOGD("XamContentCreateEnumerator(%d, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
user_index, device_id, content_type, content_flags, item_count,
buffer_size_ptr, handle_ptr);
@@ -194,6 +217,227 @@ SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state,
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamContentCreate_shim(PPCContext* ppc_state, KernelState* state) {
// uint32_t user_index = SHIM_GET_ARG_32(0);
// uint32_t content_data_ptr = SHIM_GET_ARG_32(1);
XELOGD("XamContentCreate unimplemented");
assert_always();
}
SHIM_CALL XamContentCreateEx_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t root_name_ptr = SHIM_GET_ARG_32(1);
uint32_t content_data_ptr = SHIM_GET_ARG_32(2);
uint32_t flags = SHIM_GET_ARG_32(3);
uint32_t disposition_ptr = SHIM_GET_ARG_32(4);
uint32_t license_mask_ptr = SHIM_GET_ARG_32(5);
uint32_t cache_size = SHIM_GET_ARG_32(6);
uint64_t content_size = SHIM_GET_ARG_64(7);
uint32_t sp = (uint32_t)ppc_state->r[1];
uint32_t overlapped_ptr = SHIM_MEM_32(sp + 0x54);
auto root_name =
poly::load_and_swap<std::string>(SHIM_MEM_ADDR(root_name_ptr));
auto content_data = XCONTENT_DATA(SHIM_MEM_ADDR(content_data_ptr));
XELOGD(
"XamContentCreateEx(%d, %.8X(%s), %.8X, %.8X, %.8X, %.8X, %.8X, %.8llX, "
"%.8X)",
user_index, root_name_ptr, root_name.c_str(), content_data_ptr, flags,
disposition_ptr, license_mask_ptr, cache_size, content_size,
overlapped_ptr);
assert_zero(license_mask_ptr);
X_RESULT result = X_ERROR_INVALID_PARAMETER;
auto content_manager = state->content_manager();
bool create = false;
bool open = false;
switch (flags & 0xF) {
case 1: // CREATE_NEW
// Fail if exists.
if (content_manager->ContentExists(content_data)) {
result = X_ERROR_ALREADY_EXISTS;
} else {
create = true;
}
break;
case 2: // CREATE_ALWAYS
// Overwrite existing, if any.
if (content_manager->ContentExists(content_data)) {
content_manager->DeleteContent(content_data);
create = true;
} else {
create = true;
}
break;
case 3: // OPEN_EXISTING
// Open only if exists.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_FILE_NOT_FOUND;
} else {
open = true;
}
break;
case 4: // OPEN_ALWAYS
// Create if needed.
if (!content_manager->ContentExists(content_data)) {
create = true;
} else {
open = true;
}
break;
case 5: // TRUNCATE_EXISTING
// Fail if doesn't exist, if does exist delete and recreate.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_FILE_NOT_FOUND;
} else {
content_manager->DeleteContent(content_data);
create = true;
}
break;
default:
assert_unhandled_case(flags & 0xF);
break;
}
if (disposition_ptr) {
if (overlapped_ptr) {
// If async always set to zero, but don't set to a real value.
SHIM_SET_MEM_32(disposition_ptr, 0);
} else {
SHIM_SET_MEM_32(disposition_ptr, create ? 1 : 2);
}
}
if (create) {
result = content_manager->CreateContent(root_name, content_data);
} else if (open) {
result = content_manager->OpenContent(root_name, content_data);
}
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
SHIM_CALL XamContentClose_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t root_name_ptr = SHIM_GET_ARG_32(0);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(1);
auto root_name =
poly::load_and_swap<std::string>(SHIM_MEM_ADDR(root_name_ptr));
XELOGD("XamContentClose(%.8X(%s), %.8X)", root_name_ptr, root_name.c_str(),
overlapped_ptr);
// Closes a previously opened root from XamContentCreate*.
auto result = state->content_manager()->CloseContent(root_name);
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
SHIM_CALL XamContentGetThumbnail_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t content_data_ptr = SHIM_GET_ARG_32(1);
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
uint32_t buffer_size_ptr = SHIM_GET_ARG_32(3);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
assert_not_zero(buffer_size_ptr);
uint32_t buffer_size = SHIM_MEM_32(buffer_size_ptr);
auto content_data = XCONTENT_DATA(SHIM_MEM_ADDR(content_data_ptr));
XELOGD("XamContentGetThumbnail(%d, %.8X, %.8X, %.8X(%d), %.8X)", user_index,
content_data_ptr, buffer_ptr, buffer_size_ptr, buffer_size,
overlapped_ptr);
// Get thumbnail (if it exists).
std::vector<uint8_t> buffer;
auto result =
state->content_manager()->GetContentThumbnail(content_data, &buffer);
SHIM_SET_MEM_32(buffer_size_ptr, uint32_t(buffer.size()));
if (XSUCCEEDED(result)) {
// Write data, if we were given a pointer.
// This may have just been a size query.
if (buffer_ptr) {
if (buffer_size < buffer.size()) {
// Dest buffer too small.
result = X_ERROR_INSUFFICIENT_BUFFER;
} else {
// Copy data.
std::memcpy(SHIM_MEM_ADDR(buffer_ptr), buffer.data(), buffer.size());
}
}
}
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
SHIM_CALL XamContentSetThumbnail_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t content_data_ptr = SHIM_GET_ARG_32(1);
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
uint32_t buffer_size = SHIM_GET_ARG_32(3);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
auto content_data = XCONTENT_DATA(SHIM_MEM_ADDR(content_data_ptr));
XELOGD("XamContentSetThumbnail(%d, %.8X, %.8X, %d, %.8X)", user_index,
content_data_ptr, buffer_ptr, buffer_size, overlapped_ptr);
// Buffer is PNG data.
auto buffer = std::vector<uint8_t>(SHIM_MEM_ADDR(buffer_ptr),
SHIM_MEM_ADDR(buffer_ptr) + buffer_size);
auto result = state->content_manager()->SetContentThumbnail(
content_data, std::move(buffer));
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
SHIM_CALL XamContentDelete_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t content_data_ptr = SHIM_GET_ARG_32(1);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(2);
auto content_data = XCONTENT_DATA(SHIM_MEM_ADDR(content_data_ptr));
XELOGD("XamContentDelete(%d, %.8X, %.8X)", user_index, content_data_ptr,
overlapped_ptr);
auto result = state->content_manager()->DeleteContent(content_data);
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
} // namespace kernel
} // namespace xe
@@ -204,5 +448,12 @@ void xe::kernel::xam::RegisterContentExports(ExportResolver* export_resolver,
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceName, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceState, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceData, state);
SHIM_SET_MAPPING("xam.xex", XamContentResolve, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreateEnumerator, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreate, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreateEx, state);
SHIM_SET_MAPPING("xam.xex", XamContentClose, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetThumbnail, state);
SHIM_SET_MAPPING("xam.xex", XamContentSetThumbnail, state);
SHIM_SET_MAPPING("xam.xex", XamContentDelete, state);
}