[XAM] Plugin Functions
This commit is contained in:
parent
28c67b9384
commit
6a23f1457b
|
@ -1191,7 +1191,7 @@ const std::map<int, EmulatorWindow::ControllerHotKey> controller_hotkey_map = {
|
||||||
{X_INPUT_GAMEPAD_BACK | X_INPUT_GAMEPAD_START,
|
{X_INPUT_GAMEPAD_BACK | X_INPUT_GAMEPAD_START,
|
||||||
EmulatorWindow::ControllerHotKey(
|
EmulatorWindow::ControllerHotKey(
|
||||||
EmulatorWindow::ButtonFunctions::ToggleLogging,
|
EmulatorWindow::ButtonFunctions::ToggleLogging,
|
||||||
"Back + Start = Close Window", false, false)},
|
"Back + Start = Toggle between loglevel set in config and the 'Disabled' loglevel.", false, false)},
|
||||||
{X_INPUT_GAMEPAD_DPAD_DOWN,
|
{X_INPUT_GAMEPAD_DPAD_DOWN,
|
||||||
EmulatorWindow::ControllerHotKey(
|
EmulatorWindow::ControllerHotKey(
|
||||||
EmulatorWindow::ButtonFunctions::IncTitleSelect,
|
EmulatorWindow::ButtonFunctions::IncTitleSelect,
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <xenia/kernel/xboxkrnl/xboxkrnl_error.h>
|
||||||
|
#include <xenia/kernel/xboxkrnl/xboxkrnl_modules.h>
|
||||||
#include "xenia/base/cvar.h"
|
#include "xenia/base/cvar.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/string_util.h"
|
#include "xenia/base/string_util.h"
|
||||||
|
@ -290,17 +292,165 @@ DECLARE_XAM_EXPORT1(Sleep, kNone, kImplemented);
|
||||||
dword_result_t GetTickCount_entry() { return Clock::QueryGuestUptimeMillis(); }
|
dword_result_t GetTickCount_entry() { return Clock::QueryGuestUptimeMillis(); }
|
||||||
DECLARE_XAM_EXPORT1(GetTickCount, kNone, kImplemented);
|
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() {
|
dword_result_t XamGetCurrentTitleId_entry() {
|
||||||
return kernel_state()->emulator()->title_id();
|
return kernel_state()->emulator()->title_id();
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamGetCurrentTitleId, kNone, kImplemented);
|
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;
|
||||||
|
}
|
||||||
|
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 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);
|
||||||
|
@ -419,11 +569,8 @@ dword_result_t XamAlloc_entry(dword_t flags, dword_t size, lpdword_t out_ptr) {
|
||||||
DECLARE_XAM_EXPORT1(XamAlloc, kMemory, kImplemented);
|
DECLARE_XAM_EXPORT1(XamAlloc, kMemory, kImplemented);
|
||||||
|
|
||||||
static const unsigned short XamPhysicalProtTable[4] = {
|
static const unsigned short XamPhysicalProtTable[4] = {
|
||||||
X_PAGE_READONLY,
|
X_PAGE_READONLY, X_PAGE_READWRITE | X_PAGE_NOCACHE, X_PAGE_READWRITE,
|
||||||
X_PAGE_READWRITE | X_PAGE_NOCACHE,
|
X_PAGE_WRITECOMBINE | X_PAGE_READWRITE};
|
||||||
X_PAGE_READWRITE,
|
|
||||||
X_PAGE_WRITECOMBINE | X_PAGE_READWRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
dword_result_t XamAllocEx_entry(dword_t phys_flags, dword_t flags, dword_t size,
|
dword_result_t XamAllocEx_entry(dword_t phys_flags, dword_t flags, dword_t size,
|
||||||
lpdword_t out_ptr, const ppc_context_t& ctx) {
|
lpdword_t out_ptr, const ppc_context_t& ctx) {
|
||||||
|
|
|
@ -344,6 +344,44 @@ dword_result_t XamShowMessageBoxUIEx_entry(
|
||||||
overlapped);
|
overlapped);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamShowMessageBoxUIEx, kUI, kImplemented);
|
DECLARE_XAM_EXPORT1(XamShowMessageBoxUIEx, kUI, kImplemented);
|
||||||
|
|
||||||
|
dword_result_t XNotifyQueueUI_entry(dword_t exnq, dword_t dwUserIndex,
|
||||||
|
qword_t qwAreas,
|
||||||
|
lpu16string_t displayText_ptr,
|
||||||
|
lpvoid_t contextData) {
|
||||||
|
std::string displayText = "";
|
||||||
|
|
||||||
|
if (displayText_ptr) {
|
||||||
|
displayText = xe::to_utf8(displayText_ptr.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
XELOGI("XNotifyQueueUI: {}", displayText);
|
||||||
|
|
||||||
|
if (cvars::headless) {
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto close = [](MessageBoxDialog* dialog) -> X_RESULT {
|
||||||
|
dialog->chosen_button();
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> buttons(1, "OK");
|
||||||
|
|
||||||
|
const Emulator* emulator = kernel_state()->emulator();
|
||||||
|
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
|
||||||
|
|
||||||
|
xeXamDispatchDialog<MessageBoxDialog>(
|
||||||
|
new MessageBoxDialog(imgui_drawer, "XNotifyQueueUI", displayText, buttons,
|
||||||
|
0),
|
||||||
|
close, false);
|
||||||
|
|
||||||
|
// XNotifyQueueUI -> XNotifyQueueUIEx -> XMsgProcessRequest ->
|
||||||
|
// XMsgStartIORequestEx & XMsgInProcessCall
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XNotifyQueueUI, kUI, kSketchy);
|
||||||
|
|
||||||
class KeyboardInputDialog : public XamDialog {
|
class KeyboardInputDialog : public XamDialog {
|
||||||
public:
|
public:
|
||||||
KeyboardInputDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title,
|
KeyboardInputDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "xboxkrnl_modules.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "xenia/kernel/kernel_state.h"
|
#include "xenia/kernel/kernel_state.h"
|
||||||
|
@ -39,14 +40,14 @@ dword_result_t XexCheckExecutablePrivilege_entry(dword_t privilege) {
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(XexCheckExecutablePrivilege, kModules, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(XexCheckExecutablePrivilege, kModules, kImplemented);
|
||||||
|
|
||||||
dword_result_t XexGetModuleHandle_entry(lpstring_t module_name,
|
dword_result_t XexGetModuleHandle(std::string module_name,
|
||||||
lpdword_t hmodule_ptr) {
|
xe::be<uint32_t>* hmodule_ptr) {
|
||||||
object_ref<XModule> module;
|
object_ref<XModule> module;
|
||||||
|
|
||||||
if (!module_name) {
|
if (module_name.empty()) {
|
||||||
module = kernel_state()->GetExecutableModule();
|
module = kernel_state()->GetExecutableModule();
|
||||||
} else {
|
} else {
|
||||||
module = kernel_state()->GetModule(module_name.value());
|
module = kernel_state()->GetModule(module_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!module) {
|
if (!module) {
|
||||||
|
@ -59,6 +60,11 @@ dword_result_t XexGetModuleHandle_entry(lpstring_t module_name,
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t XexGetModuleHandle_entry(lpstring_t module_name,
|
||||||
|
lpdword_t hmodule_ptr) {
|
||||||
|
return XexGetModuleHandle(module_name.value(), hmodule_ptr);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(XexGetModuleHandle, kModules, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(XexGetModuleHandle, kModules, kImplemented);
|
||||||
|
|
||||||
dword_result_t XexGetModuleSection_entry(lpvoid_t hmodule, lpstring_t name,
|
dword_result_t XexGetModuleSection_entry(lpvoid_t hmodule, lpstring_t name,
|
||||||
|
@ -119,6 +125,15 @@ dword_result_t XexLoadImage_entry(lpstring_t module_name, dword_t module_flags,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(XexLoadImage, kModules, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(XexLoadImage, kModules, kImplemented);
|
||||||
|
|
||||||
|
dword_result_t XexLoadExecutable_entry(lpstring_t module_name,
|
||||||
|
dword_t module_flags,
|
||||||
|
dword_t min_version,
|
||||||
|
lpdword_t hmodule_ptr) {
|
||||||
|
return XexLoadImage_entry(module_name, module_flags, min_version,
|
||||||
|
hmodule_ptr);
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(XexLoadExecutable, kModules, kSketchy);
|
||||||
|
|
||||||
dword_result_t XexUnloadImage_entry(lpvoid_t hmodule) {
|
dword_result_t XexUnloadImage_entry(lpvoid_t hmodule) {
|
||||||
auto module = XModule::GetFromHModule(kernel_state(), hmodule);
|
auto module = XModule::GetFromHModule(kernel_state(), hmodule);
|
||||||
if (!module) {
|
if (!module) {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2023 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULES_H_
|
||||||
|
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULES_H_
|
||||||
|
|
||||||
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
dword_result_t XexGetModuleHandle(std::string module_name,
|
||||||
|
xe::be<uint32_t>* hmodule_ptr);
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULES_H_
|
|
@ -256,9 +256,11 @@ dword_result_t NtDuplicateObject_entry(dword_t handle, lpdword_t new_handle_ptr,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtDuplicateObject, kNone, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtDuplicateObject, kNone, kImplemented);
|
||||||
|
|
||||||
dword_result_t NtClose_entry(dword_t handle) {
|
uint32_t NtClose(uint32_t handle) {
|
||||||
return kernel_state()->object_table()->ReleaseHandle(handle);
|
return kernel_state()->object_table()->ReleaseHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t NtClose_entry(dword_t handle) { return NtClose(handle); }
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtClose, kNone, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtClose, kNone, kImplemented);
|
||||||
|
|
||||||
} // namespace xboxkrnl
|
} // namespace xboxkrnl
|
||||||
|
|
|
@ -96,12 +96,10 @@ object_ref<T> LookupNamedObject(KernelState* kernel_state,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
|
uint32_t ExCreateThread(xe::be<uint32_t>* handle_ptr, uint32_t stack_size,
|
||||||
lpdword_t thread_id_ptr,
|
xe::be<uint32_t>* thread_id_ptr,
|
||||||
dword_t xapi_thread_startup,
|
uint32_t xapi_thread_startup, uint32_t start_address,
|
||||||
lpvoid_t start_address,
|
uint32_t start_context, uint32_t creation_flags) {
|
||||||
lpvoid_t start_context,
|
|
||||||
dword_t creation_flags) {
|
|
||||||
// Invalid Link
|
// Invalid Link
|
||||||
// http://jafile.com/uploads/scoop/main.cpp.txt
|
// http://jafile.com/uploads/scoop/main.cpp.txt
|
||||||
// DWORD
|
// DWORD
|
||||||
|
@ -126,8 +124,7 @@ dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
|
||||||
|
|
||||||
auto thread = object_ref<XThread>(
|
auto thread = object_ref<XThread>(
|
||||||
new XThread(kernel_state(), actual_stack_size, xapi_thread_startup,
|
new XThread(kernel_state(), actual_stack_size, xapi_thread_startup,
|
||||||
start_address.guest_address(), start_context.guest_address(),
|
start_address, start_context, creation_flags, true));
|
||||||
creation_flags, true));
|
|
||||||
|
|
||||||
X_STATUS result = thread->Create();
|
X_STATUS result = thread->Create();
|
||||||
if (XFAILED(result)) {
|
if (XFAILED(result)) {
|
||||||
|
@ -150,18 +147,32 @@ dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
|
||||||
|
lpdword_t thread_id_ptr,
|
||||||
|
dword_t xapi_thread_startup,
|
||||||
|
lpvoid_t start_address,
|
||||||
|
lpvoid_t start_context,
|
||||||
|
dword_t creation_flags) {
|
||||||
|
return ExCreateThread(handle_ptr, stack_size, thread_id_ptr,
|
||||||
|
xapi_thread_startup, start_address, start_context,
|
||||||
|
creation_flags);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(ExCreateThread, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(ExCreateThread, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t ExTerminateThread_entry(dword_t exit_code) {
|
uint32_t ExTerminateThread(uint32_t exit_code) {
|
||||||
XThread* thread = XThread::GetCurrentThread();
|
XThread* thread = XThread::GetCurrentThread();
|
||||||
|
|
||||||
// NOTE: this kills us right now. We won't return from it.
|
// NOTE: this kills us right now. We won't return from it.
|
||||||
return thread->Exit(exit_code);
|
return thread->Exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t ExTerminateThread_entry(dword_t exit_code) {
|
||||||
|
return ExTerminateThread(exit_code);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(ExTerminateThread, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(ExTerminateThread, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t NtResumeThread_entry(dword_t handle,
|
uint32_t NtResumeThread(uint32_t handle, uint32_t* suspend_count_ptr) {
|
||||||
lpdword_t suspend_count_ptr) {
|
|
||||||
X_RESULT result = X_STATUS_INVALID_HANDLE;
|
X_RESULT result = X_STATUS_INVALID_HANDLE;
|
||||||
uint32_t suspend_count = 0;
|
uint32_t suspend_count = 0;
|
||||||
|
|
||||||
|
@ -170,7 +181,6 @@ dword_result_t NtResumeThread_entry(dword_t handle,
|
||||||
if (thread) {
|
if (thread) {
|
||||||
if (thread->type() == XObject::Type::Thread) {
|
if (thread->type() == XObject::Type::Thread) {
|
||||||
result = thread->Resume(&suspend_count);
|
result = thread->Resume(&suspend_count);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return X_STATUS_OBJECT_TYPE_MISMATCH;
|
return X_STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
@ -183,6 +193,13 @@ dword_result_t NtResumeThread_entry(dword_t handle,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t NtResumeThread_entry(dword_t handle,
|
||||||
|
lpdword_t suspend_count_ptr) {
|
||||||
|
uint32_t suspend_count =
|
||||||
|
suspend_count_ptr ? static_cast<uint32_t>(*suspend_count_ptr) : 0u;
|
||||||
|
return NtResumeThread(handle, suspend_count_ptr ? &suspend_count : nullptr);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t KeResumeThread_entry(pointer_t<X_KTHREAD> thread_ptr) {
|
dword_result_t KeResumeThread_entry(pointer_t<X_KTHREAD> thread_ptr) {
|
||||||
|
@ -232,7 +249,8 @@ DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t KeSuspendThread_entry(pointer_t<X_KTHREAD> kthread,
|
dword_result_t KeSuspendThread_entry(pointer_t<X_KTHREAD> kthread,
|
||||||
const ppc_context_t& context) {
|
const ppc_context_t& context) {
|
||||||
auto thread = XObject::GetNativeObject<XThread>(context->kernel_state, kthread);
|
auto thread =
|
||||||
|
XObject::GetNativeObject<XThread>(context->kernel_state, kthread);
|
||||||
uint32_t suspend_count_out = 0;
|
uint32_t suspend_count_out = 0;
|
||||||
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
|
@ -254,7 +272,7 @@ void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
|
||||||
auto current_thread = XThread::GetCurrentThread();
|
auto current_thread = XThread::GetCurrentThread();
|
||||||
|
|
||||||
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
||||||
//also supposed to load msr mask, and the current msr with that, and store
|
// also supposed to load msr mask, and the current msr with that, and store
|
||||||
thread->stack_alloc_base = stack_alloc_base.value();
|
thread->stack_alloc_base = stack_alloc_base.value();
|
||||||
thread->stack_base = stack_base.value();
|
thread->stack_base = stack_base.value();
|
||||||
thread->stack_limit = stack_limit.value();
|
thread->stack_limit = stack_limit.value();
|
||||||
|
@ -352,8 +370,7 @@ dword_result_t KeQueryPerformanceFrequency_entry() {
|
||||||
DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
|
DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
|
||||||
kHighFrequency);
|
kHighFrequency);
|
||||||
|
|
||||||
uint32_t KeDelayExecutionThread(uint32_t processor_mode,
|
uint32_t KeDelayExecutionThread(uint32_t processor_mode, uint32_t alertable,
|
||||||
uint32_t alertable,
|
|
||||||
uint64_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);
|
||||||
|
@ -387,7 +404,7 @@ void KeQuerySystemTime_entry(lpqword_t time_ptr, const ppc_context_t& ctx) {
|
||||||
// something uses this function, but also reads it directly
|
// something uses this function, but also reads it directly
|
||||||
uint32_t ts_bundle = ctx->kernel_state->GetKeTimestampBundle();
|
uint32_t ts_bundle = ctx->kernel_state->GetKeTimestampBundle();
|
||||||
uint64_t time = Clock::QueryGuestSystemTime();
|
uint64_t time = Clock::QueryGuestSystemTime();
|
||||||
//todo: cmpxchg?
|
// todo: cmpxchg?
|
||||||
xe::store_and_swap<uint64_t>(
|
xe::store_and_swap<uint64_t>(
|
||||||
&ctx->TranslateVirtual<X_TIME_STAMP_BUNDLE*>(ts_bundle)->system_time,
|
&ctx->TranslateVirtual<X_TIME_STAMP_BUNDLE*>(ts_bundle)->system_time,
|
||||||
time);
|
time);
|
||||||
|
@ -534,7 +551,7 @@ uint32_t xeNtSetEvent(uint32_t handle, xe::be<uint32_t>* previous_state_ptr) {
|
||||||
|
|
||||||
auto ev = kernel_state()->object_table()->LookupObject<XEvent>(handle);
|
auto ev = kernel_state()->object_table()->LookupObject<XEvent>(handle);
|
||||||
if (ev) {
|
if (ev) {
|
||||||
//d3 ros does this
|
// d3 ros does this
|
||||||
if (ev->type() != XObject::Type::Event) {
|
if (ev->type() != XObject::Type::Event) {
|
||||||
return X_STATUS_OBJECT_TYPE_MISMATCH;
|
return X_STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
@ -583,7 +600,6 @@ dword_result_t NtQueryEvent_entry(dword_t handle, lpdword_t out_struc) {
|
||||||
|
|
||||||
out_struc[0] = type_tmp;
|
out_struc[0] = type_tmp;
|
||||||
out_struc[1] = state_tmp;
|
out_struc[1] = state_tmp;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -881,10 +897,8 @@ dword_result_t KeWaitForSingleObject_entry(lpvoid_t object_ptr,
|
||||||
DECLARE_XBOXKRNL_EXPORT3(KeWaitForSingleObject, kThreading, kImplemented,
|
DECLARE_XBOXKRNL_EXPORT3(KeWaitForSingleObject, kThreading, kImplemented,
|
||||||
kBlocking, kHighFrequency);
|
kBlocking, kHighFrequency);
|
||||||
|
|
||||||
dword_result_t NtWaitForSingleObjectEx_entry(dword_t object_handle,
|
uint32_t NtWaitForSingleObjectEx(uint32_t object_handle, uint32_t wait_mode,
|
||||||
dword_t wait_mode,
|
uint32_t alertable, uint64_t* timeout_ptr) {
|
||||||
dword_t alertable,
|
|
||||||
lpqword_t timeout_ptr) {
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
|
|
||||||
auto object =
|
auto object =
|
||||||
|
@ -899,6 +913,15 @@ dword_result_t NtWaitForSingleObjectEx_entry(dword_t object_handle,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t NtWaitForSingleObjectEx_entry(dword_t object_handle,
|
||||||
|
dword_t wait_mode,
|
||||||
|
dword_t alertable,
|
||||||
|
lpqword_t timeout_ptr) {
|
||||||
|
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
|
||||||
|
return NtWaitForSingleObjectEx(object_handle, wait_mode, alertable,
|
||||||
|
timeout_ptr ? &timeout : nullptr);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT3(NtWaitForSingleObjectEx, kThreading, kImplemented,
|
DECLARE_XBOXKRNL_EXPORT3(NtWaitForSingleObjectEx, kThreading, kImplemented,
|
||||||
kBlocking, kHighFrequency);
|
kBlocking, kHighFrequency);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct X_KEVENT;
|
||||||
namespace xboxkrnl {
|
namespace xboxkrnl {
|
||||||
|
|
||||||
uint32_t xeNtSetEvent(uint32_t handle, xe::be<uint32_t>* previous_state_ptr);
|
uint32_t xeNtSetEvent(uint32_t handle, xe::be<uint32_t>* previous_state_ptr);
|
||||||
|
|
||||||
uint32_t xeNtClearEvent(uint32_t handle);
|
uint32_t xeNtClearEvent(uint32_t handle);
|
||||||
|
|
||||||
uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be<uint32_t>* handles,
|
uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be<uint32_t>* handles,
|
||||||
|
@ -30,12 +31,26 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be<uint32_t>* handles,
|
||||||
uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason,
|
uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason,
|
||||||
uint32_t processor_mode, uint32_t alertable,
|
uint32_t processor_mode, uint32_t alertable,
|
||||||
uint64_t* timeout_ptr);
|
uint64_t* timeout_ptr);
|
||||||
|
|
||||||
|
uint32_t NtWaitForSingleObjectEx(uint32_t object_handle, uint32_t wait_mode,
|
||||||
|
uint32_t alertable, 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 KeDelayExecutionThread(uint32_t processor_mode, uint32_t alertable,
|
||||||
uint32_t alertable,
|
|
||||||
uint64_t* interval_ptr);
|
uint64_t* interval_ptr);
|
||||||
|
|
||||||
|
uint32_t ExCreateThread(xe::be<uint32_t>* handle_ptr, uint32_t stack_size,
|
||||||
|
xe::be<uint32_t>* thread_id_ptr,
|
||||||
|
uint32_t xapi_thread_startup, uint32_t start_address,
|
||||||
|
uint32_t start_context, uint32_t creation_flags);
|
||||||
|
|
||||||
|
uint32_t ExTerminateThread(uint32_t exit_code);
|
||||||
|
|
||||||
|
uint32_t NtResumeThread(uint32_t handle, uint32_t* suspend_count_ptr);
|
||||||
|
|
||||||
|
uint32_t NtClose(uint32_t handle);
|
||||||
|
|
||||||
} // namespace xboxkrnl
|
} // namespace xboxkrnl
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
Loading…
Reference in New Issue