Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -119,6 +119,8 @@ dword_result_t XamContentCreateEnumerator_entry(
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamContentCreateEnumerator, kContent, kImplemented);
|
||||
|
||||
enum class kDispositionState : uint32_t { Unknown = 0, Create = 1, Open = 2 };
|
||||
|
||||
dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||
lpvoid_t content_data_ptr,
|
||||
dword_t content_data_size, dword_t flags,
|
||||
@@ -146,40 +148,37 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||
content_data, disposition_ptr, license_mask_ptr, overlapped_ptr](
|
||||
uint32_t& extended_error, uint32_t& length) -> X_RESULT {
|
||||
X_RESULT result = X_ERROR_INVALID_PARAMETER;
|
||||
bool create = false;
|
||||
bool open = false;
|
||||
kDispositionState disposition = kDispositionState::Unknown;
|
||||
switch (flags & 0xF) {
|
||||
case 1: // CREATE_NEW
|
||||
// Fail if exists.
|
||||
if (content_manager->ContentExists(content_data)) {
|
||||
result = X_ERROR_ALREADY_EXISTS;
|
||||
} else {
|
||||
create = true;
|
||||
disposition = kDispositionState::Create;
|
||||
}
|
||||
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;
|
||||
}
|
||||
disposition = kDispositionState::Create;
|
||||
break;
|
||||
case 3: // OPEN_EXISTING
|
||||
// Open only if exists.
|
||||
if (!content_manager->ContentExists(content_data)) {
|
||||
result = X_ERROR_PATH_NOT_FOUND;
|
||||
} else {
|
||||
open = true;
|
||||
disposition = kDispositionState::Open;
|
||||
}
|
||||
break;
|
||||
case 4: // OPEN_ALWAYS
|
||||
// Create if needed.
|
||||
if (!content_manager->ContentExists(content_data)) {
|
||||
create = true;
|
||||
disposition = kDispositionState::Create;
|
||||
} else {
|
||||
open = true;
|
||||
disposition = kDispositionState::Open;
|
||||
}
|
||||
break;
|
||||
case 5: // TRUNCATE_EXISTING
|
||||
@@ -188,7 +187,7 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||
result = X_ERROR_PATH_NOT_FOUND;
|
||||
} else {
|
||||
content_manager->DeleteContent(content_data);
|
||||
create = true;
|
||||
disposition = kDispositionState::Create;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -196,21 +195,12 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||
break;
|
||||
}
|
||||
|
||||
// creation result
|
||||
// 0 = ?
|
||||
// 1 = created
|
||||
// 2 = opened
|
||||
uint32_t disposition = create ? 1 : 2;
|
||||
if (disposition_ptr) {
|
||||
*disposition_ptr = disposition;
|
||||
}
|
||||
|
||||
if (create) {
|
||||
if (disposition == kDispositionState::Create) {
|
||||
result = content_manager->CreateContent(root_name, content_data);
|
||||
if (XSUCCEEDED(result)) {
|
||||
content_manager->WriteContentHeaderFile(&content_data);
|
||||
}
|
||||
} else if (open) {
|
||||
} else if (disposition == kDispositionState::Open) {
|
||||
result = content_manager->OpenContent(root_name, content_data);
|
||||
}
|
||||
|
||||
@@ -224,12 +214,11 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||
}
|
||||
|
||||
extended_error = X_HRESULT_FROM_WIN32(result);
|
||||
length = disposition;
|
||||
length = static_cast<uint32_t>(disposition);
|
||||
|
||||
if (result && overlapped_ptr) {
|
||||
result = X_ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -451,7 +440,6 @@ static_assert_size(X_SWAPDISC_ERROR_MESSAGE, 12);
|
||||
dword_result_t XamSwapDisc_entry(
|
||||
dword_t disc_number, pointer_t<X_KEVENT> completion_handle,
|
||||
pointer_t<X_SWAPDISC_ERROR_MESSAGE> error_message) {
|
||||
|
||||
xex2_opt_execution_info* info = nullptr;
|
||||
kernel_state()->GetExecutableModule()->GetOptHeader(XEX_HEADER_EXECUTION_INFO,
|
||||
&info);
|
||||
|
||||
@@ -254,202 +254,15 @@ dword_result_t XGetLanguage_entry() {
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented);
|
||||
|
||||
// http://www.noxa.org/blog/2011/02/28/building-an-xbox-360-emulator-part-3-feasibilityos/
|
||||
// http://www.noxa.org/blog/2011/08/13/building-an-xbox-360-emulator-part-5-xex-files/
|
||||
dword_result_t RtlSleep_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||
LARGE_INTEGER delay{};
|
||||
|
||||
// Convert the delay time to 100-nanosecond intervals
|
||||
delay.QuadPart = dwMilliseconds == -1
|
||||
? LLONG_MAX
|
||||
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||
|
||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
|
||||
// If the delay was interrupted by an APC, keep delaying the thread
|
||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||
result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
}
|
||||
|
||||
return result == X_STATUS_SUCCESS ? X_STATUS_SUCCESS : X_STATUS_USER_APC;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(RtlSleep, kNone, kImplemented);
|
||||
|
||||
dword_result_t SleepEx_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||
return RtlSleep_entry(dwMilliseconds, bAlertable);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(SleepEx, kNone, kImplemented);
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
|
||||
void Sleep_entry(dword_t dwMilliseconds) {
|
||||
RtlSleep_entry(dwMilliseconds, FALSE);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(Sleep, kNone, kImplemented);
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount
|
||||
dword_result_t GetTickCount_entry() { return Clock::QueryGuestUptimeMillis(); }
|
||||
DECLARE_XAM_EXPORT1(GetTickCount, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamGetCurrentTitleId_entry() {
|
||||
return kernel_state()->emulator()->title_id();
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamGetCurrentTitleId, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlSetLastNTError_entry(dword_t error_code) {
|
||||
const uint32_t result =
|
||||
xe::kernel::xboxkrnl::xeRtlNtStatusToDosError(error_code);
|
||||
XThread::SetLastError(result);
|
||||
|
||||
return result;
|
||||
dword_result_t XamIsCurrentTitleDash_entry(const ppc_context_t& ctx) {
|
||||
return ctx->kernel_state->title_id() == 0xFFFE07D1;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(RtlSetLastNTError, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlGetLastError_entry() { return XThread::GetLastError(); }
|
||||
DECLARE_XAM_EXPORT1(RtlGetLastError, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetLastError_entry() { return RtlGetLastError_entry(); }
|
||||
DECLARE_XAM_EXPORT1(GetLastError, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetModuleHandleA_entry(lpstring_t module_name) {
|
||||
xe::be<uint32_t> module_ptr = 0;
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::XexGetModuleHandle(
|
||||
module_name.value(), &module_ptr);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (uint32_t)module_ptr;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(GetModuleHandleA, kNone, kImplemented);
|
||||
|
||||
dword_result_t XapipCreateThread_entry(lpdword_t lpThreadAttributes,
|
||||
dword_t dwStackSize,
|
||||
lpvoid_t lpStartAddress,
|
||||
lpvoid_t lpParameter,
|
||||
dword_t dwCreationFlags, dword_t unkn,
|
||||
lpdword_t lpThreadId) {
|
||||
uint32_t flags = (dwCreationFlags >> 2) & 1;
|
||||
|
||||
if (unkn != -1) {
|
||||
flags |= 1 << unkn << 24;
|
||||
}
|
||||
|
||||
xe::be<uint32_t> result = 0;
|
||||
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::ExCreateThread(
|
||||
&result, dwStackSize, lpThreadId, lpStartAddress, lpParameter, 0, flags);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (uint32_t)result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XapipCreateThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t CreateThread_entry(lpdword_t lpThreadAttributes,
|
||||
dword_t dwStackSize, lpvoid_t lpStartAddress,
|
||||
lpvoid_t lpParameter, dword_t dwCreationFlags,
|
||||
lpdword_t lpThreadId) {
|
||||
return XapipCreateThread_entry(lpThreadAttributes, dwStackSize,
|
||||
lpStartAddress, lpParameter, dwCreationFlags,
|
||||
-1, lpThreadId);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(CreateThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t CloseHandle_entry(dword_t hObject) {
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::NtClose(hObject);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(CloseHandle, kNone, kImplemented);
|
||||
|
||||
dword_result_t ResumeThread_entry(dword_t hThread) {
|
||||
uint32_t suspend_count;
|
||||
const X_STATUS error_code =
|
||||
xe::kernel::xboxkrnl::NtResumeThread(hThread, &suspend_count);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return suspend_count;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(ResumeThread, kNone, kImplemented);
|
||||
|
||||
void ExitThread_entry(dword_t exit_code) {
|
||||
xe::kernel::xboxkrnl::ExTerminateThread(exit_code);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(ExitThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetCurrentThreadId_entry() {
|
||||
return XThread::GetCurrentThread()->GetCurrentThreadId();
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(GetCurrentThreadId, kNone, kImplemented);
|
||||
|
||||
qword_result_t XapiFormatTimeOut_entry(lpqword_t result,
|
||||
dword_t dwMilliseconds) {
|
||||
LARGE_INTEGER delay{};
|
||||
|
||||
// Convert the delay time to 100-nanosecond intervals
|
||||
delay.QuadPart =
|
||||
dwMilliseconds == -1 ? 0 : static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||
|
||||
return (uint64_t)&delay;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XapiFormatTimeOut, kNone, kImplemented);
|
||||
|
||||
dword_result_t WaitForSingleObjectEx_entry(dword_t hHandle,
|
||||
dword_t dwMilliseconds,
|
||||
dword_t bAlertable) {
|
||||
uint64_t* timeout = nullptr;
|
||||
uint64_t timeout_ptr = XapiFormatTimeOut_entry(timeout, dwMilliseconds);
|
||||
|
||||
X_STATUS result = xe::kernel::xboxkrnl::NtWaitForSingleObjectEx(
|
||||
hHandle, 1, bAlertable, &timeout_ptr);
|
||||
|
||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||
result = xe::kernel::xboxkrnl::NtWaitForSingleObjectEx(
|
||||
hHandle, 1, bAlertable, &timeout_ptr);
|
||||
}
|
||||
|
||||
RtlSetLastNTError_entry(result);
|
||||
result = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(WaitForSingleObjectEx, kNone, kImplemented);
|
||||
|
||||
dword_result_t WaitForSingleObject_entry(dword_t hHandle,
|
||||
dword_t dwMilliseconds) {
|
||||
return WaitForSingleObjectEx_entry(hHandle, dwMilliseconds, 0);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(WaitForSingleObject, kNone, kImplemented);
|
||||
|
||||
dword_result_t lstrlenW_entry(lpu16string_t string) {
|
||||
// wcslen?
|
||||
if (string) {
|
||||
return (uint32_t)string.value().length();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(lstrlenW, kNone, kImplemented);
|
||||
DECLARE_XAM_EXPORT1(XamIsCurrentTitleDash, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamGetExecutionId_entry(lpdword_t info_ptr) {
|
||||
auto module = kernel_state()->GetExecutableModule();
|
||||
@@ -611,16 +424,204 @@ dword_result_t XamQueryLiveHiveW_entry(lpu16string_t name, lpvoid_t out_buf,
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamQueryLiveHiveW, kNone, kStub);
|
||||
|
||||
dword_result_t XamIsCurrentTitleDash_entry(const ppc_context_t& ctx) {
|
||||
return ctx->kernel_state->title_id() == 0xFFFE07D1;
|
||||
// http://www.noxa.org/blog/2011/02/28/building-an-xbox-360-emulator-part-3-feasibilityos/
|
||||
// http://www.noxa.org/blog/2011/08/13/building-an-xbox-360-emulator-part-5-xex-files/
|
||||
dword_result_t RtlSleep_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||
LARGE_INTEGER delay{};
|
||||
|
||||
// Convert the delay time to 100-nanosecond intervals
|
||||
delay.QuadPart = dwMilliseconds == -1
|
||||
? LLONG_MAX
|
||||
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||
|
||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
|
||||
// If the delay was interrupted by an APC, keep delaying the thread
|
||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||
result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
}
|
||||
|
||||
return result == X_STATUS_SUCCESS ? X_STATUS_SUCCESS : X_STATUS_USER_APC;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamIsCurrentTitleDash, kNone, kImplemented);
|
||||
DECLARE_XAM_EXPORT1(RtlSleep, kNone, kImplemented);
|
||||
|
||||
dword_result_t SleepEx_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||
return RtlSleep_entry(dwMilliseconds, bAlertable);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(SleepEx, kNone, kImplemented);
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
|
||||
void Sleep_entry(dword_t dwMilliseconds) {
|
||||
RtlSleep_entry(dwMilliseconds, FALSE);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(Sleep, kNone, kImplemented);
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount
|
||||
dword_result_t GetTickCount_entry() { return Clock::QueryGuestUptimeMillis(); }
|
||||
DECLARE_XAM_EXPORT1(GetTickCount, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlSetLastNTError_entry(dword_t error_code) {
|
||||
const uint32_t result =
|
||||
xe::kernel::xboxkrnl::xeRtlNtStatusToDosError(error_code);
|
||||
XThread::SetLastError(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(RtlSetLastNTError, kNone, kImplemented);
|
||||
|
||||
dword_result_t RtlGetLastError_entry() { return XThread::GetLastError(); }
|
||||
DECLARE_XAM_EXPORT1(RtlGetLastError, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetLastError_entry() { return RtlGetLastError_entry(); }
|
||||
DECLARE_XAM_EXPORT1(GetLastError, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetModuleHandleA_entry(lpstring_t module_name) {
|
||||
xe::be<uint32_t> module_ptr = 0;
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::XexGetModuleHandle(
|
||||
module_name.value(), &module_ptr);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (uint32_t)module_ptr;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(GetModuleHandleA, kNone, kImplemented);
|
||||
|
||||
dword_result_t XapipCreateThread_entry(lpdword_t lpThreadAttributes,
|
||||
dword_t dwStackSize,
|
||||
lpvoid_t lpStartAddress,
|
||||
lpvoid_t lpParameter,
|
||||
dword_t dwCreationFlags, dword_t unkn,
|
||||
lpdword_t lpThreadId) {
|
||||
uint32_t flags = (dwCreationFlags >> 2) & 1;
|
||||
|
||||
if (unkn != -1) {
|
||||
flags |= 1 << unkn << 24;
|
||||
}
|
||||
|
||||
xe::be<uint32_t> result = 0;
|
||||
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::ExCreateThread(
|
||||
&result, dwStackSize, lpThreadId, lpStartAddress, lpParameter, 0, flags);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (uint32_t)result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XapipCreateThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t CreateThread_entry(lpdword_t lpThreadAttributes,
|
||||
dword_t dwStackSize, lpvoid_t lpStartAddress,
|
||||
lpvoid_t lpParameter, dword_t dwCreationFlags,
|
||||
lpdword_t lpThreadId) {
|
||||
return XapipCreateThread_entry(lpThreadAttributes, dwStackSize,
|
||||
lpStartAddress, lpParameter, dwCreationFlags,
|
||||
-1, lpThreadId);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(CreateThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t CloseHandle_entry(dword_t hObject) {
|
||||
const X_STATUS error_code = xe::kernel::xboxkrnl::NtClose(hObject);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(CloseHandle, kNone, kImplemented);
|
||||
|
||||
dword_result_t ResumeThread_entry(dword_t hThread) {
|
||||
uint32_t suspend_count;
|
||||
const X_STATUS error_code =
|
||||
xe::kernel::xboxkrnl::NtResumeThread(hThread, &suspend_count);
|
||||
|
||||
if (XFAILED(error_code)) {
|
||||
RtlSetLastNTError_entry(error_code);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return suspend_count;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(ResumeThread, kNone, kImplemented);
|
||||
|
||||
void ExitThread_entry(dword_t exit_code) {
|
||||
xe::kernel::xboxkrnl::ExTerminateThread(exit_code);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(ExitThread, kNone, kImplemented);
|
||||
|
||||
dword_result_t GetCurrentThreadId_entry() {
|
||||
return XThread::GetCurrentThread()->GetCurrentThreadId();
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(GetCurrentThreadId, kNone, kImplemented);
|
||||
|
||||
qword_result_t XapiFormatTimeOut_entry(lpqword_t result,
|
||||
dword_t dwMilliseconds) {
|
||||
LARGE_INTEGER delay{};
|
||||
|
||||
// Convert the delay time to 100-nanosecond intervals
|
||||
delay.QuadPart =
|
||||
dwMilliseconds == -1 ? 0 : static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||
|
||||
return (uint64_t)&delay;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XapiFormatTimeOut, kNone, kImplemented);
|
||||
|
||||
dword_result_t WaitForSingleObjectEx_entry(dword_t hHandle,
|
||||
dword_t dwMilliseconds,
|
||||
dword_t bAlertable) {
|
||||
uint64_t* timeout = nullptr;
|
||||
uint64_t timeout_ptr = XapiFormatTimeOut_entry(timeout, dwMilliseconds);
|
||||
|
||||
X_STATUS result = xe::kernel::xboxkrnl::NtWaitForSingleObjectEx(
|
||||
hHandle, 1, bAlertable, &timeout_ptr);
|
||||
|
||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||
result = xe::kernel::xboxkrnl::NtWaitForSingleObjectEx(
|
||||
hHandle, 1, bAlertable, &timeout_ptr);
|
||||
}
|
||||
|
||||
RtlSetLastNTError_entry(result);
|
||||
result = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(WaitForSingleObjectEx, kNone, kImplemented);
|
||||
|
||||
dword_result_t WaitForSingleObject_entry(dword_t hHandle,
|
||||
dword_t dwMilliseconds) {
|
||||
return WaitForSingleObjectEx_entry(hHandle, dwMilliseconds, 0);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(WaitForSingleObject, kNone, kImplemented);
|
||||
|
||||
dword_result_t lstrlenW_entry(lpu16string_t string) {
|
||||
// wcslen?
|
||||
if (string) {
|
||||
return (uint32_t)string.value().length();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(lstrlenW, kNone, kImplemented);
|
||||
|
||||
dword_result_t XGetAudioFlags_entry() { return 65537; }
|
||||
DECLARE_XAM_EXPORT1(XGetAudioFlags, kNone, kStub);
|
||||
|
||||
/*
|
||||
todo: this table should instead be pointed to by a member of kernel state and initialized along with the process
|
||||
todo: this table should instead be pointed to by a member of kernel
|
||||
state and initialized along with the process
|
||||
*/
|
||||
static int32_t XamRtlRandomTable[128] = {
|
||||
1284227242, 1275210071, 573735546, 790525478, 2139871995, 1547161642,
|
||||
|
||||
Reference in New Issue
Block a user