[XAM] Implemented Functions

Implemented:
- RtlSleep
- SleepEx
- Sleep
- GetTickCount
- GetModuleHandleA
- XamGetCurrentTitleId
This commit is contained in:
Adrian 2023-03-01 14:43:24 +00:00 committed by Radosław Gliński
parent d62fe21d47
commit 069d33c03f
3 changed files with 73 additions and 4 deletions

View File

@ -15,6 +15,7 @@
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/xam_module.h" #include "xenia/kernel/xam/xam_module.h"
#include "xenia/kernel/xam/xam_private.h" #include "xenia/kernel/xam/xam_private.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
#include "xenia/kernel/xenumerator.h" #include "xenia/kernel/xenumerator.h"
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
@ -33,6 +34,9 @@ namespace xe {
namespace kernel { namespace kernel {
namespace xam { namespace xam {
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/km/wdm.h#L15539
typedef enum _MODE { KernelMode, UserMode, MaximumMode } MODE;
dword_result_t XamFeatureEnabled_entry(dword_t unk) { return 0; } dword_result_t XamFeatureEnabled_entry(dword_t unk) { return 0; }
DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub); DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub);
@ -247,6 +251,57 @@ dword_result_t XGetLanguage_entry() {
} }
DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented); 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 GetModuleHandleA_entry(lpstring_t moduleName) {
auto module = kernel_state()->GetModule(moduleName.value(), false);
return module ? module->hmodule_ptr() : NULL;
}
DECLARE_XAM_EXPORT1(GetModuleHandleA, kNone, kImplemented);
dword_result_t XamGetCurrentTitleId_entry() {
return kernel_state()->emulator()->title_id();
}
DECLARE_XAM_EXPORT1(XamGetCurrentTitleId, kNone, kImplemented);
dword_result_t XamGetExecutionId_entry(lpdword_t info_ptr) { dword_result_t XamGetExecutionId_entry(lpdword_t info_ptr) {
auto module = kernel_state()->GetExecutableModule(); auto module = kernel_state()->GetExecutableModule();
assert_not_null(module); assert_not_null(module);
@ -350,7 +405,8 @@ dword_result_t XamAlloc_entry(dword_t flags, dword_t size, lpdword_t out_ptr) {
// Allocate from the heap. Not sure why XAM does this specially, perhaps // Allocate from the heap. Not sure why XAM does this specially, perhaps
// it keeps stuff in a separate heap? // it keeps stuff in a separate heap?
//chrispy: there is a set of different heaps it uses, an array of them. the top 4 bits of the 32 bit flags seems to select the heap // chrispy: there is a set of different heaps it uses, an array of them. the
// top 4 bits of the 32 bit flags seems to select the heap
uint32_t ptr = kernel_state()->memory()->SystemHeapAlloc(size); uint32_t ptr = kernel_state()->memory()->SystemHeapAlloc(size);
*out_ptr = ptr; *out_ptr = ptr;

View File

@ -102,6 +102,7 @@ dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
lpvoid_t start_address, lpvoid_t start_address,
lpvoid_t start_context, lpvoid_t start_context,
dword_t creation_flags) { dword_t creation_flags) {
// Invalid Link
// http://jafile.com/uploads/scoop/main.cpp.txt // http://jafile.com/uploads/scoop/main.cpp.txt
// DWORD // DWORD
// LPHANDLE Handle, // LPHANDLE Handle,
@ -335,14 +336,22 @@ dword_result_t KeQueryPerformanceFrequency_entry() {
DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented, DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
kHighFrequency); kHighFrequency);
dword_result_t KeDelayExecutionThread_entry(dword_t processor_mode, uint32_t KeDelayExecutionThread(uint32_t processor_mode,
dword_t alertable, uint32_t alertable,
lpqword_t interval_ptr) { uint64_t* interval_ptr) {
XThread* thread = XThread::GetCurrentThread(); XThread* thread = XThread::GetCurrentThread();
X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr); X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr);
return result; return result;
} }
dword_result_t KeDelayExecutionThread_entry(dword_t processor_mode,
dword_t alertable,
lpqword_t interval_ptr) {
uint64_t interval = interval_ptr ? static_cast<uint64_t>(*interval_ptr) : 0u;
return KeDelayExecutionThread(processor_mode, alertable,
interval_ptr ? &interval : nullptr);
}
DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented, DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented,
kBlocking, kHighFrequency); kBlocking, kHighFrequency);

View File

@ -32,6 +32,10 @@ uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason,
uint64_t* timeout_ptr); uint64_t* timeout_ptr);
uint32_t xeKeSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait); uint32_t xeKeSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait);
uint32_t KeDelayExecutionThread(uint32_t processor_mode,
uint32_t alertable,
uint64_t* interval_ptr);
} // namespace xboxkrnl } // namespace xboxkrnl
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe