Merge branch 'master' into d3d12
This commit is contained in:
commit
e6bd8f37aa
|
@ -242,10 +242,20 @@ int InstrEmit_fcfidx(PPCHIRBuilder& f, const InstrData& i) {
|
||||||
|
|
||||||
int InstrEmit_fctidxx_(PPCHIRBuilder& f, const InstrData& i,
|
int InstrEmit_fctidxx_(PPCHIRBuilder& f, const InstrData& i,
|
||||||
RoundMode round_mode) {
|
RoundMode round_mode) {
|
||||||
Value* v = f.Convert(f.LoadFPR(i.X.RB), INT64_TYPE, round_mode);
|
auto end = f.NewLabel();
|
||||||
|
auto isnan = f.NewLabel();
|
||||||
|
Value* v;
|
||||||
|
f.BranchTrue(f.IsNan(f.LoadFPR(i.X.RB)), isnan);
|
||||||
|
v = f.Convert(f.LoadFPR(i.X.RB), INT64_TYPE, round_mode);
|
||||||
v = f.Cast(v, FLOAT64_TYPE);
|
v = f.Cast(v, FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
f.UpdateFPSCR(v, i.X.Rc);
|
f.UpdateFPSCR(v, i.X.Rc);
|
||||||
|
f.Branch(end);
|
||||||
|
f.MarkLabel(isnan);
|
||||||
|
v = f.Cast(f.LoadConstantUint64(0x8000000000000000u), FLOAT64_TYPE);
|
||||||
|
f.StoreFPR(i.X.RT, v);
|
||||||
|
f.UpdateFPSCR(v, i.X.Rc);
|
||||||
|
f.MarkLabel(end);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,10 +270,20 @@ int InstrEmit_fctidzx(PPCHIRBuilder& f, const InstrData& i) {
|
||||||
|
|
||||||
int InstrEmit_fctiwxx_(PPCHIRBuilder& f, const InstrData& i,
|
int InstrEmit_fctiwxx_(PPCHIRBuilder& f, const InstrData& i,
|
||||||
RoundMode round_mode) {
|
RoundMode round_mode) {
|
||||||
Value* v = f.Convert(f.LoadFPR(i.X.RB), INT32_TYPE, round_mode);
|
auto end = f.NewLabel();
|
||||||
|
auto isnan = f.NewLabel();
|
||||||
|
Value* v;
|
||||||
|
f.BranchTrue(f.IsNan(f.LoadFPR(i.X.RB)), isnan);
|
||||||
|
v = f.Convert(f.LoadFPR(i.X.RB), INT32_TYPE, round_mode);
|
||||||
v = f.Cast(f.SignExtend(v, INT64_TYPE), FLOAT64_TYPE);
|
v = f.Cast(f.SignExtend(v, INT64_TYPE), FLOAT64_TYPE);
|
||||||
f.StoreFPR(i.X.RT, v);
|
f.StoreFPR(i.X.RT, v);
|
||||||
f.UpdateFPSCR(v, i.X.Rc);
|
f.UpdateFPSCR(v, i.X.Rc);
|
||||||
|
f.Branch(end);
|
||||||
|
f.MarkLabel(isnan);
|
||||||
|
v = f.Cast(f.LoadConstantUint32(0x80000000u), FLOAT64_TYPE);
|
||||||
|
f.StoreFPR(i.X.RT, v);
|
||||||
|
f.UpdateFPSCR(v, i.X.Rc);
|
||||||
|
f.MarkLabel(end);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "xenia/kernel/xfile.h"
|
#include "xenia/kernel/xfile.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
|
|
||||||
|
DEFINE_bool(xex_apply_patches, true, "Apply XEX patches.");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
|
||||||
|
@ -100,27 +102,29 @@ X_STATUS UserModule::LoadFromFile(std::string path) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for xexp patch file
|
if (FLAGS_xex_apply_patches) {
|
||||||
auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p");
|
// Search for xexp patch file
|
||||||
|
auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p");
|
||||||
|
|
||||||
if (patch_entry) {
|
if (patch_entry) {
|
||||||
auto patch_path = patch_entry->absolute_path();
|
auto patch_path = patch_entry->absolute_path();
|
||||||
|
|
||||||
XELOGI("Loading XEX patch from %s", patch_path.c_str());
|
XELOGI("Loading XEX patch from %s", patch_path.c_str());
|
||||||
|
|
||||||
auto patch_module = object_ref<UserModule>(new UserModule(kernel_state_));
|
auto patch_module = object_ref<UserModule>(new UserModule(kernel_state_));
|
||||||
result = patch_module->LoadFromFile(patch_path);
|
result = patch_module->LoadFromFile(patch_path);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = patch_module->xex_module()->ApplyPatch(xex_module());
|
result = patch_module->xex_module()->ApplyPatch(xex_module());
|
||||||
if (result) {
|
if (result) {
|
||||||
XELOGE("Failed to apply XEX patch, code: %d", result);
|
XELOGE("Failed to apply XEX patch, code: %d", result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XELOGE("Failed to load XEX patch, code: %d", result);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
XELOGE("Failed to load XEX patch, code: %d", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return X_STATUS_UNSUCCESSFUL;
|
return X_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,8 +180,6 @@ dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name,
|
||||||
lpdword_t license_mask_ptr,
|
lpdword_t license_mask_ptr,
|
||||||
dword_t cache_size, qword_t content_size,
|
dword_t cache_size, qword_t content_size,
|
||||||
lpvoid_t overlapped_ptr) {
|
lpvoid_t overlapped_ptr) {
|
||||||
assert_null(license_mask_ptr);
|
|
||||||
|
|
||||||
X_RESULT result = X_ERROR_INVALID_PARAMETER;
|
X_RESULT result = X_ERROR_INVALID_PARAMETER;
|
||||||
auto content_data = XCONTENT_DATA((uint8_t*)content_data_ptr);
|
auto content_data = XCONTENT_DATA((uint8_t*)content_data_ptr);
|
||||||
|
|
||||||
|
@ -256,6 +254,10 @@ dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name,
|
||||||
result = content_manager->OpenContent(root_name.value(), content_data);
|
result = content_manager->OpenContent(root_name.value(), content_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (license_mask_ptr && XSUCCEEDED(result)) {
|
||||||
|
*license_mask_ptr = 0; // Stub!
|
||||||
|
}
|
||||||
|
|
||||||
if (overlapped_ptr) {
|
if (overlapped_ptr) {
|
||||||
kernel_state()->CompleteOverlappedImmediateEx(overlapped_ptr, result, 0,
|
kernel_state()->CompleteOverlappedImmediateEx(overlapped_ptr, result, 0,
|
||||||
disposition);
|
disposition);
|
||||||
|
@ -421,8 +423,7 @@ dword_result_t XamContentDelete(dword_t user_index, lpvoid_t content_data_ptr,
|
||||||
DECLARE_XAM_EXPORT1(XamContentDelete, kContent, kImplemented);
|
DECLARE_XAM_EXPORT1(XamContentDelete, kContent, kImplemented);
|
||||||
|
|
||||||
void RegisterContentExports(xe::cpu::ExportResolver* export_resolver,
|
void RegisterContentExports(xe::cpu::ExportResolver* export_resolver,
|
||||||
KernelState* kernel_state) {
|
KernelState* kernel_state) {}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
|
@ -23,11 +23,8 @@ namespace xam {
|
||||||
|
|
||||||
std::atomic<int> xam_dialogs_shown_ = {0};
|
std::atomic<int> xam_dialogs_shown_ = {0};
|
||||||
|
|
||||||
SHIM_CALL XamIsUIActive_shim(PPCContext* ppc_context,
|
dword_result_t XamIsUIActive() { return xam_dialogs_shown_ > 0 ? 1 : 0; }
|
||||||
KernelState* kernel_state) {
|
DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency);
|
||||||
XELOGD("XamIsUIActive()");
|
|
||||||
SHIM_SET_RETURN_32(xam_dialogs_shown_ > 0 ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessageBoxDialog : public xe::ui::ImGuiDialog {
|
class MessageBoxDialog : public xe::ui::ImGuiDialog {
|
||||||
public:
|
public:
|
||||||
|
@ -87,30 +84,25 @@ class MessageBoxDialog : public xe::ui::ImGuiDialog {
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/?jdfwkey=sb0vm
|
// http://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/?jdfwkey=sb0vm
|
||||||
SHIM_CALL XamShowMessageBoxUI_shim(PPCContext* ppc_context,
|
dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
|
||||||
KernelState* kernel_state) {
|
lpwstring_t text_ptr, dword_t button_count,
|
||||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
lpdword_t button_ptrs, dword_t active_button,
|
||||||
uint32_t title_ptr = SHIM_GET_ARG_32(1);
|
dword_t flags, lpdword_t result_ptr,
|
||||||
uint32_t text_ptr = SHIM_GET_ARG_32(2);
|
pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||||
uint32_t button_count = SHIM_GET_ARG_32(3);
|
|
||||||
uint32_t button_ptrs = SHIM_GET_ARG_32(4);
|
|
||||||
uint32_t active_button = SHIM_GET_ARG_32(5);
|
|
||||||
uint32_t flags = SHIM_GET_ARG_32(6);
|
|
||||||
uint32_t result_ptr = SHIM_GET_ARG_32(7);
|
|
||||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(8);
|
|
||||||
|
|
||||||
std::wstring title;
|
std::wstring title;
|
||||||
if (title_ptr) {
|
if (title_ptr) {
|
||||||
title = xe::load_and_swap<std::wstring>(SHIM_MEM_ADDR(title_ptr));
|
title = title_ptr.value();
|
||||||
} else {
|
} else {
|
||||||
title = L""; // TODO(gibbed): default title based on flags?
|
title = L""; // TODO(gibbed): default title based on flags?
|
||||||
}
|
}
|
||||||
auto text = xe::load_and_swap<std::wstring>(SHIM_MEM_ADDR(text_ptr));
|
auto text = text_ptr.value();
|
||||||
|
|
||||||
std::vector<std::wstring> buttons;
|
std::vector<std::wstring> buttons;
|
||||||
std::wstring all_buttons;
|
std::wstring all_buttons;
|
||||||
for (uint32_t j = 0; j < button_count; ++j) {
|
for (uint32_t j = 0; j < button_count; ++j) {
|
||||||
uint32_t button_ptr = SHIM_MEM_32(button_ptrs + j * 4);
|
uint32_t button_ptr = button_ptrs[j];
|
||||||
auto button = xe::load_and_swap<std::wstring>(SHIM_MEM_ADDR(button_ptr));
|
auto button = xe::load_and_swap<std::wstring>(
|
||||||
|
kernel_state()->memory()->TranslateVirtual(button_ptr));
|
||||||
all_buttons.append(button);
|
all_buttons.append(button);
|
||||||
if (j + 1 < button_count) {
|
if (j + 1 < button_count) {
|
||||||
all_buttons.append(L" | ");
|
all_buttons.append(L" | ");
|
||||||
|
@ -118,19 +110,12 @@ SHIM_CALL XamShowMessageBoxUI_shim(PPCContext* ppc_context,
|
||||||
buttons.push_back(button);
|
buttons.push_back(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
XELOGD(
|
|
||||||
"XamShowMessageBoxUI(%d, %.8X(%S), %.8X(%S), %d, %.8X(%S), %d, %X, %.8X, "
|
|
||||||
"%.8X)",
|
|
||||||
user_index, title_ptr, title.c_str(), text_ptr, text.c_str(),
|
|
||||||
button_count, button_ptrs, all_buttons.c_str(), active_button, flags,
|
|
||||||
result_ptr, overlapped_ptr);
|
|
||||||
|
|
||||||
uint32_t chosen_button;
|
uint32_t chosen_button;
|
||||||
if (FLAGS_headless) {
|
if (FLAGS_headless) {
|
||||||
// Auto-pick the focused button.
|
// Auto-pick the focused button.
|
||||||
chosen_button = active_button;
|
chosen_button = active_button;
|
||||||
} else {
|
} else {
|
||||||
auto display_window = kernel_state->emulator()->display_window();
|
auto display_window = kernel_state()->emulator()->display_window();
|
||||||
xe::threading::Fence fence;
|
xe::threading::Fence fence;
|
||||||
display_window->loop()->PostSynchronous([&]() {
|
display_window->loop()->PostSynchronous([&]() {
|
||||||
// TODO(benvanik): setup icon states.
|
// TODO(benvanik): setup icon states.
|
||||||
|
@ -156,11 +141,16 @@ SHIM_CALL XamShowMessageBoxUI_shim(PPCContext* ppc_context,
|
||||||
fence.Wait();
|
fence.Wait();
|
||||||
--xam_dialogs_shown_;
|
--xam_dialogs_shown_;
|
||||||
}
|
}
|
||||||
SHIM_SET_MEM_32(result_ptr, chosen_button);
|
*result_ptr = chosen_button;
|
||||||
|
|
||||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
if (overlapped) {
|
||||||
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
|
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
||||||
|
return X_ERROR_IO_PENDING;
|
||||||
|
} else {
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamShowMessageBoxUI, kUI, kImplemented);
|
||||||
|
|
||||||
class KeyboardInputDialog : public xe::ui::ImGuiDialog {
|
class KeyboardInputDialog : public xe::ui::ImGuiDialog {
|
||||||
public:
|
public:
|
||||||
|
@ -318,19 +308,14 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented);
|
DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL XamShowDirtyDiscErrorUI_shim(PPCContext* ppc_context,
|
void XamShowDirtyDiscErrorUI(dword_t user_index) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("XamShowDirtyDiscErrorUI(%d)", user_index);
|
|
||||||
|
|
||||||
if (FLAGS_headless) {
|
if (FLAGS_headless) {
|
||||||
assert_always();
|
assert_always();
|
||||||
exit(1);
|
exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto display_window = kernel_state->emulator()->display_window();
|
auto display_window = kernel_state()->emulator()->display_window();
|
||||||
xe::threading::Fence fence;
|
xe::threading::Fence fence;
|
||||||
display_window->loop()->PostSynchronous([&]() {
|
display_window->loop()->PostSynchronous([&]() {
|
||||||
xe::ui::ImGuiDialog::ShowMessageBox(
|
xe::ui::ImGuiDialog::ShowMessageBox(
|
||||||
|
@ -347,13 +332,10 @@ SHIM_CALL XamShowDirtyDiscErrorUI_shim(PPCContext* ppc_context,
|
||||||
// TODO(benvanik): cleaner exit.
|
// TODO(benvanik): cleaner exit.
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamShowDirtyDiscErrorUI, kUI, kImplemented);
|
||||||
|
|
||||||
void RegisterUIExports(xe::cpu::ExportResolver* export_resolver,
|
void RegisterUIExports(xe::cpu::ExportResolver* export_resolver,
|
||||||
KernelState* kernel_state) {
|
KernelState* kernel_state) {}
|
||||||
SHIM_SET_MAPPING("xam.xex", XamIsUIActive, state);
|
|
||||||
SHIM_SET_MAPPING("xam.xex", XamShowMessageBoxUI, state);
|
|
||||||
SHIM_SET_MAPPING("xam.xex", XamShowDirtyDiscErrorUI, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
|
@ -997,7 +997,7 @@ dword_result_t RtlNtStatusToDosError(dword_t source_status) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
XELOGI("RtlNtStatusToDosError => %X", result);
|
XELOGI("RtlNtStatusToDosError %X => %X", status, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
++error_table;
|
++error_table;
|
||||||
|
@ -1010,7 +1010,8 @@ dword_result_t RtlNtStatusToDosError(dword_t source_status) {
|
||||||
XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED");
|
XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED");
|
||||||
return 317; // ERROR_MR_MID_NOT_FOUND
|
return 317; // ERROR_MR_MID_NOT_FOUND
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT2(RtlNtStatusToDosError, kNone, kImportant, kLogResult);
|
DECLARE_XBOXKRNL_EXPORT3(RtlNtStatusToDosError, kNone, kImportant,
|
||||||
|
kHighFrequency, kLogResult);
|
||||||
|
|
||||||
void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver,
|
void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver,
|
||||||
KernelState* kernel_state) {}
|
KernelState* kernel_state) {}
|
||||||
|
|
|
@ -93,20 +93,11 @@ object_ref<T> LookupNamedObject(KernelState* kernel_state,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context,
|
dword_result_t ExCreateThread(lpdword_t handle_ptr, dword_t stack_size,
|
||||||
KernelState* kernel_state) {
|
lpdword_t thread_id_ptr,
|
||||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
dword_t xapi_thread_startup,
|
||||||
uint32_t stack_size = SHIM_GET_ARG_32(1);
|
lpvoid_t start_address, lpvoid_t start_context,
|
||||||
uint32_t thread_id_ptr = SHIM_GET_ARG_32(2);
|
dword_t creation_flags) {
|
||||||
uint32_t xapi_thread_startup = SHIM_GET_ARG_32(3);
|
|
||||||
uint32_t start_address = SHIM_GET_ARG_32(4);
|
|
||||||
uint32_t start_context = SHIM_GET_ARG_32(5);
|
|
||||||
uint32_t creation_flags = SHIM_GET_ARG_32(6);
|
|
||||||
|
|
||||||
XELOGD("ExCreateThread(%.8X, %d, %.8X, %.8X, %.8X, %.8X, %.8X)", handle_ptr,
|
|
||||||
stack_size, thread_id_ptr, xapi_thread_startup, start_address,
|
|
||||||
start_context, creation_flags);
|
|
||||||
|
|
||||||
// http://jafile.com/uploads/scoop/main.cpp.txt
|
// http://jafile.com/uploads/scoop/main.cpp.txt
|
||||||
// DWORD
|
// DWORD
|
||||||
// LPHANDLE Handle,
|
// LPHANDLE Handle,
|
||||||
|
@ -118,103 +109,86 @@ SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context,
|
||||||
// DWORD CreationFlags // 0x80?
|
// DWORD CreationFlags // 0x80?
|
||||||
|
|
||||||
// Inherit default stack size
|
// Inherit default stack size
|
||||||
if (stack_size == 0) {
|
uint32_t actual_stack_size = stack_size;
|
||||||
stack_size = kernel_state->GetExecutableModule()->stack_size();
|
|
||||||
|
if (actual_stack_size == 0) {
|
||||||
|
actual_stack_size = kernel_state()->GetExecutableModule()->stack_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stack must be aligned to 16kb pages
|
// Stack must be aligned to 16kb pages
|
||||||
stack_size = std::max((uint32_t)0x4000, ((stack_size + 0xFFF) & 0xFFFFF000));
|
actual_stack_size =
|
||||||
|
std::max((uint32_t)0x4000, ((actual_stack_size + 0xFFF) & 0xFFFFF000));
|
||||||
|
|
||||||
auto thread = object_ref<XThread>(
|
auto thread = object_ref<XThread>(
|
||||||
new XThread(kernel_state, stack_size, xapi_thread_startup, start_address,
|
new XThread(kernel_state(), actual_stack_size, xapi_thread_startup,
|
||||||
start_context, creation_flags, true));
|
start_address.guest_address(), start_context.guest_address(),
|
||||||
|
creation_flags, true));
|
||||||
|
|
||||||
X_STATUS result = thread->Create();
|
X_STATUS result = thread->Create();
|
||||||
if (XFAILED(result)) {
|
if (XFAILED(result)) {
|
||||||
// Failed!
|
// Failed!
|
||||||
XELOGE("Thread creation failed: %.8X", result);
|
XELOGE("Thread creation failed: %.8X", result);
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XSUCCEEDED(result)) {
|
if (XSUCCEEDED(result)) {
|
||||||
if (handle_ptr) {
|
if (handle_ptr) {
|
||||||
if (creation_flags & 0x80) {
|
if (creation_flags & 0x80) {
|
||||||
SHIM_SET_MEM_32(handle_ptr, thread->guest_object());
|
*handle_ptr = thread->guest_object();
|
||||||
} else {
|
} else {
|
||||||
SHIM_SET_MEM_32(handle_ptr, thread->handle());
|
*handle_ptr = thread->handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (thread_id_ptr) {
|
if (thread_id_ptr) {
|
||||||
SHIM_SET_MEM_32(thread_id_ptr, thread->thread_id());
|
*thread_id_ptr = thread->thread_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(ExCreateThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL ExTerminateThread_shim(PPCContext* ppc_context,
|
dword_result_t ExTerminateThread(dword_t exit_code) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t exit_code = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("ExTerminateThread(%d)", 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.
|
||||||
X_STATUS result = thread->Exit(exit_code);
|
return thread->Exit(exit_code);
|
||||||
SHIM_SET_RETURN_32(result);
|
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(ExTerminateThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtResumeThread_shim(PPCContext* ppc_context,
|
dword_result_t NtResumeThread(dword_t handle, lpdword_t suspend_count_ptr) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t suspend_count_ptr = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("NtResumeThread(%.8X, %.8X)", handle, 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;
|
||||||
|
|
||||||
auto thread = kernel_state->object_table()->LookupObject<XThread>(handle);
|
auto thread = kernel_state()->object_table()->LookupObject<XThread>(handle);
|
||||||
if (thread) {
|
if (thread) {
|
||||||
result = thread->Resume(&suspend_count);
|
result = thread->Resume(&suspend_count);
|
||||||
}
|
}
|
||||||
if (suspend_count_ptr) {
|
if (suspend_count_ptr) {
|
||||||
SHIM_SET_MEM_32(suspend_count_ptr, suspend_count);
|
*suspend_count_ptr = suspend_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeResumeThread_shim(PPCContext* ppc_context,
|
dword_result_t KeResumeThread(lpvoid_t thread_ptr) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("KeResumeThread(%.8X)", thread_ptr);
|
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
SHIM_MEM_ADDR(thread_ptr));
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
result = thread->Resume();
|
result = thread->Resume();
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeResumeThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtSuspendThread_shim(PPCContext* ppc_context,
|
dword_result_t NtSuspendThread(dword_t handle, lpdword_t suspend_count_ptr) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t suspend_count_ptr = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("NtSuspendThread(%.8X, %.8X)", handle, suspend_count_ptr);
|
|
||||||
|
|
||||||
X_RESULT result = X_STATUS_SUCCESS;
|
X_RESULT result = X_STATUS_SUCCESS;
|
||||||
uint32_t suspend_count = 0;
|
uint32_t suspend_count = 0;
|
||||||
|
|
||||||
auto thread = kernel_state->object_table()->LookupObject<XThread>(handle);
|
auto thread = kernel_state()->object_table()->LookupObject<XThread>(handle);
|
||||||
if (thread) {
|
if (thread) {
|
||||||
result = thread->Suspend(&suspend_count);
|
result = thread->Suspend(&suspend_count);
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,11 +196,12 @@ SHIM_CALL NtSuspendThread_shim(PPCContext* ppc_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suspend_count_ptr) {
|
if (suspend_count_ptr) {
|
||||||
SHIM_SET_MEM_32(suspend_count_ptr, suspend_count);
|
*suspend_count_ptr = suspend_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
|
||||||
|
|
||||||
void KeSetCurrentStackPointers(lpvoid_t stack_ptr,
|
void KeSetCurrentStackPointers(lpvoid_t stack_ptr,
|
||||||
pointer_t<X_KTHREAD> cur_thread,
|
pointer_t<X_KTHREAD> cur_thread,
|
||||||
|
@ -245,104 +220,72 @@ void KeSetCurrentStackPointers(lpvoid_t stack_ptr,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentStackPointers, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentStackPointers, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeSetAffinityThread_shim(PPCContext* ppc_context,
|
dword_result_t KeSetAffinityThread(lpvoid_t thread_ptr, dword_t affinity) {
|
||||||
KernelState* kernel_state) {
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t affinity = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("KeSetAffinityThread(%.8X, %.8X)", thread_ptr, affinity);
|
|
||||||
|
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
|
|
||||||
SHIM_MEM_ADDR(thread_ptr));
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
thread->SetAffinity(affinity);
|
thread->SetAffinity(affinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(affinity);
|
return (uint32_t)affinity;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeSetAffinityThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeQueryBasePriorityThread_shim(PPCContext* ppc_context,
|
dword_result_t KeQueryBasePriorityThread(lpvoid_t thread_ptr) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("KeQueryBasePriorityThread(%.8X)", thread_ptr);
|
|
||||||
|
|
||||||
int32_t priority = 0;
|
int32_t priority = 0;
|
||||||
|
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
SHIM_MEM_ADDR(thread_ptr));
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
priority = thread->QueryPriority();
|
priority = thread->QueryPriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(priority);
|
return priority;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeQueryBasePriorityThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeSetBasePriorityThread_shim(PPCContext* ppc_context,
|
dword_result_t KeSetBasePriorityThread(lpvoid_t thread_ptr, dword_t increment) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t increment = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("KeSetBasePriorityThread(%.8X, %.8X)", thread_ptr, increment);
|
|
||||||
|
|
||||||
int32_t prev_priority = 0;
|
int32_t prev_priority = 0;
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
SHIM_MEM_ADDR(thread_ptr));
|
|
||||||
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
prev_priority = thread->QueryPriority();
|
prev_priority = thread->QueryPriority();
|
||||||
thread->SetPriority(increment);
|
thread->SetPriority(increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(prev_priority);
|
return prev_priority;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeSetBasePriorityThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeSetDisableBoostThread_shim(PPCContext* ppc_context,
|
dword_result_t KeSetDisableBoostThread(lpvoid_t thread_ptr, dword_t disabled) {
|
||||||
KernelState* kernel_state) {
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t disabled = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("KeSetDisableBoostThread(%.8X, %.8X)", thread_ptr, disabled);
|
|
||||||
|
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
|
|
||||||
SHIM_MEM_ADDR(thread_ptr));
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
// Uhm?
|
// Uhm?
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeSetDisableBoostThread, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeGetCurrentProcessType_shim(PPCContext* ppc_context,
|
dword_result_t KeGetCurrentProcessType() {
|
||||||
KernelState* kernel_state) {
|
return kernel_state()->process_type();
|
||||||
// XELOGD(
|
|
||||||
// "KeGetCurrentProcessType()");
|
|
||||||
|
|
||||||
// DWORD
|
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(kernel_state->process_type());
|
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeGetCurrentProcessType, kThreading, kImplemented,
|
||||||
|
kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL KeSetCurrentProcessType_shim(PPCContext* ppc_context,
|
void KeSetCurrentProcessType(dword_t type) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t type = SHIM_GET_ARG_32(0);
|
|
||||||
// One of X_PROCTYPE_?
|
// One of X_PROCTYPE_?
|
||||||
|
|
||||||
XELOGD("KeSetCurrentProcessType(%d)", type);
|
|
||||||
|
|
||||||
assert_true(type <= 2);
|
assert_true(type <= 2);
|
||||||
|
|
||||||
kernel_state->set_process_type(type);
|
kernel_state()->set_process_type(type);
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentProcessType, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeQueryPerformanceFrequency_shim(PPCContext* ppc_context,
|
dword_result_t KeQueryPerformanceFrequency() {
|
||||||
KernelState* kernel_state) {
|
|
||||||
// XELOGD(
|
|
||||||
// "KeQueryPerformanceFrequency()");
|
|
||||||
|
|
||||||
uint64_t result = Clock::guest_tick_frequency();
|
uint64_t result = Clock::guest_tick_frequency();
|
||||||
SHIM_SET_RETURN_32(result);
|
return static_cast<uint32_t>(result);
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
|
||||||
|
kHighFrequency);
|
||||||
|
|
||||||
dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
|
dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
|
||||||
lpqword_t interval_ptr) {
|
lpqword_t interval_ptr) {
|
||||||
|
@ -354,25 +297,21 @@ dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
|
||||||
DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented,
|
DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented,
|
||||||
kBlocking, kHighFrequency);
|
kBlocking, kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL NtYieldExecution_shim(PPCContext* ppc_context,
|
dword_result_t NtYieldExecution() {
|
||||||
KernelState* kernel_state) {
|
|
||||||
// XELOGD("NtYieldExecution()");
|
|
||||||
auto thread = XThread::GetCurrentThread();
|
auto thread = XThread::GetCurrentThread();
|
||||||
thread->Delay(0, 0, 0);
|
thread->Delay(0, 0, 0);
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(NtYieldExecution, kThreading, kImplemented,
|
||||||
|
kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL KeQuerySystemTime_shim(PPCContext* ppc_context,
|
void KeQuerySystemTime(lpqword_t time_ptr) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t time_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("KeQuerySystemTime(%.8X)", time_ptr);
|
|
||||||
|
|
||||||
uint64_t time = Clock::QueryGuestSystemTime();
|
uint64_t time = Clock::QueryGuestSystemTime();
|
||||||
if (time_ptr) {
|
if (time_ptr) {
|
||||||
SHIM_SET_MEM_64(time_ptr, time);
|
*time_ptr = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeQuerySystemTime, kThreading, kImplemented);
|
||||||
|
|
||||||
// http://msdn.microsoft.com/en-us/library/ms686801
|
// http://msdn.microsoft.com/en-us/library/ms686801
|
||||||
dword_result_t KeTlsAlloc() {
|
dword_result_t KeTlsAlloc() {
|
||||||
|
@ -586,34 +525,26 @@ dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
|
dword_result_t NtCreateSemaphore(lpdword_t handle_ptr,
|
||||||
KernelState* kernel_state) {
|
lpvoid_t obj_attributes_ptr, dword_t count,
|
||||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
dword_t limit) {
|
||||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
|
|
||||||
int32_t count = SHIM_GET_ARG_32(2);
|
|
||||||
int32_t limit = SHIM_GET_ARG_32(3);
|
|
||||||
|
|
||||||
XELOGD("NtCreateSemaphore(%.8X, %.8X, %d, %d)", handle_ptr,
|
|
||||||
obj_attributes_ptr, count, limit);
|
|
||||||
|
|
||||||
// Check for an existing timer with the same name.
|
// Check for an existing timer with the same name.
|
||||||
auto existing_object =
|
auto existing_object =
|
||||||
LookupNamedObject<XSemaphore>(kernel_state, obj_attributes_ptr);
|
LookupNamedObject<XSemaphore>(kernel_state(), obj_attributes_ptr);
|
||||||
if (existing_object) {
|
if (existing_object) {
|
||||||
if (existing_object->type() == XObject::kTypeSemaphore) {
|
if (existing_object->type() == XObject::kTypeSemaphore) {
|
||||||
if (handle_ptr) {
|
if (handle_ptr) {
|
||||||
existing_object->RetainHandle();
|
existing_object->RetainHandle();
|
||||||
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
|
*handle_ptr = existing_object->handle();
|
||||||
}
|
}
|
||||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
return X_STATUS_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
|
return X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state));
|
auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state()));
|
||||||
sem->Initialize(count, limit);
|
sem->Initialize((int32_t)count, (int32_t)limit);
|
||||||
|
|
||||||
// obj_attributes may have a name inside of it, if != NULL.
|
// obj_attributes may have a name inside of it, if != NULL.
|
||||||
if (obj_attributes_ptr) {
|
if (obj_attributes_ptr) {
|
||||||
|
@ -621,36 +552,32 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle_ptr) {
|
if (handle_ptr) {
|
||||||
SHIM_SET_MEM_32(handle_ptr, sem->handle());
|
*handle_ptr = sem->handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
return X_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtCreateSemaphore, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context,
|
dword_result_t NtReleaseSemaphore(dword_t sem_handle, dword_t release_count,
|
||||||
KernelState* kernel_state) {
|
lpdword_t previous_count_ptr) {
|
||||||
uint32_t sem_handle = SHIM_GET_ARG_32(0);
|
|
||||||
int32_t release_count = SHIM_GET_ARG_32(1);
|
|
||||||
int32_t previous_count_ptr = SHIM_GET_ARG_32(2);
|
|
||||||
|
|
||||||
XELOGD("NtReleaseSemaphore(%.8X, %d, %.8X)", sem_handle, release_count,
|
|
||||||
previous_count_ptr);
|
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
int32_t previous_count = 0;
|
int32_t previous_count = 0;
|
||||||
|
|
||||||
auto sem = kernel_state->object_table()->LookupObject<XSemaphore>(sem_handle);
|
auto sem =
|
||||||
|
kernel_state()->object_table()->LookupObject<XSemaphore>(sem_handle);
|
||||||
if (sem) {
|
if (sem) {
|
||||||
previous_count = sem->ReleaseSemaphore(release_count);
|
previous_count = sem->ReleaseSemaphore((int32_t)release_count);
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
if (previous_count_ptr) {
|
if (previous_count_ptr) {
|
||||||
SHIM_SET_MEM_32(previous_count_ptr, previous_count);
|
*previous_count_ptr = (uint32_t)previous_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtReleaseSemaphore, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t NtCreateMutant(lpdword_t handle_out,
|
dword_result_t NtCreateMutant(lpdword_t handle_out,
|
||||||
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
|
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
|
||||||
|
@ -686,10 +613,7 @@ dword_result_t NtCreateMutant(lpdword_t handle_out,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtCreateMutant, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtCreateMutant, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context,
|
dword_result_t NtReleaseMutant(dword_t mutant_handle, dword_t unknown) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t mutant_handle = SHIM_GET_ARG_32(0);
|
|
||||||
int32_t unknown = SHIM_GET_ARG_32(1);
|
|
||||||
// This doesn't seem to be supported.
|
// This doesn't seem to be supported.
|
||||||
// int32_t previous_count_ptr = SHIM_GET_ARG_32(2);
|
// int32_t previous_count_ptr = SHIM_GET_ARG_32(2);
|
||||||
|
|
||||||
|
@ -706,44 +630,37 @@ SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context,
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
|
|
||||||
auto mutant =
|
auto mutant =
|
||||||
kernel_state->object_table()->LookupObject<XMutant>(mutant_handle);
|
kernel_state()->object_table()->LookupObject<XMutant>(mutant_handle);
|
||||||
if (mutant) {
|
if (mutant) {
|
||||||
result = mutant->ReleaseMutant(priority_increment, abandon, wait);
|
result = mutant->ReleaseMutant(priority_increment, abandon, wait);
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtReleaseMutant, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context,
|
dword_result_t NtCreateTimer(lpdword_t handle_ptr, lpvoid_t obj_attributes_ptr,
|
||||||
KernelState* kernel_state) {
|
dword_t timer_type) {
|
||||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
|
|
||||||
uint32_t timer_type = SHIM_GET_ARG_32(2);
|
|
||||||
|
|
||||||
// timer_type = NotificationTimer (0) or SynchronizationTimer (1)
|
// timer_type = NotificationTimer (0) or SynchronizationTimer (1)
|
||||||
|
|
||||||
XELOGD("NtCreateTimer(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr,
|
|
||||||
timer_type);
|
|
||||||
|
|
||||||
// Check for an existing timer with the same name.
|
// Check for an existing timer with the same name.
|
||||||
auto existing_object =
|
auto existing_object =
|
||||||
LookupNamedObject<XTimer>(kernel_state, obj_attributes_ptr);
|
LookupNamedObject<XTimer>(kernel_state(), obj_attributes_ptr);
|
||||||
if (existing_object) {
|
if (existing_object) {
|
||||||
if (existing_object->type() == XObject::kTypeTimer) {
|
if (existing_object->type() == XObject::kTypeTimer) {
|
||||||
if (handle_ptr) {
|
if (handle_ptr) {
|
||||||
existing_object->RetainHandle();
|
existing_object->RetainHandle();
|
||||||
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
|
*handle_ptr = existing_object->handle();
|
||||||
}
|
}
|
||||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
return X_STATUS_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
|
return X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto timer = object_ref<XTimer>(new XTimer(kernel_state));
|
auto timer = object_ref<XTimer>(new XTimer(kernel_state()));
|
||||||
timer->Initialize(timer_type);
|
timer->Initialize(timer_type);
|
||||||
|
|
||||||
// obj_attributes may have a name inside of it, if != NULL.
|
// obj_attributes may have a name inside of it, if != NULL.
|
||||||
|
@ -752,66 +669,57 @@ SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle_ptr) {
|
if (handle_ptr) {
|
||||||
SHIM_SET_MEM_32(handle_ptr, timer->handle());
|
*handle_ptr = timer->handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
return X_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtCreateTimer, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtSetTimerEx_shim(PPCContext* ppc_context,
|
dword_result_t NtSetTimerEx(dword_t timer_handle, lpqword_t due_time_ptr,
|
||||||
KernelState* kernel_state) {
|
lpvoid_t routine_ptr /*PTIMERAPCROUTINE*/,
|
||||||
uint32_t timer_handle = SHIM_GET_ARG_32(0);
|
dword_t unk_one, lpvoid_t routine_arg,
|
||||||
uint32_t due_time_ptr = SHIM_GET_ARG_32(1);
|
dword_t resume, dword_t period_ms,
|
||||||
uint32_t routine = SHIM_GET_ARG_32(2); // PTIMERAPCROUTINE
|
dword_t unk_zero) {
|
||||||
uint32_t unk_one = SHIM_GET_ARG_32(3);
|
|
||||||
uint32_t routine_arg = SHIM_GET_ARG_32(4);
|
|
||||||
uint32_t resume = SHIM_GET_ARG_32(5);
|
|
||||||
uint32_t period_ms = SHIM_GET_ARG_32(6);
|
|
||||||
uint32_t unk_zero = SHIM_GET_ARG_32(7);
|
|
||||||
|
|
||||||
assert_true(unk_one == 1);
|
assert_true(unk_one == 1);
|
||||||
assert_true(unk_zero == 0);
|
assert_true(unk_zero == 0);
|
||||||
|
|
||||||
uint64_t due_time = SHIM_MEM_64(due_time_ptr);
|
uint64_t due_time = *due_time_ptr;
|
||||||
|
|
||||||
XELOGD("NtSetTimerEx(%.8X, %.8X(%lld), %.8X, %.8X, %.8X, %.1X, %d, %.8X)",
|
|
||||||
timer_handle, due_time_ptr, due_time, routine, unk_one, routine_arg,
|
|
||||||
resume, period_ms, unk_zero);
|
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
|
|
||||||
auto timer = kernel_state->object_table()->LookupObject<XTimer>(timer_handle);
|
auto timer =
|
||||||
|
kernel_state()->object_table()->LookupObject<XTimer>(timer_handle);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
result = timer->SetTimer(due_time, period_ms, routine, routine_arg,
|
result =
|
||||||
resume ? true : false);
|
timer->SetTimer(due_time, period_ms, routine_ptr.guest_address(),
|
||||||
|
routine_arg.guest_address(), resume ? true : false);
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtSetTimerEx, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL NtCancelTimer_shim(PPCContext* ppc_context,
|
dword_result_t NtCancelTimer(dword_t timer_handle,
|
||||||
KernelState* kernel_state) {
|
lpdword_t current_state_ptr) {
|
||||||
uint32_t timer_handle = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t current_state_ptr = SHIM_GET_ARG_32(1);
|
|
||||||
|
|
||||||
XELOGD("NtCancelTimer(%.8X, %.8X)", timer_handle, current_state_ptr);
|
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
|
|
||||||
auto timer = kernel_state->object_table()->LookupObject<XTimer>(timer_handle);
|
auto timer =
|
||||||
|
kernel_state()->object_table()->LookupObject<XTimer>(timer_handle);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
result = timer->Cancel();
|
result = timer->Cancel();
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
if (current_state_ptr) {
|
if (current_state_ptr) {
|
||||||
SHIM_SET_MEM_32(current_state_ptr, 0);
|
*current_state_ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(NtCancelTimer, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
|
dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
|
||||||
dword_t processor_mode, dword_t alertable,
|
dword_t processor_mode, dword_t alertable,
|
||||||
|
@ -991,96 +899,63 @@ void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) {
|
||||||
DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading,
|
DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading,
|
||||||
kImplemented, kHighFrequency);
|
kImplemented, kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL KeEnterCriticalRegion_shim(PPCContext* ppc_context,
|
void KeEnterCriticalRegion() { XThread::EnterCriticalRegion(); }
|
||||||
KernelState* kernel_state) {
|
DECLARE_XBOXKRNL_EXPORT2(KeEnterCriticalRegion, kThreading, kImplemented,
|
||||||
// XELOGD(
|
kHighFrequency);
|
||||||
// "KeEnterCriticalRegion()");
|
|
||||||
XThread::EnterCriticalRegion();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHIM_CALL KeLeaveCriticalRegion_shim(PPCContext* ppc_context,
|
void KeLeaveCriticalRegion() {
|
||||||
KernelState* kernel_state) {
|
|
||||||
// XELOGD(
|
|
||||||
// "KeLeaveCriticalRegion()");
|
|
||||||
XThread::LeaveCriticalRegion();
|
XThread::LeaveCriticalRegion();
|
||||||
|
|
||||||
XThread::GetCurrentThread()->CheckApcs();
|
XThread::GetCurrentThread()->CheckApcs();
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeLeaveCriticalRegion, kThreading, kImplemented,
|
||||||
|
kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL KeRaiseIrqlToDpcLevel_shim(PPCContext* ppc_context,
|
dword_result_t KeRaiseIrqlToDpcLevel() {
|
||||||
KernelState* kernel_state) {
|
auto old_value = kernel_state()->processor()->RaiseIrql(cpu::Irql::DPC);
|
||||||
// XELOGD(
|
return (uint32_t)old_value;
|
||||||
// "KeRaiseIrqlToDpcLevel()");
|
|
||||||
auto old_value = kernel_state->processor()->RaiseIrql(cpu::Irql::DPC);
|
|
||||||
SHIM_SET_RETURN_32(old_value);
|
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeRaiseIrqlToDpcLevel, kThreading, kImplemented,
|
||||||
|
kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL KfLowerIrql_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
void KfLowerIrql(dword_t old_value) {
|
||||||
uint32_t old_value = SHIM_GET_ARG_32(0);
|
kernel_state()->processor()->LowerIrql(
|
||||||
// XELOGD(
|
static_cast<cpu::Irql>((uint32_t)old_value));
|
||||||
// "KfLowerIrql(%d)",
|
|
||||||
// old_value);
|
|
||||||
kernel_state->processor()->LowerIrql(static_cast<cpu::Irql>(old_value));
|
|
||||||
|
|
||||||
XThread::GetCurrentThread()->CheckApcs();
|
XThread::GetCurrentThread()->CheckApcs();
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency);
|
||||||
|
|
||||||
SHIM_CALL NtQueueApcThread_shim(PPCContext* ppc_context,
|
void NtQueueApcThread(dword_t thread_handle, lpvoid_t apc_routine,
|
||||||
KernelState* kernel_state) {
|
lpvoid_t arg1, lpvoid_t arg2, lpvoid_t arg3) {
|
||||||
uint32_t thread_handle = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t apc_routine = SHIM_GET_ARG_32(1);
|
|
||||||
uint32_t arg1 = SHIM_GET_ARG_32(2);
|
|
||||||
uint32_t arg2 = SHIM_GET_ARG_32(3);
|
|
||||||
uint32_t arg3 = SHIM_GET_ARG_32(4); // ?
|
|
||||||
XELOGD("NtQueueApcThread(%.8X, %.8X, %.8X, %.8X, %.8X)", thread_handle,
|
|
||||||
apc_routine, arg1, arg2, arg3);
|
|
||||||
|
|
||||||
// Alloc APC object (from somewhere) and insert.
|
// Alloc APC object (from somewhere) and insert.
|
||||||
|
|
||||||
assert_always("not implemented");
|
assert_always("not implemented");
|
||||||
}
|
}
|
||||||
|
// DECLARE_XBOXKRNL_EXPORT1(NtQueueApcThread, kThreading, kStub);
|
||||||
|
|
||||||
SHIM_CALL KeInitializeApc_shim(PPCContext* ppc_context,
|
void KeInitializeApc(pointer_t<XAPC> apc, lpvoid_t thread_ptr,
|
||||||
KernelState* kernel_state) {
|
lpvoid_t kernel_routine, lpvoid_t rundown_routine,
|
||||||
uint32_t apc_ptr = SHIM_GET_ARG_32(0);
|
lpvoid_t normal_routine, dword_t processor_mode,
|
||||||
uint32_t thread = SHIM_GET_ARG_32(1);
|
lpvoid_t normal_context) {
|
||||||
uint32_t kernel_routine = SHIM_GET_ARG_32(2);
|
|
||||||
uint32_t rundown_routine = SHIM_GET_ARG_32(3);
|
|
||||||
uint32_t normal_routine = SHIM_GET_ARG_32(4);
|
|
||||||
uint32_t processor_mode = SHIM_GET_ARG_32(5);
|
|
||||||
uint32_t normal_context = SHIM_GET_ARG_32(6);
|
|
||||||
|
|
||||||
XELOGD("KeInitializeApc(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", apc_ptr,
|
|
||||||
thread, kernel_routine, rundown_routine, normal_routine,
|
|
||||||
processor_mode, normal_context);
|
|
||||||
|
|
||||||
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
|
|
||||||
apc->Initialize();
|
apc->Initialize();
|
||||||
apc->processor_mode = processor_mode;
|
apc->processor_mode = processor_mode;
|
||||||
apc->thread_ptr = thread;
|
apc->thread_ptr = thread_ptr.guest_address();
|
||||||
apc->kernel_routine = kernel_routine;
|
apc->kernel_routine = kernel_routine.guest_address();
|
||||||
apc->rundown_routine = rundown_routine;
|
apc->rundown_routine = rundown_routine.guest_address();
|
||||||
apc->normal_routine = normal_routine;
|
apc->normal_routine = normal_routine.guest_address();
|
||||||
apc->normal_context = normal_routine ? normal_context : 0;
|
apc->normal_context =
|
||||||
|
normal_routine.guest_address() ? normal_context.guest_address() : 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeInitializeApc, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeInsertQueueApc_shim(PPCContext* ppc_context,
|
dword_result_t KeInsertQueueApc(pointer_t<XAPC> apc, lpvoid_t arg1,
|
||||||
KernelState* kernel_state) {
|
lpvoid_t arg2, dword_t priority_increment) {
|
||||||
uint32_t apc_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t arg1 = SHIM_GET_ARG_32(1);
|
|
||||||
uint32_t arg2 = SHIM_GET_ARG_32(2);
|
|
||||||
uint32_t priority_increment = SHIM_GET_ARG_32(3);
|
|
||||||
|
|
||||||
XELOGD("KeInsertQueueApc(%.8X, %.8X, %.8X, %.8X)", apc_ptr, arg1, arg2,
|
|
||||||
priority_increment);
|
|
||||||
|
|
||||||
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
|
|
||||||
|
|
||||||
auto thread = XObject::GetNativeObject<XThread>(
|
auto thread = XObject::GetNativeObject<XThread>(
|
||||||
kernel_state, SHIM_MEM_ADDR(apc->thread_ptr));
|
kernel_state(),
|
||||||
|
kernel_state()->memory()->TranslateVirtual(apc->thread_ptr));
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock thread.
|
// Lock thread.
|
||||||
|
@ -1089,53 +964,45 @@ SHIM_CALL KeInsertQueueApc_shim(PPCContext* ppc_context,
|
||||||
// Fail if already inserted.
|
// Fail if already inserted.
|
||||||
if (apc->enqueued) {
|
if (apc->enqueued) {
|
||||||
thread->UnlockApc(false);
|
thread->UnlockApc(false);
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prep APC.
|
// Prep APC.
|
||||||
apc->arg1 = arg1;
|
apc->arg1 = arg1.guest_address();
|
||||||
apc->arg2 = arg2;
|
apc->arg2 = arg2.guest_address();
|
||||||
apc->enqueued = 1;
|
apc->enqueued = 1;
|
||||||
|
|
||||||
auto apc_list = thread->apc_list();
|
auto apc_list = thread->apc_list();
|
||||||
|
|
||||||
uint32_t list_entry_ptr = apc_ptr + 8;
|
uint32_t list_entry_ptr = apc.guest_address() + 8;
|
||||||
apc_list->Insert(list_entry_ptr);
|
apc_list->Insert(list_entry_ptr);
|
||||||
|
|
||||||
// Unlock thread.
|
// Unlock thread.
|
||||||
thread->UnlockApc(true);
|
thread->UnlockApc(true);
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeInsertQueueApc, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KeRemoveQueueApc_shim(PPCContext* ppc_context,
|
dword_result_t KeRemoveQueueApc(pointer_t<XAPC> apc) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t apc_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("KeRemoveQueueApc(%.8X)", apc_ptr);
|
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
|
|
||||||
|
|
||||||
auto thread = XObject::GetNativeObject<XThread>(
|
auto thread = XObject::GetNativeObject<XThread>(
|
||||||
kernel_state, SHIM_MEM_ADDR(apc->thread_ptr));
|
kernel_state(),
|
||||||
|
kernel_state()->memory()->TranslateVirtual(apc->thread_ptr));
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->LockApc();
|
thread->LockApc();
|
||||||
|
|
||||||
if (!apc->enqueued) {
|
if (!apc->enqueued) {
|
||||||
thread->UnlockApc(false);
|
thread->UnlockApc(false);
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto apc_list = thread->apc_list();
|
auto apc_list = thread->apc_list();
|
||||||
uint32_t list_entry_ptr = apc_ptr + 8;
|
uint32_t list_entry_ptr = apc.guest_address() + 8;
|
||||||
if (apc_list->IsQueued(list_entry_ptr)) {
|
if (apc_list->IsQueued(list_entry_ptr)) {
|
||||||
apc_list->Remove(list_entry_ptr);
|
apc_list->Remove(list_entry_ptr);
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -1143,90 +1010,81 @@ SHIM_CALL KeRemoveQueueApc_shim(PPCContext* ppc_context,
|
||||||
|
|
||||||
thread->UnlockApc(true);
|
thread->UnlockApc(true);
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result ? 1 : 0);
|
return result ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeRemoveQueueApc, kThreading, kImplemented);
|
||||||
|
|
||||||
SHIM_CALL KiApcNormalRoutineNop_shim(PPCContext* ppc_context,
|
dword_result_t KiApcNormalRoutineNop(dword_t unk0 /* output? */,
|
||||||
KernelState* kernel_state) {
|
dword_t unk1 /* 0x13 */) {
|
||||||
uint32_t unk0 = SHIM_GET_ARG_32(0); // output?
|
return 0;
|
||||||
uint32_t unk1 = SHIM_GET_ARG_32(1); // 0x13
|
|
||||||
|
|
||||||
XELOGD("KiApcNormalRoutineNop(%.8X, %.8X)", unk0, unk1);
|
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(0);
|
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KiApcNormalRoutineNop, kThreading, kStub);
|
||||||
|
|
||||||
SHIM_CALL KeInitializeDpc_shim(PPCContext* ppc_context,
|
typedef struct {
|
||||||
KernelState* kernel_state) {
|
xe::be<uint32_t> unknown;
|
||||||
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
xe::be<uint32_t> flink;
|
||||||
uint32_t routine = SHIM_GET_ARG_32(1);
|
xe::be<uint32_t> blink;
|
||||||
uint32_t context = SHIM_GET_ARG_32(2);
|
xe::be<uint32_t> routine;
|
||||||
|
xe::be<uint32_t> context;
|
||||||
XELOGD("KeInitializeDpc(%.8X, %.8X, %.8X)", dpc_ptr, routine, context);
|
xe::be<uint32_t> arg1;
|
||||||
|
xe::be<uint32_t> arg2;
|
||||||
|
} XDPC;
|
||||||
|
|
||||||
|
void KeInitializeDpc(pointer_t<XDPC> dpc, lpvoid_t routine, lpvoid_t context) {
|
||||||
// KDPC (maybe) 0x18 bytes?
|
// KDPC (maybe) 0x18 bytes?
|
||||||
uint32_t type = 19; // DpcObject
|
uint32_t type = 19; // DpcObject
|
||||||
uint32_t importance = 0;
|
uint32_t importance = 0;
|
||||||
uint32_t number = 0; // ?
|
uint32_t number = 0; // ?
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 0, (type << 24) | (importance << 16) | (number));
|
dpc->unknown = (type << 24) | (importance << 16) | (number);
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 4, 0); // flink
|
dpc->flink = 0;
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 8, 0); // blink
|
dpc->blink = 0;
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 12, routine);
|
dpc->routine = routine.guest_address();
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 16, context);
|
dpc->context = context.guest_address();
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 20, 0); // arg1
|
dpc->arg1 = 0;
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 24, 0); // arg2
|
dpc->arg2 = 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeInitializeDpc, kThreading, kImplemented, kSketchy);
|
||||||
|
|
||||||
SHIM_CALL KeInsertQueueDpc_shim(PPCContext* ppc_context,
|
dword_result_t KeInsertQueueDpc(pointer_t<XDPC> dpc, dword_t arg1,
|
||||||
KernelState* kernel_state) {
|
dword_t arg2) {
|
||||||
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
uint32_t arg1 = SHIM_GET_ARG_32(1);
|
|
||||||
uint32_t arg2 = SHIM_GET_ARG_32(2);
|
|
||||||
|
|
||||||
assert_always("DPC does not dispatch yet; going to hang!");
|
assert_always("DPC does not dispatch yet; going to hang!");
|
||||||
|
|
||||||
XELOGD("KeInsertQueueDpc(%.8X, %.8X, %.8X)", dpc_ptr, arg1, arg2);
|
uint32_t list_entry_ptr = dpc.guest_address() + 4;
|
||||||
|
|
||||||
uint32_t list_entry_ptr = dpc_ptr + 4;
|
|
||||||
|
|
||||||
// Lock dispatcher.
|
// Lock dispatcher.
|
||||||
auto global_lock = xe::global_critical_region::AcquireDirect();
|
auto global_lock = xe::global_critical_region::AcquireDirect();
|
||||||
auto dpc_list = kernel_state->dpc_list();
|
auto dpc_list = kernel_state()->dpc_list();
|
||||||
|
|
||||||
// If already in a queue, abort.
|
// If already in a queue, abort.
|
||||||
if (dpc_list->IsQueued(list_entry_ptr)) {
|
if (dpc_list->IsQueued(list_entry_ptr)) {
|
||||||
SHIM_SET_RETURN_32(0);
|
return 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prep DPC.
|
// Prep DPC.
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 20, arg1);
|
dpc->arg1 = (uint32_t)arg1;
|
||||||
SHIM_SET_MEM_32(dpc_ptr + 24, arg2);
|
dpc->arg2 = (uint32_t)arg2;
|
||||||
|
|
||||||
dpc_list->Insert(list_entry_ptr);
|
dpc_list->Insert(list_entry_ptr);
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT2(KeInsertQueueDpc, kThreading, kStub, kSketchy);
|
||||||
|
|
||||||
SHIM_CALL KeRemoveQueueDpc_shim(PPCContext* ppc_context,
|
dword_result_t KeRemoveQueueDpc(pointer_t<XDPC> dpc) {
|
||||||
KernelState* kernel_state) {
|
|
||||||
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
XELOGD("KeRemoveQueueDpc(%.8X)", dpc_ptr);
|
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
uint32_t list_entry_ptr = dpc_ptr + 4;
|
uint32_t list_entry_ptr = dpc.guest_address() + 4;
|
||||||
|
|
||||||
auto global_lock = xe::global_critical_region::AcquireDirect();
|
auto global_lock = xe::global_critical_region::AcquireDirect();
|
||||||
auto dpc_list = kernel_state->dpc_list();
|
auto dpc_list = kernel_state()->dpc_list();
|
||||||
if (dpc_list->IsQueued(list_entry_ptr)) {
|
if (dpc_list->IsQueued(list_entry_ptr)) {
|
||||||
dpc_list->Remove(list_entry_ptr);
|
dpc_list->Remove(list_entry_ptr);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(result ? 1 : 0);
|
return result ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeRemoveQueueDpc, kThreading, kImplemented);
|
||||||
|
|
||||||
// https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/51e4dfcaacfdbd1a9692272931a436371492f72d/import/OpenXDK/include/xboxkrnl/xboxkrnl.h#L1372
|
// https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/51e4dfcaacfdbd1a9692272931a436371492f72d/import/OpenXDK/include/xboxkrnl/xboxkrnl.h#L1372
|
||||||
struct X_ERWLOCK {
|
struct X_ERWLOCK {
|
||||||
|
@ -1323,49 +1181,7 @@ pointer_result_t InterlockedFlushSList(pointer_t<X_SLIST_HEADER> plist_ptr) {
|
||||||
DECLARE_XBOXKRNL_EXPORT1(InterlockedFlushSList, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(InterlockedFlushSList, kThreading, kImplemented);
|
||||||
|
|
||||||
void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
|
void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
|
||||||
KernelState* kernel_state) {
|
KernelState* kernel_state) {}
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExCreateThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExTerminateThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtResumeThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeResumeThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSuspendThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetAffinityThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryBasePriorityThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetBasePriorityThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetDisableBoostThread, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeGetCurrentProcessType, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetCurrentProcessType, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtYieldExecution, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseSemaphore, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetTimerEx, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCancelTimer, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeRaiseIrqlToDpcLevel, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KfLowerIrql, state);
|
|
||||||
|
|
||||||
// SHIM_SET_MAPPING("xboxkrnl.exe", NtQueueApcThread, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeApc, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInsertQueueApc, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeRemoveQueueApc, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KiApcNormalRoutineNop, state);
|
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeDpc, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInsertQueueDpc, state);
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeRemoveQueueDpc, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace xboxkrnl
|
} // namespace xboxkrnl
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
Loading…
Reference in New Issue