diff --git a/src/xenia/kernel/xam_content.cc b/src/xenia/kernel/xam_content.cc index f108eb06a..3cacead7b 100644 --- a/src/xenia/kernel/xam_content.cc +++ b/src/xenia/kernel/xam_content.cc @@ -17,6 +17,17 @@ namespace xe { namespace kernel { +struct DeviceInfo { + uint32_t device_id; + uint32_t device_type; + uint64_t total_bytes; + uint64_t free_bytes; + std::wstring name; +}; +static const DeviceInfo dummy_device_info_ = { + 0xF00D0000, 1, 1024 * 1024 * 1024, 1024 * 1024 * 1024, L"Dummy HDD", +}; + SHIM_CALL XamContentGetLicenseMask_shim(PPCContext* ppc_state, KernelState* state) { uint32_t mask_ptr = SHIM_GET_ARG_32(0); @@ -52,13 +63,13 @@ SHIM_CALL XamShowDeviceSelectorUI_shim(PPCContext* ppc_state, switch (content_type) { case 1: // save game - SHIM_SET_MEM_32(device_id_ptr, 0xF00D0001); + SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0001); break; case 2: // marketplace - SHIM_SET_MEM_32(device_id_ptr, 0xF00D0002); + SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0002); break; case 3: // title/publisher update? - SHIM_SET_MEM_32(device_id_ptr, 0xF00D0003); + SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0003); break; } @@ -80,8 +91,20 @@ SHIM_CALL XamContentGetDeviceName_shim(PPCContext* ppc_state, XELOGD("XamContentGetDeviceName(%.8X, %.8X, %d)", device_id, name_ptr, name_capacity); - // Always say device not connected. - SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); + if ((device_id & 0xFFFF0000) != dummy_device_info_.device_id) { + SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); + return; + } + + if (name_capacity < dummy_device_info_.name.size() + 1) { + SHIM_SET_RETURN_32(X_ERROR_INSUFFICIENT_BUFFER); + return; + } + + poly::store_and_swap(SHIM_MEM_ADDR(name_ptr), + dummy_device_info_.name); + + SHIM_SET_RETURN_32(X_ERROR_SUCCESS); } SHIM_CALL XamContentGetDeviceState_shim(PPCContext* ppc_state, @@ -91,19 +114,51 @@ SHIM_CALL XamContentGetDeviceState_shim(PPCContext* ppc_state, XELOGD("XamContentGetDeviceState(%.8X, %.8X)", device_id, overlapped_ptr); - // Always say device not connected. - // This may cause games to go into an infinite loop trying to show the device - // dialog, but we can deal with that later. + if ((device_id & 0xFFFF0000) != dummy_device_info_.device_id) { + if (overlapped_ptr) { + state->CompleteOverlappedImmediate(overlapped_ptr, + X_ERROR_FUNCTION_FAILED); + XOverlappedSetExtendedError(SHIM_MEM_BASE + overlapped_ptr, + X_ERROR_DEVICE_NOT_CONNECTED); + SHIM_SET_RETURN_32(X_ERROR_IO_PENDING); + } else { + SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); + } + return; + } + if (overlapped_ptr) { - state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_FUNCTION_FAILED); - XOverlappedSetExtendedError(SHIM_MEM_BASE + overlapped_ptr, - X_ERROR_DEVICE_NOT_CONNECTED); + state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS); SHIM_SET_RETURN_32(X_ERROR_IO_PENDING); } else { - SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); + SHIM_SET_RETURN_32(X_ERROR_SUCCESS); } } +SHIM_CALL XamContentGetDeviceData_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t device_id = SHIM_GET_ARG_32(0); + uint32_t device_data_ptr = SHIM_GET_ARG_32(1); + + XELOGD("XamContentGetDeviceData(%.8X, %.8X)", device_id, device_data_ptr); + + if ((device_id & 0xFFFF0000) != dummy_device_info_.device_id) { + // TODO(benvanik): memset 0 the data? + SHIM_SET_RETURN_32(X_ERROR_DEVICE_NOT_CONNECTED); + return; + } + + const auto& device_info = dummy_device_info_; + SHIM_SET_MEM_32(device_data_ptr + 0, device_info.device_id); + SHIM_SET_MEM_32(device_data_ptr + 4, device_info.device_type); + SHIM_SET_MEM_64(device_data_ptr + 8, device_info.total_bytes); + SHIM_SET_MEM_64(device_data_ptr + 16, device_info.free_bytes); + poly::store_and_swap(SHIM_MEM_ADDR(device_data_ptr + 24), + device_info.name); + + SHIM_SET_RETURN_32(X_ERROR_SUCCESS); +} + // http://gameservice.googlecode.com/svn-history/r14/trunk/ContentManager.cpp SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state, KernelState* state) { @@ -119,8 +174,15 @@ SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state, user_index, device_id, content_type, content_flags, item_count, buffer_size_ptr, handle_ptr); + if (device_id && (device_id & 0xFFFF0000) != dummy_device_info_.device_id) { + // TODO(benvanik): memset 0 the data? + SHIM_SET_RETURN_32(X_E_INVALIDARG); + return; + } + // 4 + 4 + 128*2 + 42 = 306 if (buffer_size_ptr) { + uint32_t bp = SHIM_MEM_32(buffer_size_ptr); SHIM_SET_MEM_32(buffer_size_ptr, item_count * 306); } @@ -141,5 +203,6 @@ void xe::kernel::xam::RegisterContentExports(ExportResolver* export_resolver, SHIM_SET_MAPPING("xam.xex", XamShowDeviceSelectorUI, state); 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", XamContentCreateEnumerator, state); } diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 2a247ae84..0f2397e5b 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -70,23 +70,26 @@ typedef uint32_t X_STATUS; // Windows is a weird place. typedef uint32_t X_RESULT; #define X_FACILITY_WIN32 7 -#define X_HRESULT_FROM_WIN32(x) x //((X_RESULT)(x) <= 0 ? ((X_RESULT)(x)) : ((X_RESULT) (((x) & 0x0000FFFF) | (X_FACILITY_WIN32 << 16) | 0x80000000))) -#define X_ERROR_SUCCESS X_HRESULT_FROM_WIN32(0x00000000L) -#define X_ERROR_ACCESS_DENIED X_HRESULT_FROM_WIN32(0x00000005L) -#define X_ERROR_INVALID_HANDLE X_HRESULT_FROM_WIN32(0x00000006L) -#define X_ERROR_NO_MORE_FILES X_HRESULT_FROM_WIN32(0x00000018L) -#define X_ERROR_INVALID_PARAMETER X_HRESULT_FROM_WIN32(0x00000057L) -#define X_ERROR_IO_PENDING X_HRESULT_FROM_WIN32(0x000003E5L) -#define X_ERROR_INSUFFICIENT_BUFFER X_HRESULT_FROM_WIN32(0x0000007AL) -#define X_ERROR_BAD_ARGUMENTS X_HRESULT_FROM_WIN32(0x000000A0L) -#define X_ERROR_BUSY X_HRESULT_FROM_WIN32(0x000000AAL) -#define X_ERROR_DEVICE_NOT_CONNECTED X_HRESULT_FROM_WIN32(0x0000048FL) -#define X_ERROR_NOT_FOUND X_HRESULT_FROM_WIN32(0x00000490L) -#define X_ERROR_CANCELLED X_HRESULT_FROM_WIN32(0x000004C7L) -#define X_ERROR_NOT_LOGGED_ON X_HRESULT_FROM_WIN32(0x000004DDL) -#define X_ERROR_NO_SUCH_USER X_HRESULT_FROM_WIN32(0x00000525L) -#define X_ERROR_FUNCTION_FAILED X_HRESULT_FROM_WIN32(0x0000065BL) -#define X_ERROR_EMPTY X_HRESULT_FROM_WIN32(0x000010D2L) +#define X_RESULT_FROM_WIN32(x) x //((X_RESULT)(x) <= 0 ? ((X_RESULT)(x)) : ((X_RESULT) (((x) & 0x0000FFFF) | (X_FACILITY_WIN32 << 16) | 0x80000000))) +#define X_ERROR_SUCCESS X_RESULT_FROM_WIN32(0x00000000L) +#define X_ERROR_ACCESS_DENIED X_RESULT_FROM_WIN32(0x00000005L) +#define X_ERROR_INVALID_HANDLE X_RESULT_FROM_WIN32(0x00000006L) +#define X_ERROR_NO_MORE_FILES X_RESULT_FROM_WIN32(0x00000018L) +#define X_ERROR_INVALID_PARAMETER X_RESULT_FROM_WIN32(0x00000057L) +#define X_ERROR_IO_PENDING X_RESULT_FROM_WIN32(0x000003E5L) +#define X_ERROR_INSUFFICIENT_BUFFER X_RESULT_FROM_WIN32(0x0000007AL) +#define X_ERROR_BAD_ARGUMENTS X_RESULT_FROM_WIN32(0x000000A0L) +#define X_ERROR_BUSY X_RESULT_FROM_WIN32(0x000000AAL) +#define X_ERROR_DEVICE_NOT_CONNECTED X_RESULT_FROM_WIN32(0x0000048FL) +#define X_ERROR_NOT_FOUND X_RESULT_FROM_WIN32(0x00000490L) +#define X_ERROR_CANCELLED X_RESULT_FROM_WIN32(0x000004C7L) +#define X_ERROR_NOT_LOGGED_ON X_RESULT_FROM_WIN32(0x000004DDL) +#define X_ERROR_NO_SUCH_USER X_RESULT_FROM_WIN32(0x00000525L) +#define X_ERROR_FUNCTION_FAILED X_RESULT_FROM_WIN32(0x0000065BL) +#define X_ERROR_EMPTY X_RESULT_FROM_WIN32(0x000010D2L) + +typedef uint32_t X_HRESULT; +#define X_E_INVALIDARG static_cast(0x80070057L) // MEM_*, used by NtAllocateVirtualMemory #define X_MEM_COMMIT 0x00001000