Shuffling kernel/.
This commit is contained in:
143
src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc
Normal file
143
src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/apu/audio_system.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
SHIM_CALL XAudioGetSpeakerConfig_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t config_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XAudioGetSpeakerConfig(%.8X)", config_ptr);
|
||||
|
||||
SHIM_SET_MEM_32(config_ptr, 0x00010001);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioGetVoiceCategoryVolumeChangeMask_shim(
|
||||
PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t out_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XAudioGetVoiceCategoryVolumeChangeMask(%.8X, %.8X)", driver_ptr,
|
||||
out_ptr);
|
||||
|
||||
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
|
||||
|
||||
// Checking these bits to see if any voice volume changed.
|
||||
// I think.
|
||||
SHIM_SET_MEM_32(out_ptr, 0);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioGetVoiceCategoryVolume_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk = SHIM_GET_ARG_32(0);
|
||||
uint32_t out_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XAudioGetVoiceCategoryVolume(%.8X, %.8X)", unk, out_ptr);
|
||||
|
||||
// Expects a floating point single. Volume %?
|
||||
xe::store_and_swap<float>(SHIM_MEM_ADDR(out_ptr), 1.0f);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioEnableDucker_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XAudioEnableDucker(%.8X)", unk);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioRegisterRenderDriverClient_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t callback_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t driver_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
uint32_t callback = SHIM_MEM_32(callback_ptr + 0);
|
||||
uint32_t callback_arg = SHIM_MEM_32(callback_ptr + 4);
|
||||
|
||||
XELOGD("XAudioRegisterRenderDriverClient(%.8X(%.8X, %.8X), %.8X)",
|
||||
callback_ptr, callback, callback_arg, driver_ptr);
|
||||
|
||||
auto audio_system = kernel_state->emulator()->audio_system();
|
||||
|
||||
size_t index;
|
||||
auto result = audio_system->RegisterClient(callback, callback_arg, &index);
|
||||
if (XFAILED(result)) {
|
||||
SHIM_SET_RETURN_32(result);
|
||||
return;
|
||||
}
|
||||
|
||||
assert_true(!(index & ~0x0000FFFF));
|
||||
SHIM_SET_MEM_32(driver_ptr,
|
||||
0x41550000 | (static_cast<uint32_t>(index) & 0x0000FFFF));
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioUnregisterRenderDriverClient_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XAudioUnregisterRenderDriverClient(%.8X)", driver_ptr);
|
||||
|
||||
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
|
||||
|
||||
auto audio_system = kernel_state->emulator()->audio_system();
|
||||
audio_system->UnregisterClient(driver_ptr & 0x0000FFFF);
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XAudioSubmitRenderDriverFrame_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t samples_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XAudioSubmitRenderDriverFrame(%.8X, %.8X)", driver_ptr, samples_ptr);
|
||||
|
||||
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
|
||||
|
||||
auto audio_system = kernel_state->emulator()->audio_system();
|
||||
audio_system->SubmitFrame(driver_ptr & 0x0000FFFF, samples_ptr);
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
void RegisterAudioExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
// Additional XMA* methods are in xboxkrnl_audio_xma.cc.
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetSpeakerConfig, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolumeChangeMask,
|
||||
state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolume, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioEnableDucker, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioRegisterRenderDriverClient, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioUnregisterRenderDriverClient, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioSubmitRenderDriverFrame, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
372
src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc
Normal file
372
src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc
Normal file
@@ -0,0 +1,372 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "xenia/apu/audio_system.h"
|
||||
#include "xenia/apu/xma_decoder.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
using xe::apu::XMA_CONTEXT_DATA;
|
||||
|
||||
// See audio_system.cc for implementation details.
|
||||
//
|
||||
// XMA details:
|
||||
// https://devel.nuclex.org/external/svn/directx/trunk/include/xma2defs.h
|
||||
// https://github.com/gdawg/fsbext/blob/master/src/xma_header.h
|
||||
//
|
||||
// XMA is undocumented, but the methods are pretty simple.
|
||||
// Games do this sequence to decode (now):
|
||||
// (not sure we are setting buffer validity/offsets right)
|
||||
// d> XMACreateContext(20656800)
|
||||
// d> XMAIsInputBuffer0Valid(000103E0)
|
||||
// d> XMAIsInputBuffer1Valid(000103E0)
|
||||
// d> XMADisableContext(000103E0, 0)
|
||||
// d> XMABlockWhileInUse(000103E0)
|
||||
// d> XMAInitializeContext(000103E0, 20008810)
|
||||
// d> XMASetOutputBufferValid(000103E0)
|
||||
// d> XMASetInputBuffer0Valid(000103E0)
|
||||
// d> XMAEnableContext(000103E0)
|
||||
// d> XMAGetOutputBufferWriteOffset(000103E0)
|
||||
// d> XMAGetOutputBufferReadOffset(000103E0)
|
||||
// d> XMAIsOutputBufferValid(000103E0)
|
||||
// d> XMAGetOutputBufferReadOffset(000103E0)
|
||||
// d> XMAGetOutputBufferWriteOffset(000103E0)
|
||||
// d> XMAIsInputBuffer0Valid(000103E0)
|
||||
// d> XMAIsInputBuffer1Valid(000103E0)
|
||||
// d> XMAIsInputBuffer0Valid(000103E0)
|
||||
// d> XMAIsInputBuffer1Valid(000103E0)
|
||||
// d> XMAReleaseContext(000103E0)
|
||||
//
|
||||
// XAudio2 uses XMA under the covers, and seems to map with the same
|
||||
// restrictions of frame/subframe/etc:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2_buffer(v=vs.85).aspx
|
||||
|
||||
SHIM_CALL XMACreateContext_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_out_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XMACreateContext(%.8X)", context_out_ptr);
|
||||
|
||||
auto xma_decoder = kernel_state->emulator()->audio_system()->xma_decoder();
|
||||
uint32_t context_ptr = xma_decoder->AllocateContext();
|
||||
SHIM_SET_MEM_32(context_out_ptr, context_ptr);
|
||||
if (!context_ptr) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XMAReleaseContext_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XMAReleaseContext(%.8X)", context_ptr);
|
||||
|
||||
auto xma_decoder = kernel_state->emulator()->audio_system()->xma_decoder();
|
||||
xma_decoder->ReleaseContext(context_ptr);
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
void StoreXmaContextIndexedRegister(KernelState* kernel_state,
|
||||
uint32_t base_reg, uint32_t context_ptr) {
|
||||
auto xma_decoder = kernel_state->emulator()->audio_system()->xma_decoder();
|
||||
uint32_t hw_index = (context_ptr - xma_decoder->context_array_ptr()) /
|
||||
sizeof(XMA_CONTEXT_DATA);
|
||||
uint32_t reg_num = base_reg + (hw_index >> 5) * 4;
|
||||
uint32_t reg_value = 1 << (hw_index & 0x1F);
|
||||
xma_decoder->WriteRegister(reg_num, xe::byte_swap(reg_value));
|
||||
}
|
||||
|
||||
struct XMA_LOOP_DATA {
|
||||
xe::be<uint32_t> loop_start;
|
||||
xe::be<uint32_t> loop_end;
|
||||
xe::be<uint8_t> loop_count;
|
||||
xe::be<uint8_t> loop_subframe_end;
|
||||
xe::be<uint8_t> loop_subframe_skip;
|
||||
};
|
||||
static_assert_size(XMA_LOOP_DATA, 12);
|
||||
|
||||
struct XMA_CONTEXT_INIT {
|
||||
xe::be<uint32_t> input_buffer_0_ptr;
|
||||
xe::be<uint32_t> input_buffer_0_packet_count;
|
||||
xe::be<uint32_t> input_buffer_1_ptr;
|
||||
xe::be<uint32_t> input_buffer_1_packet_count;
|
||||
xe::be<uint32_t> input_buffer_read_offset;
|
||||
xe::be<uint32_t> output_buffer_ptr;
|
||||
xe::be<uint32_t> output_buffer_block_count;
|
||||
xe::be<uint32_t> work_buffer;
|
||||
xe::be<uint32_t> subframe_decode_count;
|
||||
xe::be<uint32_t> channel_count;
|
||||
xe::be<uint32_t> sample_rate;
|
||||
XMA_LOOP_DATA loop_data;
|
||||
};
|
||||
static_assert_size(XMA_CONTEXT_INIT, 56);
|
||||
|
||||
dword_result_t XMAInitializeContext(lpvoid_t context_ptr,
|
||||
pointer_t<XMA_CONTEXT_INIT> context_init) {
|
||||
std::memset(context_ptr, 0, sizeof(XMA_CONTEXT_DATA));
|
||||
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
|
||||
context.input_buffer_0_ptr = context_init->input_buffer_0_ptr;
|
||||
context.input_buffer_0_packet_count =
|
||||
context_init->input_buffer_0_packet_count;
|
||||
context.input_buffer_1_ptr = context_init->input_buffer_1_ptr;
|
||||
context.input_buffer_1_packet_count =
|
||||
context_init->input_buffer_1_packet_count;
|
||||
context.input_buffer_read_offset = context_init->input_buffer_read_offset;
|
||||
context.output_buffer_ptr = context_init->output_buffer_ptr;
|
||||
context.output_buffer_block_count = context_init->output_buffer_block_count;
|
||||
|
||||
// context.work_buffer = context_init->work_buffer; // ?
|
||||
context.subframe_decode_count = context_init->subframe_decode_count;
|
||||
context.is_stereo = context_init->channel_count == 2;
|
||||
context.sample_rate = context_init->sample_rate;
|
||||
|
||||
context.loop_start = context_init->loop_data.loop_start;
|
||||
context.loop_end = context_init->loop_data.loop_end;
|
||||
context.loop_count = context_init->loop_data.loop_count;
|
||||
context.loop_subframe_end = context_init->loop_data.loop_subframe_end;
|
||||
context.loop_subframe_skip = context_init->loop_data.loop_subframe_skip;
|
||||
|
||||
context.Store(context_ptr);
|
||||
|
||||
StoreXmaContextIndexedRegister(kernel_state(), 0x1A80, context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAInitializeContext,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
SHIM_CALL XMASetLoopData_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t loop_data_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XMASetLoopData(%.8X, %.8X)", context_ptr, loop_data_ptr);
|
||||
|
||||
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
|
||||
auto loop_data =
|
||||
reinterpret_cast<XMA_CONTEXT_DATA*>(SHIM_MEM_ADDR(loop_data_ptr));
|
||||
|
||||
context.loop_start = loop_data->loop_start;
|
||||
context.loop_end = loop_data->loop_end;
|
||||
context.loop_count = loop_data->loop_count;
|
||||
context.loop_subframe_end = loop_data->loop_subframe_end;
|
||||
context.loop_subframe_skip = loop_data->loop_subframe_skip;
|
||||
|
||||
context.Store(SHIM_MEM_ADDR(context_ptr));
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
dword_result_t XMAGetInputBufferReadOffset(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.input_buffer_read_offset;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAGetInputBufferReadOffset,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetInputBufferReadOffset(lpvoid_t context_ptr,
|
||||
dword_t value) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
context.input_buffer_read_offset = value;
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetInputBufferReadOffset,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetInputBuffer0(lpvoid_t context_ptr, lpvoid_t buffer,
|
||||
dword_t packet_count) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
|
||||
context.input_buffer_0_ptr = buffer.guest_address();
|
||||
context.input_buffer_0_packet_count = packet_count;
|
||||
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer0,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAIsInputBuffer0Valid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.input_buffer_0_valid;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAIsInputBuffer0Valid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetInputBuffer0Valid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
context.input_buffer_0_valid = 1;
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer0Valid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetInputBuffer1(lpvoid_t context_ptr, lpvoid_t buffer,
|
||||
dword_t packet_count) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
|
||||
context.input_buffer_1_ptr = buffer.guest_address();
|
||||
context.input_buffer_1_packet_count = packet_count;
|
||||
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer1,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAIsInputBuffer1Valid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.input_buffer_1_valid;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAIsInputBuffer1Valid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetInputBuffer1Valid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
context.input_buffer_1_valid = 1;
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer1Valid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAIsOutputBufferValid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.output_buffer_valid;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAIsOutputBufferValid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetOutputBufferValid(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
context.output_buffer_valid = 1;
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetOutputBufferValid,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAGetOutputBufferReadOffset(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.output_buffer_read_offset;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAGetOutputBufferReadOffset,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMASetOutputBufferReadOffset(lpvoid_t context_ptr,
|
||||
dword_t value) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
context.output_buffer_read_offset = value;
|
||||
context.Store(context_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMASetOutputBufferReadOffset,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAGetOutputBufferWriteOffset(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.output_buffer_write_offset;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAGetOutputBufferWriteOffset,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
dword_result_t XMAGetPacketMetadata(lpvoid_t context_ptr) {
|
||||
XMA_CONTEXT_DATA context(context_ptr);
|
||||
return context.packet_metadata;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XMAGetPacketMetadata,
|
||||
ExportTag::kImplemented | ExportTag::kAudio);
|
||||
|
||||
SHIM_CALL XMAEnableContext_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XMAEnableContext(%.8X)", context_ptr);
|
||||
|
||||
StoreXmaContextIndexedRegister(kernel_state, 0x1940, context_ptr);
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
SHIM_CALL XMADisableContext_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t wait = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XMADisableContext(%.8X, %d)", context_ptr, wait);
|
||||
|
||||
X_HRESULT result = X_E_SUCCESS;
|
||||
StoreXmaContextIndexedRegister(kernel_state, 0x1A40, context_ptr);
|
||||
if (!kernel_state->emulator()->audio_system()->xma_decoder()->BlockOnContext(
|
||||
context_ptr, !wait)) {
|
||||
result = X_E_FALSE;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL XMABlockWhileInUse_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t context_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XMABlockWhileInUse(%.8X)", context_ptr);
|
||||
|
||||
do {
|
||||
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
|
||||
if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) {
|
||||
break;
|
||||
}
|
||||
xe::threading::Sleep(std::chrono::milliseconds(1));
|
||||
} while (true);
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
// Used for both XMA* methods and direct register access.
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMACreateContext, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, state);
|
||||
|
||||
// Only used in older games.
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetLoopData, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMAEnableContext, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMADisableContext, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMABlockWhileInUse, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
136
src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc
Normal file
136
src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
#include "third_party/crypto/TinySHA1.hpp"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint32_t> count; // 0x0
|
||||
xe::be<uint32_t> state[5]; // 0x4
|
||||
uint8_t buffer[64]; // 0x18
|
||||
} XECRYPT_SHA_STATE;
|
||||
|
||||
void InitSha1(sha1::SHA1* sha, const XECRYPT_SHA_STATE* state) {
|
||||
uint32_t digest[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
digest[i] = state->state[i];
|
||||
}
|
||||
|
||||
sha->init(digest, state->buffer, state->count);
|
||||
}
|
||||
|
||||
void StoreSha1(sha1::SHA1* sha, XECRYPT_SHA_STATE* state) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
state->state[i] = sha->getDigest()[i];
|
||||
}
|
||||
|
||||
state->count = static_cast<uint32_t>(sha->getByteCount());
|
||||
std::memcpy(state->buffer, sha->getBlock(), sha->getBlockByteIndex());
|
||||
}
|
||||
|
||||
void XeCryptShaInit(pointer_t<XECRYPT_SHA_STATE> sha_state) {
|
||||
sha_state.Zero();
|
||||
|
||||
sha_state->state[0] = 0x67452301;
|
||||
sha_state->state[1] = 0xEFCDAB89;
|
||||
sha_state->state[2] = 0x98BADCFE;
|
||||
sha_state->state[3] = 0x10325476;
|
||||
sha_state->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptShaInit, ExportTag::kImplemented);
|
||||
|
||||
void XeCryptShaUpdate(pointer_t<XECRYPT_SHA_STATE> sha_state, lpvoid_t input,
|
||||
dword_t input_size) {
|
||||
sha1::SHA1 sha;
|
||||
InitSha1(&sha, sha_state);
|
||||
|
||||
sha.processBytes(input, input_size);
|
||||
|
||||
StoreSha1(&sha, sha_state);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptShaUpdate, ExportTag::kImplemented);
|
||||
|
||||
void XeCryptShaFinal(pointer_t<XECRYPT_SHA_STATE> sha_state,
|
||||
pointer_t<xe::be<uint32_t>> out, dword_t out_size) {
|
||||
sha1::SHA1 sha;
|
||||
InitSha1(&sha, sha_state);
|
||||
|
||||
uint32_t digest[5];
|
||||
sha.finalize(digest);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sha_state->state[i] = digest[i];
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < out_size / 4; i++) {
|
||||
out[i] = digest[i];
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptShaFinal, ExportTag::kImplemented);
|
||||
|
||||
void XeCryptSha(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2,
|
||||
dword_t input_2_size, lpvoid_t input_3, dword_t input_3_size,
|
||||
pointer_t<xe::be<uint32_t>> output, dword_t output_size) {
|
||||
sha1::SHA1 sha;
|
||||
|
||||
if (input_1 && input_1_size) {
|
||||
sha.processBytes(input_1, input_1_size);
|
||||
}
|
||||
if (input_2 && input_2_size) {
|
||||
sha.processBytes(input_2, input_2_size);
|
||||
}
|
||||
if (input_3 && input_3_size) {
|
||||
sha.processBytes(input_3, input_3_size);
|
||||
}
|
||||
|
||||
uint32_t digest[5];
|
||||
sha.finalize(digest);
|
||||
|
||||
for (uint32_t i = 0; i < output_size / 4; i++) {
|
||||
output[i] = digest[i];
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptSha, ExportTag::kImplemented);
|
||||
|
||||
// Byteswap?
|
||||
dword_result_t XeCryptBnQw_SwapDwQwLeBe(lpqword_t qw_inp, lpqword_t qw_out,
|
||||
dword_t size) {
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptBnQw_SwapDwQwLeBe, ExportTag::kStub);
|
||||
|
||||
dword_result_t XeCryptBnQwNeRsaPubCrypt(lpqword_t qw_a, lpqword_t qw_b,
|
||||
lpvoid_t rsa) {
|
||||
// 0 indicates failure (but not a BOOL return value)
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptBnQwNeRsaPubCrypt, ExportTag::kStub);
|
||||
|
||||
dword_result_t XeCryptBnDwLePkcs1Verify(lpvoid_t hash, lpvoid_t sig,
|
||||
dword_t size) {
|
||||
// BOOL return value
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XeCryptBnDwLePkcs1Verify, ExportTag::kStub);
|
||||
|
||||
void RegisterCryptExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
113
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc
Normal file
113
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/debugging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
void DbgBreakPoint() { xe::debugging::Break(); }
|
||||
DECLARE_XBOXKRNL_EXPORT(DbgBreakPoint, ExportTag::kImportant);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
typedef struct {
|
||||
xe::be<uint32_t> type;
|
||||
xe::be<uint32_t> name_ptr;
|
||||
xe::be<uint32_t> thread_id;
|
||||
xe::be<uint32_t> flags;
|
||||
} X_THREADNAME_INFO;
|
||||
static_assert_size(X_THREADNAME_INFO, 0x10);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082.aspx
|
||||
typedef struct {
|
||||
xe::be<uint32_t> exception_code;
|
||||
xe::be<uint32_t> exception_flags;
|
||||
xe::be<uint32_t> exception_record;
|
||||
xe::be<uint32_t> exception_address;
|
||||
xe::be<uint32_t> number_parameters;
|
||||
xe::be<uint32_t> exception_information[15];
|
||||
} X_EXCEPTION_RECORD;
|
||||
static_assert_size(X_EXCEPTION_RECORD, 0x50);
|
||||
void AppendParam(StringBuffer* string_buffer,
|
||||
pointer_t<X_EXCEPTION_RECORD> record) {
|
||||
string_buffer->AppendFormat("%.8X(%.8X)", record.guest_address(),
|
||||
uint32_t(record->exception_code));
|
||||
}
|
||||
|
||||
void RtlRaiseException(pointer_t<X_EXCEPTION_RECORD> record) {
|
||||
if (record->exception_code == 0x406D1388) {
|
||||
// SetThreadName. FFS.
|
||||
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
|
||||
// TODO(benvanik): check record->number_parameters to make sure it's a
|
||||
// correct size.
|
||||
auto thread_info =
|
||||
reinterpret_cast<X_THREADNAME_INFO*>(&record->exception_information[0]);
|
||||
|
||||
assert_true(thread_info->type == 0x1000);
|
||||
auto name =
|
||||
kernel_memory()->TranslateVirtual<const char*>(thread_info->name_ptr);
|
||||
|
||||
object_ref<XThread> thread;
|
||||
if (thread_info->thread_id == -1) {
|
||||
// Current thread.
|
||||
thread = retain_object(XThread::GetCurrentThread());
|
||||
} else {
|
||||
// Lookup thread by ID.
|
||||
thread = kernel_state()->GetThreadByID(thread_info->thread_id);
|
||||
}
|
||||
|
||||
if (thread) {
|
||||
XELOGD("SetThreadName(%d, %s)", thread->thread_id(), name);
|
||||
thread->set_name(name);
|
||||
}
|
||||
|
||||
// TODO(benvanik): unwinding required here?
|
||||
return;
|
||||
}
|
||||
|
||||
if (record->exception_code == 0xE06D7363) {
|
||||
// C++ exception.
|
||||
// http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
|
||||
xe::debugging::Break();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(benvanik): unwinding.
|
||||
// This is going to suck.
|
||||
xe::debugging::Break();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlRaiseException, ExportTag::kImportant);
|
||||
|
||||
void KeBugCheckEx(dword_t code, dword_t param1, dword_t param2, dword_t param3,
|
||||
dword_t param4) {
|
||||
XELOGD("*** STOP: 0x%.8X (0x%.8X, 0x%.8X, 0x%.8X, 0x%.8X)", code, param1,
|
||||
param2, param3, param4);
|
||||
fflush(stdout);
|
||||
xe::debugging::Break();
|
||||
assert_always();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeBugCheckEx, ExportTag::kImportant);
|
||||
|
||||
void KeBugCheck(dword_t code) { KeBugCheckEx(code, 0, 0, 0, 0); }
|
||||
DECLARE_XBOXKRNL_EXPORT(KeBugCheck, ExportTag::kImportant);
|
||||
|
||||
void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
1022
src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc
Normal file
1022
src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc
Normal file
File diff suppressed because it is too large
Load Diff
26
src/xenia/kernel/xboxkrnl/xboxkrnl_error.h
Normal file
26
src/xenia/kernel/xboxkrnl/xboxkrnl_error.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ERROR_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ERROR_H_
|
||||
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
dword_result_t RtlNtStatusToDosError(dword_t source_status);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ERROR_H_
|
||||
39
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc
Normal file
39
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
void HalReturnToFirmware(dword_t routine) {
|
||||
// void
|
||||
// IN FIRMWARE_REENTRY Routine
|
||||
|
||||
// Routine must be 1 'HalRebootRoutine'
|
||||
assert_true(routine == 1);
|
||||
|
||||
// TODO(benvank): diediedie much more gracefully
|
||||
// Not sure how to blast back up the stack in LLVM without exceptions, though.
|
||||
XELOGE("Game requested shutdown via HalReturnToFirmware");
|
||||
exit(0);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(HalReturnToFirmware, ExportTag::kImportant);
|
||||
|
||||
void RegisterHalExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
673
src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc
Normal file
673
src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc
Normal file
@@ -0,0 +1,673 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/memory.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xevent.h"
|
||||
#include "xenia/kernel/xfile.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
#include "xenia/vfs/device.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540287.aspx
|
||||
class X_FILE_FS_VOLUME_INFORMATION {
|
||||
public:
|
||||
// FILE_FS_VOLUME_INFORMATION
|
||||
uint64_t creation_time;
|
||||
uint32_t serial_number;
|
||||
uint32_t label_length;
|
||||
uint32_t supports_objects;
|
||||
char label[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
xe::store_and_swap<uint64_t>(dst + 0, this->creation_time);
|
||||
xe::store_and_swap<uint32_t>(dst + 8, this->serial_number);
|
||||
xe::store_and_swap<uint32_t>(dst + 12, this->label_length);
|
||||
xe::store_and_swap<uint32_t>(dst + 16, this->supports_objects);
|
||||
memcpy(dst + 20, this->label, this->label_length);
|
||||
}
|
||||
};
|
||||
static_assert_size(X_FILE_FS_VOLUME_INFORMATION, 24);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff540282.aspx
|
||||
class X_FILE_FS_SIZE_INFORMATION {
|
||||
public:
|
||||
// FILE_FS_SIZE_INFORMATION
|
||||
uint64_t total_allocation_units;
|
||||
uint64_t available_allocation_units;
|
||||
uint32_t sectors_per_allocation_unit;
|
||||
uint32_t bytes_per_sector;
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
xe::store_and_swap<uint64_t>(dst + 0, this->total_allocation_units);
|
||||
xe::store_and_swap<uint64_t>(dst + 8, this->available_allocation_units);
|
||||
xe::store_and_swap<uint32_t>(dst + 16, this->sectors_per_allocation_unit);
|
||||
xe::store_and_swap<uint32_t>(dst + 20, this->bytes_per_sector);
|
||||
}
|
||||
};
|
||||
static_assert_size(X_FILE_FS_SIZE_INFORMATION, 24);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
|
||||
class X_FILE_FS_ATTRIBUTE_INFORMATION {
|
||||
public:
|
||||
// FILE_FS_ATTRIBUTE_INFORMATION
|
||||
uint32_t attributes;
|
||||
int32_t maximum_component_name_length;
|
||||
uint32_t fs_name_length;
|
||||
char fs_name[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
xe::store_and_swap<uint32_t>(dst + 0, this->attributes);
|
||||
xe::store_and_swap<uint32_t>(dst + 4, this->maximum_component_name_length);
|
||||
xe::store_and_swap<uint32_t>(dst + 8, this->fs_name_length);
|
||||
memcpy(dst + 12, this->fs_name, this->fs_name_length);
|
||||
}
|
||||
};
|
||||
static_assert_size(X_FILE_FS_ATTRIBUTE_INFORMATION, 16);
|
||||
|
||||
dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
|
||||
pointer_t<X_OBJECT_ATTRIBUTES> object_attrs,
|
||||
pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
lpqword_t allocation_size_ptr,
|
||||
dword_t file_attributes, dword_t share_access,
|
||||
dword_t creation_disposition,
|
||||
dword_t create_options) {
|
||||
uint64_t allocation_size = 0; // is this correct???
|
||||
if (allocation_size_ptr) {
|
||||
allocation_size = *allocation_size_ptr;
|
||||
}
|
||||
|
||||
if (!object_attrs) {
|
||||
// ..? Some games do this. This parameter is not optional.
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
assert_not_null(handle_out);
|
||||
|
||||
auto object_name =
|
||||
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
|
||||
|
||||
// Compute path, possibly attrs relative.
|
||||
std::string target_path =
|
||||
object_name->to_string(kernel_memory()->virtual_membase());
|
||||
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
|
||||
object_attrs->root_directory != 0) {
|
||||
auto root_file = kernel_state()->object_table()->LookupObject<XFile>(
|
||||
object_attrs->root_directory);
|
||||
assert_not_null(root_file);
|
||||
assert_true(root_file->type() == XObject::Type::kTypeFile);
|
||||
|
||||
// Resolve the file using the device the root directory is part of.
|
||||
auto device = root_file->device();
|
||||
target_path = xe::join_paths(
|
||||
device->mount_path(), xe::join_paths(root_file->path(), target_path));
|
||||
}
|
||||
|
||||
// Attempt open (or create).
|
||||
object_ref<XFile> file;
|
||||
xe::vfs::FileAction file_action;
|
||||
X_STATUS result = kernel_state()->file_system()->OpenFile(
|
||||
kernel_state(), target_path,
|
||||
xe::vfs::FileDisposition((uint32_t)creation_disposition), desired_access,
|
||||
&file, &file_action);
|
||||
|
||||
X_HANDLE handle = X_INVALID_HANDLE_VALUE;
|
||||
if (XSUCCEEDED(result)) {
|
||||
// Handle ref is incremented, so return that.
|
||||
handle = file->handle();
|
||||
}
|
||||
|
||||
if (io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = (uint32_t)file_action;
|
||||
}
|
||||
|
||||
*handle_out = handle;
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtCreateFile, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t NtOpenFile(lpdword_t handle_out, dword_t desired_access,
|
||||
pointer_t<X_OBJECT_ATTRIBUTES> object_attributes,
|
||||
pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
dword_t open_options) {
|
||||
return NtCreateFile(handle_out, desired_access, object_attributes,
|
||||
io_status_block, nullptr, 0, 0,
|
||||
static_cast<uint32_t>(xe::vfs::FileDisposition::kOpen),
|
||||
open_options);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtOpenFile, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t NtReadFile(dword_t file_handle, dword_t event_handle,
|
||||
lpvoid_t apc_routine_ptr, lpvoid_t apc_context,
|
||||
pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
lpvoid_t buffer, dword_t buffer_length,
|
||||
lpqword_t byte_offset_ptr) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
bool signal_event = false;
|
||||
auto ev = kernel_state()->object_table()->LookupObject<XEvent>(event_handle);
|
||||
if (event_handle && !ev) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||
if (!file) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (true) {
|
||||
// Synchronous.
|
||||
size_t bytes_read = 0;
|
||||
result = file->Read(buffer, buffer_length,
|
||||
byte_offset_ptr ? *byte_offset_ptr : -1, &bytes_read);
|
||||
if (io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = (uint32_t)bytes_read;
|
||||
}
|
||||
|
||||
// Queue the APC callback. It must be delivered via the APC mechanism even
|
||||
// though were are completing immediately.
|
||||
if ((uint32_t)apc_routine_ptr & ~1) {
|
||||
if (apc_context) {
|
||||
auto thread = XThread::GetCurrentThread();
|
||||
thread->EnqueueApc((uint32_t)apc_routine_ptr & ~1, apc_context,
|
||||
io_status_block, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark that we should signal the event now. We do this after
|
||||
// we have written the info out.
|
||||
signal_event = true;
|
||||
} else {
|
||||
// TODO(benvanik): async.
|
||||
|
||||
// X_STATUS_PENDING if not returning immediately.
|
||||
// XFile is waitable and signalled after each async req completes.
|
||||
// reset the input event (->Reset())
|
||||
/*xeNtReadFileState* call_state = new xeNtReadFileState();
|
||||
XAsyncRequest* request = new XAsyncRequest(
|
||||
state, file,
|
||||
(XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
|
||||
call_state);*/
|
||||
// result = file->Read(buffer, buffer_length, byte_offset, request);
|
||||
if (io_status_block) {
|
||||
io_status_block->status = X_STATUS_PENDING;
|
||||
io_status_block->information = 0;
|
||||
}
|
||||
|
||||
result = X_STATUS_PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
if (XFAILED(result) && io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = 0;
|
||||
}
|
||||
|
||||
if (ev && signal_event) {
|
||||
ev->Set(0, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtReadFile, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t NtWriteFile(dword_t file_handle, dword_t event_handle,
|
||||
function_t apc_routine, lpvoid_t apc_context,
|
||||
pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
lpvoid_t buffer, dword_t buffer_length,
|
||||
lpqword_t byte_offset_ptr) {
|
||||
// Async not supported yet.
|
||||
assert_zero(apc_routine);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab event to signal.
|
||||
bool signal_event = false;
|
||||
auto ev = kernel_state()->object_table()->LookupObject<XEvent>(event_handle);
|
||||
if (event_handle && !ev) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
// Grab file.
|
||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||
if (!file) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
// Execute write.
|
||||
if (XSUCCEEDED(result)) {
|
||||
// TODO(benvanik): async path.
|
||||
if (true) {
|
||||
// Synchronous request.
|
||||
size_t bytes_written = 0;
|
||||
result =
|
||||
file->Write(buffer, buffer_length,
|
||||
byte_offset_ptr ? *byte_offset_ptr : -1, &bytes_written);
|
||||
if (XSUCCEEDED(result)) {
|
||||
info = (int32_t)bytes_written;
|
||||
}
|
||||
|
||||
// Mark that we should signal the event now. We do this after
|
||||
// we have written the info out.
|
||||
signal_event = true;
|
||||
} else {
|
||||
// X_STATUS_PENDING if not returning immediately.
|
||||
result = X_STATUS_PENDING;
|
||||
info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = info;
|
||||
}
|
||||
|
||||
if (ev && signal_event) {
|
||||
ev->Set(0, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtWriteFile, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t NtCreateIoCompletion(lpvoid_t out_handle, dword_t desired_access,
|
||||
lpvoid_t object_attribs,
|
||||
dword_t num_concurrent_threads) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtCreateIoCompletion, ExportTag::kStub);
|
||||
|
||||
dword_result_t NtSetInformationFile(
|
||||
dword_t file_handle, pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
lpvoid_t file_info, dword_t length, dword_t file_info_class) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab file.
|
||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||
if (!file) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
switch (file_info_class) {
|
||||
case XFileDispositionInformation: {
|
||||
// Used to set deletion flag. Which we don't support. Probably?
|
||||
info = 0;
|
||||
bool delete_on_close =
|
||||
(xe::load_and_swap<uint8_t>(file_info)) ? true : false;
|
||||
XELOGW("NtSetInformationFile ignoring delete on close: %d",
|
||||
delete_on_close);
|
||||
break;
|
||||
}
|
||||
case XFilePositionInformation:
|
||||
// struct FILE_POSITION_INFORMATION {
|
||||
// LARGE_INTEGER CurrentByteOffset;
|
||||
// };
|
||||
assert_true(length == 8);
|
||||
info = 8;
|
||||
file->set_position(xe::load_and_swap<uint64_t>(file_info));
|
||||
break;
|
||||
case XFileAllocationInformation:
|
||||
case XFileEndOfFileInformation:
|
||||
assert_true(length == 8);
|
||||
info = 8;
|
||||
XELOGW("NtSetInformationFile ignoring alloc/eof");
|
||||
break;
|
||||
case XFileCompletionInformation:
|
||||
// Games appear to call NtCreateIoCompletion right before this
|
||||
break;
|
||||
default:
|
||||
// Unsupported, for now.
|
||||
assert_always();
|
||||
info = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = info;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtSetInformationFile, ExportTag::kImplemented);
|
||||
|
||||
struct X_IO_STATUS_BLOCK {
|
||||
union {
|
||||
xe::be<uint32_t> status;
|
||||
xe::be<uint32_t> pointer;
|
||||
};
|
||||
xe::be<uint32_t> information;
|
||||
};
|
||||
|
||||
dword_result_t NtQueryInformationFile(
|
||||
dword_t file_handle, pointer_t<X_IO_STATUS_BLOCK> io_status_block_ptr,
|
||||
lpvoid_t file_info_ptr, dword_t length, dword_t file_info_class) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab file.
|
||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||
if (file) {
|
||||
switch (file_info_class) {
|
||||
case XFileInternalInformation:
|
||||
// Internal unique file pointer. Not sure why anyone would want this.
|
||||
assert_true(length == 8);
|
||||
info = 8;
|
||||
// TODO(benvanik): use pointer to fs:: entry?
|
||||
xe::store_and_swap<uint64_t>(file_info_ptr,
|
||||
xe::memory::hash_combine(0, file->path()));
|
||||
break;
|
||||
case XFilePositionInformation:
|
||||
// struct FILE_POSITION_INFORMATION {
|
||||
// LARGE_INTEGER CurrentByteOffset;
|
||||
// };
|
||||
assert_true(length == 8);
|
||||
info = 8;
|
||||
xe::store_and_swap<uint64_t>(file_info_ptr, file->position());
|
||||
break;
|
||||
case XFileNetworkOpenInformation: {
|
||||
// struct FILE_NETWORK_OPEN_INFORMATION {
|
||||
// LARGE_INTEGER CreationTime;
|
||||
// LARGE_INTEGER LastAccessTime;
|
||||
// LARGE_INTEGER LastWriteTime;
|
||||
// LARGE_INTEGER ChangeTime;
|
||||
// LARGE_INTEGER AllocationSize;
|
||||
// LARGE_INTEGER EndOfFile;
|
||||
// ULONG FileAttributes;
|
||||
// ULONG Unknown;
|
||||
// };
|
||||
assert_true(length == 56);
|
||||
|
||||
auto file_info = file_info_ptr.as<X_FILE_NETWORK_OPEN_INFORMATION*>();
|
||||
file_info->creation_time = file->entry()->create_timestamp();
|
||||
file_info->last_access_time = file->entry()->access_timestamp();
|
||||
file_info->last_write_time = file->entry()->write_timestamp();
|
||||
file_info->change_time = file->entry()->write_timestamp();
|
||||
file_info->allocation_size = file->entry()->allocation_size();
|
||||
file_info->end_of_file = file->entry()->size();
|
||||
file_info->attributes = file->entry()->attributes();
|
||||
info = 56;
|
||||
break;
|
||||
}
|
||||
case XFileXctdCompressionInformation: {
|
||||
assert_true(length == 4);
|
||||
XELOGE(
|
||||
"NtQueryInformationFile(XFileXctdCompressionInformation) "
|
||||
"unimplemented");
|
||||
// This is wrong and puts files into wrong states for games that use
|
||||
// XctdDecompression.
|
||||
/*
|
||||
uint32_t magic;
|
||||
size_t bytes_read;
|
||||
size_t cur_pos = file->position();
|
||||
|
||||
file->set_position(0);
|
||||
result = file->Read(&magic, sizeof(magic), 0, &bytes_read);
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (bytes_read == sizeof(magic)) {
|
||||
info = 4;
|
||||
*file_info_ptr.as<xe::be<uint32_t>*>() =
|
||||
magic == xe::byte_swap(0x0FF512ED) ? 1 : 0;
|
||||
} else {
|
||||
result = X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
file->set_position(cur_pos);
|
||||
info = 4;
|
||||
*/
|
||||
result = X_STATUS_UNSUCCESSFUL;
|
||||
info = 0;
|
||||
} break;
|
||||
case XFileSectorInformation:
|
||||
// TODO(benvanik): return sector this file's on.
|
||||
assert_true(length == 4);
|
||||
XELOGE("NtQueryInformationFile(XFileSectorInformation) unimplemented");
|
||||
result = X_STATUS_UNSUCCESSFUL;
|
||||
info = 0;
|
||||
break;
|
||||
default:
|
||||
// Unsupported, for now.
|
||||
assert_always();
|
||||
info = 0;
|
||||
result = X_STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (io_status_block_ptr) {
|
||||
io_status_block_ptr->status = result;
|
||||
io_status_block_ptr->information = info; // # bytes written
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtQueryInformationFile,
|
||||
ExportTag::kImplemented | ExportTag::kFileSystem);
|
||||
|
||||
dword_result_t NtQueryFullAttributesFile(
|
||||
pointer_t<X_OBJECT_ATTRIBUTES> obj_attribs,
|
||||
pointer_t<X_FILE_NETWORK_OPEN_INFORMATION> file_info) {
|
||||
auto object_name =
|
||||
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(obj_attribs->name_ptr);
|
||||
|
||||
object_ref<XFile> root_file;
|
||||
if (obj_attribs->root_directory != 0xFFFFFFFD && // ObDosDevices
|
||||
obj_attribs->root_directory != 0) {
|
||||
root_file = kernel_state()->object_table()->LookupObject<XFile>(
|
||||
obj_attribs->root_directory);
|
||||
assert_not_null(root_file);
|
||||
assert_true(root_file->type() == XObject::Type::kTypeFile);
|
||||
assert_always();
|
||||
}
|
||||
|
||||
// Resolve the file using the virtual file system.
|
||||
auto entry = kernel_state()->file_system()->ResolvePath(
|
||||
object_name->to_string(kernel_memory()->virtual_membase()));
|
||||
if (entry) {
|
||||
// Found.
|
||||
file_info->creation_time = entry->create_timestamp();
|
||||
file_info->last_access_time = entry->access_timestamp();
|
||||
file_info->last_write_time = entry->write_timestamp();
|
||||
file_info->change_time = entry->write_timestamp();
|
||||
file_info->allocation_size = entry->allocation_size();
|
||||
file_info->end_of_file = entry->size();
|
||||
file_info->attributes = entry->attributes();
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtQueryFullAttributesFile, ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL NtQueryVolumeInformationFile_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t fs_info_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t length = SHIM_GET_ARG_32(3);
|
||||
uint32_t fs_info_class = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD("NtQueryVolumeInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
file_handle, io_status_block_ptr, fs_info_ptr, length, fs_info_class);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab file.
|
||||
auto file = kernel_state->object_table()->LookupObject<XFile>(file_handle);
|
||||
if (file) {
|
||||
switch (fs_info_class) {
|
||||
case 1: { // FileFsVolumeInformation
|
||||
// TODO(gibbed): actual value
|
||||
std::string name = "test";
|
||||
X_FILE_FS_VOLUME_INFORMATION volume_info = {0};
|
||||
volume_info.creation_time = 0;
|
||||
volume_info.serial_number = 12345678;
|
||||
volume_info.supports_objects = 0;
|
||||
volume_info.label_length = uint32_t(name.size());
|
||||
std::memcpy(volume_info.label, name.data(), name.size());
|
||||
volume_info.Write(SHIM_MEM_BASE, fs_info_ptr);
|
||||
info = length;
|
||||
break;
|
||||
}
|
||||
case 3: { // FileFsSizeInformation
|
||||
X_FILE_FS_SIZE_INFORMATION fs_size_info = {0};
|
||||
fs_size_info.total_allocation_units =
|
||||
file->device()->total_allocation_units();
|
||||
fs_size_info.available_allocation_units =
|
||||
file->device()->available_allocation_units();
|
||||
fs_size_info.sectors_per_allocation_unit =
|
||||
file->device()->sectors_per_allocation_unit();
|
||||
fs_size_info.bytes_per_sector = file->device()->bytes_per_sector();
|
||||
fs_size_info.Write(SHIM_MEM_BASE, fs_info_ptr);
|
||||
info = length;
|
||||
break;
|
||||
}
|
||||
case 5: { // FileFsAttributeInformation
|
||||
// TODO(gibbed): actual value
|
||||
std::string name = "test";
|
||||
X_FILE_FS_ATTRIBUTE_INFORMATION fs_attribute_info = {0};
|
||||
fs_attribute_info.attributes = 0;
|
||||
fs_attribute_info.maximum_component_name_length = 255;
|
||||
fs_attribute_info.fs_name_length = uint32_t(name.size());
|
||||
std::memcpy(fs_attribute_info.fs_name, name.data(), name.size());
|
||||
fs_attribute_info.Write(SHIM_MEM_BASE, fs_info_ptr);
|
||||
info = length;
|
||||
break;
|
||||
}
|
||||
case 2: // FileFsLabelInformation
|
||||
case 4: // FileFsDeviceInformation
|
||||
case 6: // FileFsControlInformation
|
||||
case 7: // FileFsFullSizeInformation
|
||||
case 8: // FileFsObjectIdInformation
|
||||
default:
|
||||
// Unsupported, for now.
|
||||
assert_always();
|
||||
info = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result = X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
if (XFAILED(result)) {
|
||||
info = 0;
|
||||
}
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
dword_result_t NtQueryDirectoryFile(
|
||||
dword_t file_handle, dword_t event_handle, function_t apc_routine,
|
||||
lpvoid_t apc_context, pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
pointer_t<X_FILE_DIRECTORY_INFORMATION> file_info_ptr, dword_t length,
|
||||
pointer_t<X_ANSI_STRING> file_name, dword_t restart_scan) {
|
||||
if (length < 72) {
|
||||
return X_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
X_STATUS result = X_STATUS_UNSUCCESSFUL;
|
||||
uint32_t info = 0;
|
||||
|
||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||
auto name =
|
||||
file_name ? file_name->to_string(kernel_memory()->virtual_membase()) : "";
|
||||
if (file) {
|
||||
X_FILE_DIRECTORY_INFORMATION dir_info = {0};
|
||||
result = file->QueryDirectory(file_info_ptr, length,
|
||||
!name.empty() ? name.c_str() : nullptr,
|
||||
restart_scan != 0);
|
||||
if (XSUCCEEDED(result)) {
|
||||
info = length;
|
||||
}
|
||||
} else {
|
||||
result = X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
if (XFAILED(result)) {
|
||||
info = 0;
|
||||
}
|
||||
|
||||
if (io_status_block) {
|
||||
io_status_block->status = result;
|
||||
io_status_block->information = info;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtQueryDirectoryFile, ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL NtFlushBuffersFile_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("NtFlushBuffersFile(%.8X, %.8X)", file_handle, io_status_block_ptr);
|
||||
|
||||
auto result = X_STATUS_SUCCESS;
|
||||
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, 0); // Information
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
dword_result_t FscGetCacheElementCount(dword_t r3) { return 0; }
|
||||
DECLARE_XBOXKRNL_EXPORT(FscGetCacheElementCount, ExportTag::kStub);
|
||||
|
||||
SHIM_CALL FscSetCacheElementCount_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk_0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk_1 = SHIM_GET_ARG_32(1);
|
||||
// unk_0 = 0
|
||||
// unk_1 looks like a count? in what units? 256 is a common value
|
||||
|
||||
XELOGD("FscSetCacheElementCount(%.8X, %.8X)", unk_0, unk_1);
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
void RegisterIoExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVolumeInformationFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtFlushBuffersFile, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", FscSetCacheElementCount, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
611
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc
Normal file
611
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc
Normal file
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
uint32_t ToXdkProtectFlags(uint32_t protect) {
|
||||
uint32_t result = 0;
|
||||
if (!(protect & kMemoryProtectRead) && !(protect & kMemoryProtectWrite)) {
|
||||
result = X_PAGE_NOACCESS;
|
||||
} else if ((protect & kMemoryProtectRead) &&
|
||||
!(protect & kMemoryProtectWrite)) {
|
||||
result = X_PAGE_READONLY;
|
||||
} else {
|
||||
result = X_PAGE_READWRITE;
|
||||
}
|
||||
if (protect & kMemoryProtectNoCache) {
|
||||
result = X_PAGE_NOCACHE;
|
||||
}
|
||||
if (protect & kMemoryProtectWriteCombine) {
|
||||
result = X_PAGE_WRITECOMBINE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FromXdkProtectFlags(uint32_t protect) {
|
||||
uint32_t result = 0;
|
||||
if ((protect & X_PAGE_READONLY) | (protect & X_PAGE_EXECUTE_READ)) {
|
||||
result |= kMemoryProtectRead;
|
||||
} else if ((protect & X_PAGE_READWRITE) |
|
||||
(protect & X_PAGE_EXECUTE_READWRITE)) {
|
||||
result |= kMemoryProtectRead | kMemoryProtectWrite;
|
||||
}
|
||||
if (protect & X_PAGE_NOCACHE) {
|
||||
result |= kMemoryProtectNoCache;
|
||||
}
|
||||
if (protect & X_PAGE_WRITECOMBINE) {
|
||||
result |= kMemoryProtectWriteCombine;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SHIM_CALL NtAllocateVirtualMemory_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||
uint32_t alloc_type = SHIM_GET_ARG_32(2); // X_MEM_* bitmask
|
||||
uint32_t protect_bits = SHIM_GET_ARG_32(3); // X_PAGE_* bitmask
|
||||
uint32_t unknown = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD("NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)",
|
||||
base_addr_ptr, base_addr_value, region_size_ptr, region_size_value,
|
||||
alloc_type, protect_bits, unknown);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PVOID *BaseAddress,
|
||||
// _Inout_ PSIZE_T RegionSize,
|
||||
// _In_ ULONG AllocationType,
|
||||
// _In_ ULONG Protect
|
||||
// ? handle?
|
||||
|
||||
// I've only seen zero.
|
||||
assert_true(unknown == 0);
|
||||
|
||||
// This allocates memory from the kernel heap, which is initialized on startup
|
||||
// and shared by both the kernel implementation and user code.
|
||||
// The xe_memory_ref object is used to actually get the memory, and although
|
||||
// it's simple today we could extend it to do better things in the future.
|
||||
|
||||
// Must request a size.
|
||||
if (!region_size_value) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
// Check allocation type.
|
||||
if (!(alloc_type & (X_MEM_COMMIT | X_MEM_RESET | X_MEM_RESERVE))) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
// If MEM_RESET is set only MEM_RESET can be set.
|
||||
if (alloc_type & X_MEM_RESET && (alloc_type & ~X_MEM_RESET)) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
// Don't allow games to set execute bits.
|
||||
if (protect_bits & (X_PAGE_EXECUTE | X_PAGE_EXECUTE_READ |
|
||||
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
|
||||
XELOGW("Game setting EXECUTE bit on allocation");
|
||||
}
|
||||
|
||||
// Adjust size.
|
||||
uint32_t page_size = 4096;
|
||||
if (alloc_type & X_MEM_LARGE_PAGES) {
|
||||
page_size = 64 * 1024;
|
||||
}
|
||||
if (int32_t(region_size_value) < 0) {
|
||||
// Some games pass in negative sizes.
|
||||
region_size_value = -int32_t(region_size_value);
|
||||
}
|
||||
uint32_t adjusted_size = xe::round_up(region_size_value, page_size);
|
||||
|
||||
// Allocate.
|
||||
uint32_t allocation_type = 0;
|
||||
if (alloc_type & X_MEM_RESERVE) {
|
||||
allocation_type |= kMemoryAllocationReserve;
|
||||
}
|
||||
if (alloc_type & X_MEM_COMMIT) {
|
||||
allocation_type |= kMemoryAllocationCommit;
|
||||
}
|
||||
if (alloc_type & X_MEM_RESET) {
|
||||
XELOGE("X_MEM_RESET not implemented");
|
||||
assert_always();
|
||||
}
|
||||
uint32_t protect = FromXdkProtectFlags(protect_bits);
|
||||
uint32_t address = 0;
|
||||
if (base_addr_value) {
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_addr_value);
|
||||
if (heap->AllocFixed(base_addr_value, adjusted_size, page_size,
|
||||
allocation_type, protect)) {
|
||||
address = base_addr_value;
|
||||
}
|
||||
} else {
|
||||
bool top_down = !!(alloc_type & X_MEM_TOP_DOWN);
|
||||
auto heap = kernel_state->memory()->LookupHeapByType(false, page_size);
|
||||
heap->Alloc(adjusted_size, page_size, allocation_type, protect, top_down,
|
||||
&address);
|
||||
}
|
||||
if (!address) {
|
||||
// Failed - assume no memory available.
|
||||
SHIM_SET_RETURN_32(X_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
// Zero memory, if needed.
|
||||
if (address && !(alloc_type & X_MEM_NOZERO)) {
|
||||
if (alloc_type & X_MEM_COMMIT) {
|
||||
kernel_state->memory()->Zero(address, adjusted_size);
|
||||
}
|
||||
}
|
||||
|
||||
XELOGD("NtAllocateVirtualMemory = %.8X", address);
|
||||
|
||||
// Stash back.
|
||||
// Maybe set X_STATUS_ALREADY_COMMITTED if MEM_COMMIT?
|
||||
SHIM_SET_MEM_32(base_addr_ptr, address);
|
||||
SHIM_SET_MEM_32(region_size_ptr, adjusted_size);
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL NtFreeVirtualMemory_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||
// X_MEM_DECOMMIT | X_MEM_RELEASE
|
||||
uint32_t free_type = SHIM_GET_ARG_32(2);
|
||||
uint32_t unknown = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("NtFreeVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X)",
|
||||
base_addr_ptr, base_addr_value, region_size_ptr, region_size_value,
|
||||
free_type, unknown);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PVOID *BaseAddress,
|
||||
// _Inout_ PSIZE_T RegionSize,
|
||||
// _In_ ULONG FreeType
|
||||
// ? handle?
|
||||
|
||||
// I've only seen zero.
|
||||
assert_true(unknown == 0);
|
||||
|
||||
if (!base_addr_value) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_MEMORY_NOT_ALLOCATED);
|
||||
return;
|
||||
}
|
||||
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_addr_value);
|
||||
bool result = false;
|
||||
if (free_type == X_MEM_DECOMMIT) {
|
||||
// If zero, we may need to query size (free whole region).
|
||||
assert_not_zero(region_size_value);
|
||||
|
||||
region_size_value = xe::round_up(region_size_value, heap->page_size());
|
||||
result = heap->Decommit(base_addr_value, region_size_value);
|
||||
} else {
|
||||
result = heap->Release(base_addr_value, ®ion_size_value);
|
||||
}
|
||||
if (!result) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_UNSUCCESSFUL);
|
||||
return;
|
||||
}
|
||||
|
||||
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
|
||||
SHIM_SET_MEM_32(region_size_ptr, region_size_value);
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
struct X_MEMORY_BASIC_INFORMATION {
|
||||
be<uint32_t> base_address;
|
||||
be<uint32_t> allocation_base;
|
||||
be<uint32_t> allocation_protect;
|
||||
be<uint32_t> region_size;
|
||||
be<uint32_t> state;
|
||||
be<uint32_t> protect;
|
||||
be<uint32_t> type;
|
||||
};
|
||||
|
||||
SHIM_CALL NtQueryVirtualMemory_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
uint32_t memory_basic_information_ptr = SHIM_GET_ARG_32(1);
|
||||
auto memory_basic_information =
|
||||
SHIM_STRUCT(X_MEMORY_BASIC_INFORMATION, memory_basic_information_ptr);
|
||||
|
||||
XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address,
|
||||
memory_basic_information_ptr);
|
||||
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_address);
|
||||
HeapAllocationInfo alloc_info;
|
||||
if (heap == nullptr || !heap->QueryRegionInfo(base_address, &alloc_info)) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
memory_basic_information->base_address =
|
||||
static_cast<uint32_t>(alloc_info.base_address);
|
||||
memory_basic_information->allocation_base =
|
||||
static_cast<uint32_t>(alloc_info.allocation_base);
|
||||
memory_basic_information->allocation_protect =
|
||||
ToXdkProtectFlags(alloc_info.allocation_protect);
|
||||
memory_basic_information->region_size =
|
||||
static_cast<uint32_t>(alloc_info.region_size);
|
||||
uint32_t x_state = 0;
|
||||
if (alloc_info.state & kMemoryAllocationReserve) {
|
||||
x_state |= X_MEM_RESERVE;
|
||||
}
|
||||
if (alloc_info.state & kMemoryAllocationCommit) {
|
||||
x_state |= X_MEM_COMMIT;
|
||||
}
|
||||
memory_basic_information->state = x_state;
|
||||
memory_basic_information->protect = ToXdkProtectFlags(alloc_info.protect);
|
||||
memory_basic_information->type = alloc_info.type;
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t type = SHIM_GET_ARG_32(0);
|
||||
uint32_t region_size = SHIM_GET_ARG_32(1);
|
||||
uint32_t protect_bits = SHIM_GET_ARG_32(2);
|
||||
uint32_t min_addr_range = SHIM_GET_ARG_32(3);
|
||||
uint32_t max_addr_range = SHIM_GET_ARG_32(4);
|
||||
uint32_t alignment = SHIM_GET_ARG_32(5);
|
||||
|
||||
XELOGD("MmAllocatePhysicalMemoryEx(%d, %.8X, %.8X, %.8X, %.8X, %.8X)", type,
|
||||
region_size, protect_bits, min_addr_range, max_addr_range, alignment);
|
||||
|
||||
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
|
||||
// by D3D/etc.
|
||||
|
||||
// Check protection bits.
|
||||
if (!(protect_bits & (X_PAGE_READONLY | X_PAGE_READWRITE))) {
|
||||
XELOGE("MmAllocatePhysicalMemoryEx: bad protection bits");
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Either may be OR'ed into protect_bits:
|
||||
// X_PAGE_NOCACHE
|
||||
// X_PAGE_WRITECOMBINE
|
||||
// We could use this to detect what's likely GPU-synchronized memory
|
||||
// and let the GPU know we're messing with it (or even allocate from
|
||||
// the GPU). At least the D3D command buffer is X_PAGE_WRITECOMBINE.
|
||||
|
||||
// Calculate page size.
|
||||
// Default = 4KB
|
||||
// X_MEM_LARGE_PAGES = 64KB
|
||||
// X_MEM_16MB_PAGES = 16MB
|
||||
uint32_t page_size = 4 * 1024;
|
||||
if (protect_bits & X_MEM_LARGE_PAGES) {
|
||||
page_size = 64 * 1024;
|
||||
} else if (protect_bits & X_MEM_16MB_PAGES) {
|
||||
page_size = 16 * 1024 * 1024;
|
||||
}
|
||||
|
||||
// Round up the region size and alignment to the next page.
|
||||
uint32_t adjusted_size = xe::round_up(region_size, page_size);
|
||||
uint32_t adjusted_alignment = xe::round_up(alignment, page_size);
|
||||
|
||||
// Callers can pick an address to allocate with min_addr_range/max_addr_range
|
||||
// and the memory must be allocated there. I haven't seen a game do this,
|
||||
// and instead they all do min=0 / max=-1 to indicate the system should pick.
|
||||
// If we have to suport arbitrary placement things will get nasty.
|
||||
|
||||
uint32_t allocation_type = kMemoryAllocationReserve | kMemoryAllocationCommit;
|
||||
uint32_t protect = FromXdkProtectFlags(protect_bits);
|
||||
bool top_down = true;
|
||||
auto heap = kernel_state->memory()->LookupHeapByType(true, page_size);
|
||||
uint32_t base_address;
|
||||
if (!heap->AllocRange(min_addr_range, max_addr_range, adjusted_size,
|
||||
adjusted_alignment, allocation_type, protect, top_down,
|
||||
&base_address)) {
|
||||
// Failed - assume no memory available.
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
XELOGD("MmAllocatePhysicalMemoryEx = %.8X", base_address);
|
||||
|
||||
SHIM_SET_RETURN_32(base_address);
|
||||
}
|
||||
|
||||
SHIM_CALL MmFreePhysicalMemory_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t type = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_address = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("MmFreePhysicalAddress(%d, %.8X)", type, base_address);
|
||||
|
||||
// base_address = result of MmAllocatePhysicalMemory.
|
||||
|
||||
assert_true((base_address & 0x1F) == 0);
|
||||
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_address);
|
||||
heap->Release(base_address);
|
||||
}
|
||||
|
||||
SHIM_CALL MmQueryAddressProtect_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("MmQueryAddressProtect(%.8X)", base_address);
|
||||
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_address);
|
||||
uint32_t access;
|
||||
if (!heap->QueryProtect(base_address, &access)) {
|
||||
access = 0;
|
||||
}
|
||||
access = ToXdkProtectFlags(access);
|
||||
|
||||
SHIM_SET_RETURN_32(access);
|
||||
}
|
||||
|
||||
void MmSetAddressProtect(lpvoid_t base_address, dword_t region_size,
|
||||
dword_t protect_bits) {
|
||||
uint32_t protect = FromXdkProtectFlags(protect_bits);
|
||||
auto heap = kernel_memory()->LookupHeap(base_address);
|
||||
heap->Protect(base_address.guest_address(), region_size, protect);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(MmSetAddressProtect, ExportTag::kMemory);
|
||||
|
||||
SHIM_CALL MmQueryAllocationSize_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("MmQueryAllocationSize(%.8X)", base_address);
|
||||
|
||||
auto heap = kernel_state->memory()->LookupHeap(base_address);
|
||||
uint32_t size;
|
||||
if (!heap->QuerySize(base_address, &size)) {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(size);
|
||||
}
|
||||
|
||||
// https://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h
|
||||
struct X_MM_QUERY_STATISTICS_SECTION {
|
||||
xe::be<uint32_t> available_pages;
|
||||
xe::be<uint32_t> total_virtual_memory_bytes;
|
||||
xe::be<uint32_t> reserved_virtual_memory_bytes;
|
||||
xe::be<uint32_t> physical_pages;
|
||||
xe::be<uint32_t> pool_pages;
|
||||
xe::be<uint32_t> stack_pages;
|
||||
xe::be<uint32_t> image_pages;
|
||||
xe::be<uint32_t> heap_pages;
|
||||
xe::be<uint32_t> virtual_pages;
|
||||
xe::be<uint32_t> page_table_pages;
|
||||
xe::be<uint32_t> cache_pages;
|
||||
};
|
||||
|
||||
struct X_MM_QUERY_STATISTICS_RESULT {
|
||||
xe::be<uint32_t> size;
|
||||
xe::be<uint32_t> total_physical_pages;
|
||||
xe::be<uint32_t> kernel_pages;
|
||||
X_MM_QUERY_STATISTICS_SECTION title;
|
||||
X_MM_QUERY_STATISTICS_SECTION system;
|
||||
xe::be<uint32_t> highest_physical_page;
|
||||
};
|
||||
static_assert_size(X_MM_QUERY_STATISTICS_RESULT, 104);
|
||||
|
||||
SHIM_CALL MmQueryStatistics_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t stats_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("MmQueryStatistics(%.8X)", stats_ptr);
|
||||
|
||||
if (stats_ptr == 0) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t size = sizeof(X_MM_QUERY_STATISTICS_RESULT);
|
||||
|
||||
auto stats =
|
||||
reinterpret_cast<X_MM_QUERY_STATISTICS_RESULT*>(SHIM_MEM_ADDR(stats_ptr));
|
||||
if (stats->size != size) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_BUFFER_TOO_SMALL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Zero out the struct.
|
||||
std::memset(stats, 0, size);
|
||||
|
||||
// Set the constants the game is likely asking for.
|
||||
// These numbers are mostly guessed. If the game is just checking for
|
||||
// memory, this should satisfy it. If it's actually verifying things
|
||||
// this won't work :/
|
||||
stats->size = size;
|
||||
|
||||
stats->total_physical_pages = 0x00020000;
|
||||
stats->kernel_pages = 0x00000300;
|
||||
|
||||
stats->title.available_pages = 0x00013300;
|
||||
stats->title.total_virtual_memory_bytes = 0x2FFF0000;
|
||||
stats->title.reserved_virtual_memory_bytes = 0x00160000;
|
||||
stats->title.physical_pages = 0x00001000;
|
||||
stats->title.pool_pages = 0x00000010;
|
||||
stats->title.stack_pages = 0x00000100;
|
||||
stats->title.image_pages = 0x00000100;
|
||||
stats->title.heap_pages = 0x00000100;
|
||||
stats->title.virtual_pages = 0x00000100;
|
||||
stats->title.page_table_pages = 0x00000100;
|
||||
stats->title.cache_pages = 0x00000100;
|
||||
|
||||
stats->system.available_pages = 0x00000000;
|
||||
stats->system.total_virtual_memory_bytes = 0x00000000;
|
||||
stats->system.reserved_virtual_memory_bytes = 0x00000000;
|
||||
stats->system.physical_pages = 0x00000000;
|
||||
stats->system.pool_pages = 0x00000000;
|
||||
stats->system.stack_pages = 0x00000000;
|
||||
stats->system.image_pages = 0x00000000;
|
||||
stats->system.heap_pages = 0x00000000;
|
||||
stats->system.virtual_pages = 0x00000000;
|
||||
stats->system.page_table_pages = 0x00000000;
|
||||
stats->system.cache_pages = 0x00000000;
|
||||
|
||||
stats->highest_physical_page = 0x0001FFFF;
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
|
||||
SHIM_CALL MmGetPhysicalAddress_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("MmGetPhysicalAddress(%.8X)", base_address);
|
||||
|
||||
// PHYSICAL_ADDRESS MmGetPhysicalAddress(
|
||||
// _In_ PVOID BaseAddress
|
||||
// );
|
||||
// base_address = result of MmAllocatePhysicalMemory.
|
||||
|
||||
uint32_t physical_address = base_address & 0x1FFFFFFF;
|
||||
if (base_address >= 0xE0000000) {
|
||||
physical_address += 0x1000;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(physical_address);
|
||||
}
|
||||
|
||||
SHIM_CALL MmMapIoSpace_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t src_address = SHIM_GET_ARG_32(1); // from MmGetPhysicalAddress
|
||||
uint32_t size = SHIM_GET_ARG_32(2);
|
||||
uint32_t flags = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("MmMapIoSpace(%.8X, %.8X, %d, %.8X)", unk0, src_address, size, flags);
|
||||
|
||||
// I've only seen this used to map XMA audio contexts.
|
||||
// The code seems fine with taking the src address, so this just returns that.
|
||||
// If others start using it there could be problems.
|
||||
assert_true(unk0 == 2);
|
||||
assert_true(size == 0x40);
|
||||
assert_true(flags == 0x404);
|
||||
|
||||
SHIM_SET_RETURN_32(src_address);
|
||||
}
|
||||
|
||||
SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t size = SHIM_GET_ARG_32(0);
|
||||
uint32_t tag = SHIM_GET_ARG_32(1);
|
||||
uint32_t zero = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("ExAllocatePoolTypeWithTag(%d, %.8X, %d)", size, tag, zero);
|
||||
|
||||
uint32_t alignment = 8;
|
||||
uint32_t adjusted_size = size;
|
||||
if (adjusted_size < 4 * 1024) {
|
||||
adjusted_size = xe::round_up(adjusted_size, 4 * 1024);
|
||||
} else {
|
||||
alignment = 4 * 1024;
|
||||
}
|
||||
|
||||
uint32_t addr =
|
||||
kernel_state->memory()->SystemHeapAlloc(adjusted_size, alignment);
|
||||
|
||||
SHIM_SET_RETURN_32(addr);
|
||||
}
|
||||
|
||||
SHIM_CALL ExFreePool_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("ExFreePool(%.8X)", base_address);
|
||||
|
||||
kernel_state->memory()->SystemHeapFree(base_address);
|
||||
}
|
||||
|
||||
SHIM_CALL KeLockL2_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
// Ignored for now. This is just a perf optimization, I think.
|
||||
// It may be useful as a hint for CPU-GPU transfer.
|
||||
|
||||
XELOGD("KeLockL2(?)");
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
SHIM_CALL KeUnlockL2_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
XELOGD("KeUnlockL2(?)");
|
||||
}
|
||||
|
||||
SHIM_CALL MmCreateKernelStack_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
auto stack_size = SHIM_GET_ARG_32(0);
|
||||
auto unk1 = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("MmCreateKernelStack(%.8X, %.8X)", stack_size, unk1);
|
||||
|
||||
stack_size = (stack_size + 0xFFF) & 0xFFFFF000;
|
||||
uint32_t stack_alignment = (stack_size & 0xF000) ? 0x1000 : 0x10000;
|
||||
|
||||
uint32_t stack_address;
|
||||
kernel_state->memory()
|
||||
->LookupHeap(0x70000000)
|
||||
->AllocRange(0x70000000, 0x7FFFFFFF, stack_size, stack_alignment,
|
||||
kMemoryAllocationReserve | kMemoryAllocationCommit,
|
||||
kMemoryProtectRead | kMemoryProtectWrite, false,
|
||||
&stack_address);
|
||||
SHIM_SET_RETURN_32(stack_address + stack_size);
|
||||
}
|
||||
|
||||
SHIM_CALL MmDeleteKernelStack_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
auto unk0 = SHIM_GET_ARG_32(0);
|
||||
auto unk1 = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("MmDeleteKernelStack(%.8X, %.8X)", unk0, unk1);
|
||||
|
||||
assert_always();
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
void RegisterMemoryExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtAllocateVirtualMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtFreeVirtualMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVirtualMemory, state);
|
||||
// SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemoryEx, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmFreePhysicalMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmQueryAddressProtect, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmQueryAllocationSize, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmQueryStatistics, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmGetPhysicalAddress, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmMapIoSpace, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExAllocatePoolTypeWithTag, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExFreePool, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeLockL2, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeUnlockL2, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmCreateKernelStack, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmDeleteKernelStack, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
35
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc
Normal file
35
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
SHIM_CALL KeEnableFpuExceptions_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t enabled = SHIM_GET_ARG_32(0);
|
||||
XELOGD("KeEnableFpuExceptions(%d)", enabled);
|
||||
// TODO(benvanik): can we do anything about exceptions?
|
||||
}
|
||||
|
||||
void RegisterMiscExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnableFpuExceptions, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
202
src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc
Normal file
202
src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
||||
: KernelModule(kernel_state, "xe:\\xboxkrnl.exe"),
|
||||
timestamp_timer_(nullptr) {
|
||||
RegisterExportTable(export_resolver_);
|
||||
|
||||
// Register all exported functions.
|
||||
RegisterAudioExports(export_resolver_, kernel_state_);
|
||||
RegisterAudioXmaExports(export_resolver_, kernel_state_);
|
||||
RegisterCryptExports(export_resolver_, kernel_state_);
|
||||
RegisterDebugExports(export_resolver_, kernel_state_);
|
||||
RegisterErrorExports(export_resolver_, kernel_state_);
|
||||
RegisterHalExports(export_resolver_, kernel_state_);
|
||||
RegisterIoExports(export_resolver_, kernel_state_);
|
||||
RegisterMemoryExports(export_resolver_, kernel_state_);
|
||||
RegisterMiscExports(export_resolver_, kernel_state_);
|
||||
RegisterModuleExports(export_resolver_, kernel_state_);
|
||||
RegisterObExports(export_resolver_, kernel_state_);
|
||||
RegisterRtlExports(export_resolver_, kernel_state_);
|
||||
RegisterStringExports(export_resolver_, kernel_state_);
|
||||
RegisterThreadingExports(export_resolver_, kernel_state_);
|
||||
RegisterUsbcamExports(export_resolver_, kernel_state_);
|
||||
RegisterVideoExports(export_resolver_, kernel_state_);
|
||||
|
||||
// KeDebugMonitorData (?*)
|
||||
// Set to a valid value when a remote debugger is attached.
|
||||
// Offset 0x18 is a 4b pointer to a handler function that seems to take two
|
||||
// arguments. If we wanted to see what would happen we could fake that.
|
||||
uint32_t pKeDebugMonitorData = memory_->SystemHeapAlloc(256);
|
||||
auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0);
|
||||
|
||||
// KeCertMonitorData (?*)
|
||||
// Always set to zero, ignored.
|
||||
uint32_t pKeCertMonitorData = memory_->SystemHeapAlloc(4);
|
||||
auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeCertMonitorData, 0);
|
||||
|
||||
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
|
||||
// flags cpu# ? ? ? ? ? ?
|
||||
// 0x00000000, 0x06, 0x00, 0x00, 0x00, 0x00000000, 0x0000, 0x0000
|
||||
// Games seem to check if bit 26 (0x20) is set, which at least for xbox1
|
||||
// was whether an HDD was present. Not sure what the other flags are.
|
||||
//
|
||||
// aomega08 says the value is 0x02000817, bit 27: debug mode on.
|
||||
// When that is set, though, allocs crash in weird ways.
|
||||
uint32_t pXboxHardwareInfo = memory_->SystemHeapAlloc(16);
|
||||
auto lpXboxHardwareInfo = memory_->TranslateVirtual(pXboxHardwareInfo);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::XboxHardwareInfo, pXboxHardwareInfo);
|
||||
xe::store_and_swap<uint32_t>(lpXboxHardwareInfo + 0, 0); // flags
|
||||
xe::store_and_swap<uint8_t>(lpXboxHardwareInfo + 4, 0x06); // cpu count
|
||||
// Remaining 11b are zeroes?
|
||||
|
||||
// XexExecutableModuleHandle (?**)
|
||||
// Games try to dereference this to get a pointer to some module struct.
|
||||
// So far it seems like it's just in loader code, and only used to look up
|
||||
// the XexHeaderBase for use by RtlImageXexHeaderField.
|
||||
// We fake it so that the address passed to that looks legit.
|
||||
// 0x80100FFC <- pointer to structure
|
||||
// 0x80101000 <- our module structure
|
||||
// 0x80101058 <- pointer to xex header
|
||||
// 0x80101100 <- xex header base
|
||||
uint32_t ppXexExecutableModuleHandle = memory_->SystemHeapAlloc(4);
|
||||
export_resolver_->SetVariableMapping("xboxkrnl.exe",
|
||||
ordinals::XexExecutableModuleHandle,
|
||||
ppXexExecutableModuleHandle);
|
||||
|
||||
// ExLoadedCommandLine (char*)
|
||||
// The name of the xex. Not sure this is ever really used on real devices.
|
||||
// Perhaps it's how swap disc/etc data is sent?
|
||||
// Always set to "default.xex" (with quotes) for now.
|
||||
uint32_t pExLoadedCommandLine = memory_->SystemHeapAlloc(1024);
|
||||
auto lpExLoadedCommandLine = memory_->TranslateVirtual(pExLoadedCommandLine);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::ExLoadedCommandLine, pExLoadedCommandLine);
|
||||
char command_line[] = "\"default.xex\"";
|
||||
std::memcpy(lpExLoadedCommandLine, command_line,
|
||||
xe::countof(command_line) + 1);
|
||||
|
||||
// XboxKrnlVersion (8b)
|
||||
// Kernel version, looks like 2b.2b.2b.2b.
|
||||
// I've only seen games check >=, so we just fake something here.
|
||||
uint32_t pXboxKrnlVersion = memory_->SystemHeapAlloc(8);
|
||||
auto lpXboxKrnlVersion = memory_->TranslateVirtual(pXboxKrnlVersion);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::XboxKrnlVersion, pXboxKrnlVersion);
|
||||
xe::store_and_swap<uint16_t>(lpXboxKrnlVersion + 0, 2);
|
||||
xe::store_and_swap<uint16_t>(lpXboxKrnlVersion + 2, 0xFFFF);
|
||||
xe::store_and_swap<uint16_t>(lpXboxKrnlVersion + 4, 0xFFFF);
|
||||
xe::store_and_swap<uint8_t>(lpXboxKrnlVersion + 6, 0x80);
|
||||
xe::store_and_swap<uint8_t>(lpXboxKrnlVersion + 7, 0x00);
|
||||
|
||||
// KeTimeStampBundle (ad)
|
||||
// This must be updated during execution, at 1ms intevals.
|
||||
// We setup a system timer here to do that.
|
||||
uint32_t pKeTimeStampBundle = memory_->SystemHeapAlloc(24);
|
||||
auto lpKeTimeStampBundle = memory_->TranslateVirtual(pKeTimeStampBundle);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle);
|
||||
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0);
|
||||
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0);
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16,
|
||||
Clock::QueryGuestUptimeMillis());
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0);
|
||||
timestamp_timer_ = xe::threading::HighResolutionTimer::CreateRepeating(
|
||||
std::chrono::milliseconds(1), [lpKeTimeStampBundle]() {
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16,
|
||||
Clock::QueryGuestUptimeMillis());
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<xe::cpu::Export*> xboxkrnl_exports(4096);
|
||||
|
||||
xe::cpu::Export* RegisterExport_xboxkrnl(xe::cpu::Export* export_entry) {
|
||||
assert_true(export_entry->ordinal < xboxkrnl_exports.size());
|
||||
xboxkrnl_exports[export_entry->ordinal] = export_entry;
|
||||
return export_entry;
|
||||
}
|
||||
|
||||
void XboxkrnlModule::RegisterExportTable(
|
||||
xe::cpu::ExportResolver* export_resolver) {
|
||||
assert_not_null(export_resolver);
|
||||
|
||||
// Build the export table used for resolution.
|
||||
#include "xenia/kernel/util/export_table_pre.inc"
|
||||
static xe::cpu::Export xboxkrnl_export_table[] = {
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_table.inc"
|
||||
};
|
||||
#include "xenia/kernel/util/export_table_post.inc"
|
||||
for (size_t i = 0; i < xe::countof(xboxkrnl_export_table); ++i) {
|
||||
auto& export_entry = xboxkrnl_export_table[i];
|
||||
assert_true(export_entry.ordinal < xboxkrnl_exports.size());
|
||||
if (!xboxkrnl_exports[export_entry.ordinal]) {
|
||||
xboxkrnl_exports[export_entry.ordinal] = &export_entry;
|
||||
}
|
||||
}
|
||||
export_resolver->RegisterTable("xboxkrnl.exe", &xboxkrnl_exports);
|
||||
}
|
||||
|
||||
XboxkrnlModule::~XboxkrnlModule() = default;
|
||||
|
||||
int XboxkrnlModule::LaunchModule(const char* path) {
|
||||
// Create and register the module. We keep it local to this function and
|
||||
// dispose it on exit.
|
||||
auto module = kernel_state_->LoadUserModule(path);
|
||||
if (!module) {
|
||||
XELOGE("Failed to load user module %s.", path);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Set as the main module, while running.
|
||||
kernel_state_->SetExecutableModule(module);
|
||||
|
||||
// Launch the module.
|
||||
// NOTE: this won't return until the module exits.
|
||||
X_STATUS result_code = module->Launch(0);
|
||||
|
||||
// Main thread exited. Terminate the title.
|
||||
kernel_state_->TerminateTitle();
|
||||
kernel_state_->SetExecutableModule(NULL);
|
||||
if (XFAILED(result_code)) {
|
||||
XELOGE("Failed to launch module %s: %.8X", path, result_code);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
45
src/xenia/kernel/xboxkrnl/xboxkrnl_module.h
Normal file
45
src/xenia/kernel/xboxkrnl/xboxkrnl_module.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/kernel/kernel_module.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h"
|
||||
|
||||
// All of the exported functions:
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_rtl.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
class XboxkrnlModule : public KernelModule {
|
||||
public:
|
||||
XboxkrnlModule(Emulator* emulator, KernelState* kernel_state);
|
||||
virtual ~XboxkrnlModule();
|
||||
|
||||
static void RegisterExportTable(xe::cpu::ExportResolver* export_resolver);
|
||||
|
||||
int LaunchModule(const char* path);
|
||||
|
||||
private:
|
||||
std::unique_ptr<xe::threading::HighResolutionTimer> timestamp_timer_;
|
||||
};
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MODULE_H_
|
||||
358
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc
Normal file
358
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc
Normal file
@@ -0,0 +1,358 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/util/xex2.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting,
|
||||
void* buffer, uint16_t buffer_size,
|
||||
uint16_t* required_size) {
|
||||
uint16_t setting_size = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
// TODO(benvanik): have real structs here that just get copied from.
|
||||
// http://free60.org/XConfig
|
||||
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
|
||||
switch (category) {
|
||||
case 0x0002:
|
||||
// XCONFIG_SECURED_CATEGORY
|
||||
switch (setting) {
|
||||
case 0x0002: // XCONFIG_SECURED_AV_REGION
|
||||
setting_size = 4;
|
||||
value = 0x00001000; // USA/Canada
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(setting);
|
||||
return X_STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
break;
|
||||
case 0x0003:
|
||||
// XCONFIG_USER_CATEGORY
|
||||
switch (setting) {
|
||||
case 0x0001: // XCONFIG_USER_TIME_ZONE_BIAS
|
||||
case 0x0002: // XCONFIG_USER_TIME_ZONE_STD_NAME
|
||||
case 0x0003: // XCONFIG_USER_TIME_ZONE_DLT_NAME
|
||||
case 0x0004: // XCONFIG_USER_TIME_ZONE_STD_DATE
|
||||
case 0x0005: // XCONFIG_USER_TIME_ZONE_DLT_DATE
|
||||
case 0x0006: // XCONFIG_USER_TIME_ZONE_STD_BIAS
|
||||
case 0x0007: // XCONFIG_USER_TIME_ZONE_DLT_BIAS
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
case 0x0009: // XCONFIG_USER_LANGUAGE
|
||||
setting_size = 4;
|
||||
value = 0x00000001; // English
|
||||
break;
|
||||
case 0x000A: // XCONFIG_USER_VIDEO_FLAGS
|
||||
setting_size = 4;
|
||||
value = 0x00040000;
|
||||
break;
|
||||
case 0x000C: // XCONFIG_USER_RETAIL_FLAGS
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
case 0x000E: // XCONFIG_USER_COUNTRY
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(setting);
|
||||
return X_STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(category);
|
||||
return X_STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
|
||||
if (buffer_size < setting_size) {
|
||||
return X_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
if (!buffer && buffer_size) {
|
||||
return X_STATUS_INVALID_PARAMETER_3;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
xe::store_and_swap<uint32_t>(buffer, value);
|
||||
}
|
||||
if (required_size) {
|
||||
*required_size = setting_size;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SHIM_CALL ExGetXConfigSetting_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint16_t category = SHIM_GET_ARG_16(0);
|
||||
uint16_t setting = SHIM_GET_ARG_16(1);
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
|
||||
uint16_t buffer_size = SHIM_GET_ARG_16(3);
|
||||
uint32_t required_size_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD("ExGetXConfigSetting(%.4X, %.4X, %.8X, %.4X, %.8X)", category, setting,
|
||||
buffer_ptr, buffer_size, required_size_ptr);
|
||||
|
||||
void* buffer = buffer_ptr ? SHIM_MEM_ADDR(buffer_ptr) : NULL;
|
||||
uint16_t required_size = 0;
|
||||
X_STATUS result = xeExGetXConfigSetting(category, setting, buffer,
|
||||
buffer_size, &required_size);
|
||||
|
||||
if (required_size_ptr) {
|
||||
SHIM_SET_MEM_16(required_size_ptr, required_size);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t privilege = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XexCheckExecutablePrivilege(%.8X)", privilege);
|
||||
|
||||
// BOOL
|
||||
// DWORD Privilege
|
||||
|
||||
// Privilege is bit position in xe_xex2_system_flags enum - so:
|
||||
// Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
|
||||
uint32_t mask = 1 << privilege;
|
||||
|
||||
auto module = kernel_state->GetExecutableModule();
|
||||
if (!module) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
module->GetOptHeader<uint32_t>(XEX_HEADER_SYSTEM_FLAGS, &flags);
|
||||
|
||||
SHIM_SET_RETURN_32((flags & mask) > 0);
|
||||
}
|
||||
|
||||
SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
|
||||
const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
|
||||
uint32_t hmodule_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, hmodule_ptr);
|
||||
|
||||
object_ref<XModule> module;
|
||||
if (!module_name) {
|
||||
module = kernel_state->GetExecutableModule();
|
||||
} else {
|
||||
module = kernel_state->GetModule(module_name);
|
||||
}
|
||||
if (!module) {
|
||||
SHIM_SET_MEM_32(hmodule_ptr, 0);
|
||||
SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we don't retain the handle for return.
|
||||
SHIM_SET_MEM_32(hmodule_ptr, module->hmodule_ptr());
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t hmodule = SHIM_GET_ARG_32(0);
|
||||
uint32_t name_ptr = SHIM_GET_ARG_32(1);
|
||||
const char* name = (const char*)SHIM_MEM_ADDR(name_ptr);
|
||||
uint32_t data_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t size_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", hmodule, name, data_ptr,
|
||||
size_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
auto module = XModule::GetFromHModule(kernel_state, SHIM_MEM_ADDR(hmodule));
|
||||
if (module) {
|
||||
uint32_t section_data = 0;
|
||||
uint32_t section_size = 0;
|
||||
result = module->GetSection(name, §ion_data, §ion_size);
|
||||
if (XSUCCEEDED(result)) {
|
||||
SHIM_SET_MEM_32(data_ptr, section_data);
|
||||
SHIM_SET_MEM_32(size_ptr, section_size);
|
||||
}
|
||||
} else {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL XexLoadImage_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
|
||||
const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
|
||||
uint32_t module_flags = SHIM_GET_ARG_32(1);
|
||||
uint32_t min_version = SHIM_GET_ARG_32(2);
|
||||
uint32_t hmodule_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("XexLoadImage(%s, %.8X, %.8X, %.8X)", module_name, module_flags,
|
||||
min_version, hmodule_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
||||
|
||||
uint32_t hmodule = 0;
|
||||
auto module = kernel_state->GetModule(module_name);
|
||||
if (module) {
|
||||
// Existing module found.
|
||||
hmodule = module->hmodule_ptr();
|
||||
result = X_STATUS_SUCCESS;
|
||||
} else {
|
||||
// Not found; attempt to load as a user module.
|
||||
auto user_module = kernel_state->LoadUserModule(module_name);
|
||||
if (user_module) {
|
||||
user_module->Retain();
|
||||
hmodule = user_module->hmodule_ptr();
|
||||
result = X_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the module's load count.
|
||||
if (hmodule) {
|
||||
auto ldr_data =
|
||||
kernel_memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(hmodule);
|
||||
ldr_data->load_count++;
|
||||
}
|
||||
|
||||
SHIM_SET_MEM_32(hmodule_ptr, hmodule);
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL XexUnloadImage_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t hmodule = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("XexUnloadImage(%.8X)", hmodule);
|
||||
|
||||
auto module = XModule::GetFromHModule(kernel_state, SHIM_MEM_ADDR(hmodule));
|
||||
if (!module) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't unload kernel modules from user code.
|
||||
if (module->module_type() != XModule::ModuleType::kKernelModule) {
|
||||
auto ldr_data =
|
||||
kernel_state->memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(
|
||||
hmodule);
|
||||
if (--ldr_data->load_count == 0) {
|
||||
// No more references, free it.
|
||||
module->Release();
|
||||
kernel_state->object_table()->RemoveHandle(module->handle());
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t hmodule = SHIM_GET_ARG_32(0);
|
||||
uint32_t ordinal = SHIM_GET_ARG_32(1);
|
||||
uint32_t out_function_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
// May be entry point?
|
||||
assert_not_zero(ordinal);
|
||||
|
||||
bool is_string_name = (ordinal & 0xFFFF0000) != 0;
|
||||
auto string_name = reinterpret_cast<const char*>(SHIM_MEM_ADDR(ordinal));
|
||||
|
||||
if (is_string_name) {
|
||||
XELOGD("XexGetProcedureAddress(%.8X, %.8X(%s), %.8X)", hmodule, ordinal,
|
||||
string_name, out_function_ptr);
|
||||
} else {
|
||||
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", hmodule, ordinal,
|
||||
out_function_ptr);
|
||||
}
|
||||
|
||||
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
||||
|
||||
object_ref<XModule> module;
|
||||
if (!hmodule) {
|
||||
module = kernel_state->GetExecutableModule();
|
||||
} else {
|
||||
module = XModule::GetFromHModule(kernel_state, SHIM_MEM_ADDR(hmodule));
|
||||
}
|
||||
if (module) {
|
||||
uint32_t ptr;
|
||||
if (is_string_name) {
|
||||
ptr = module->GetProcAddressByName(string_name);
|
||||
} else {
|
||||
ptr = module->GetProcAddressByOrdinal(ordinal);
|
||||
}
|
||||
if (ptr) {
|
||||
SHIM_SET_MEM_32(out_function_ptr, ptr);
|
||||
result = X_STATUS_SUCCESS;
|
||||
} else {
|
||||
XELOGW("ERROR: XexGetProcedureAddress ordinal not found!");
|
||||
SHIM_SET_MEM_32(out_function_ptr, 0);
|
||||
result = X_STATUS_DRIVER_ORDINAL_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
void AppendParam(StringBuffer* string_buffer,
|
||||
pointer_t<X_EX_TITLE_TERMINATE_REGISTRATION> reg) {
|
||||
string_buffer->AppendFormat("%.8X(%.8X, %.8X)", reg.guest_address(),
|
||||
reg->notification_routine, reg->priority);
|
||||
}
|
||||
|
||||
void ExRegisterTitleTerminateNotification(
|
||||
pointer_t<X_EX_TITLE_TERMINATE_REGISTRATION> reg, dword_t create) {
|
||||
if (create) {
|
||||
// Adding.
|
||||
kernel_state()->RegisterTitleTerminateNotification(
|
||||
reg->notification_routine, reg->priority);
|
||||
} else {
|
||||
// Removing.
|
||||
kernel_state()->RemoveTitleTerminateNotification(reg->notification_routine);
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(ExRegisterTitleTerminateNotification,
|
||||
ExportTag::kImplemented);
|
||||
|
||||
void RegisterModuleExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
211
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc
Normal file
211
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xobject.h"
|
||||
#include "xenia/kernel/xsemaphore.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
SHIM_CALL ObOpenObjectByName_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
// r3 = ptr to info?
|
||||
// +0 = -4
|
||||
// +4 = name ptr
|
||||
// +8 = 0
|
||||
// r4 = ExEventObjectType | ExSemaphoreObjectType | ExTimerObjectType
|
||||
// r5 = 0
|
||||
// r6 = out_ptr (handle?)
|
||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk = SHIM_GET_ARG_32(2);
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
auto name =
|
||||
X_ANSI_STRING::to_string_indirect(SHIM_MEM_BASE, obj_attributes_ptr + 4);
|
||||
|
||||
XELOGD("ObOpenObjectByName(%.8X(name=%s), %.8X, %.8X, %.8X)",
|
||||
obj_attributes_ptr, name.c_str(), object_type_ptr, unk, handle_ptr);
|
||||
|
||||
X_HANDLE handle = X_INVALID_HANDLE_VALUE;
|
||||
X_STATUS result =
|
||||
kernel_state->object_table()->GetObjectByName(name, &handle);
|
||||
if (XSUCCEEDED(result)) {
|
||||
SHIM_SET_MEM_32(handle_ptr, handle);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
dword_result_t ObOpenObjectByPointer(lpvoid_t object_ptr,
|
||||
lpdword_t out_handle_ptr) {
|
||||
auto object = XObject::GetNativeObject<XObject>(kernel_state(), object_ptr);
|
||||
if (!object) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Retain the handle. Will be released in NtClose.
|
||||
object->RetainHandle();
|
||||
*out_handle_ptr = object->handle();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(ObOpenObjectByPointer, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t ObLookupThreadByThreadId(dword_t thread_id,
|
||||
lpdword_t out_object_ptr) {
|
||||
auto thread = kernel_state()->GetThreadByID(thread_id);
|
||||
if (!thread) {
|
||||
return X_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Retain the object. Will be released in ObDereferenceObject.
|
||||
thread->Retain();
|
||||
*out_object_ptr = thread->guest_object();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(ObLookupThreadByThreadId, ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t out_object_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("ObReferenceObjectByHandle(%.8X, %.8X, %.8X)", handle, object_type_ptr,
|
||||
out_object_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
auto object = kernel_state->object_table()->LookupObject<XObject>(handle);
|
||||
if (object) {
|
||||
// TODO(benvanik): verify type with object_type_ptr
|
||||
|
||||
// TODO(benvanik): get native value, if supported.
|
||||
uint32_t native_ptr;
|
||||
switch (object_type_ptr) {
|
||||
case 0x00000000: { // whatever?
|
||||
switch (object->type()) {
|
||||
case XObject::kTypeEvent: {
|
||||
assert(object->type() == XObject::kTypeEvent);
|
||||
native_ptr = object->guest_object();
|
||||
assert_not_zero(native_ptr);
|
||||
} break;
|
||||
case XObject::kTypeSemaphore: {
|
||||
assert(object->type() == XObject::kTypeSemaphore);
|
||||
native_ptr = object->guest_object();
|
||||
assert_not_zero(native_ptr);
|
||||
} break;
|
||||
case XObject::kTypeThread: {
|
||||
assert(object->type() == XObject::kTypeThread);
|
||||
native_ptr = object->guest_object();
|
||||
assert_not_zero(native_ptr);
|
||||
} break;
|
||||
default: {
|
||||
assert_unhandled_case(object->type());
|
||||
native_ptr = 0xDEADF00D;
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case 0xD017BEEF: { // ExSemaphoreObjectType
|
||||
assert(object->type() == XObject::kTypeSemaphore);
|
||||
native_ptr = object->guest_object();
|
||||
assert_not_zero(native_ptr);
|
||||
} break;
|
||||
case 0xD01BBEEF: { // ExThreadObjectType
|
||||
assert(object->type() == XObject::kTypeThread);
|
||||
native_ptr = object->guest_object();
|
||||
assert_not_zero(native_ptr);
|
||||
} break;
|
||||
default: {
|
||||
assert_unhandled_case(object_type_ptr);
|
||||
native_ptr = 0xDEADF00D;
|
||||
} break;
|
||||
}
|
||||
|
||||
// Caller takes the reference.
|
||||
// It's released in ObDereferenceObject.
|
||||
object->Retain();
|
||||
if (out_object_ptr) {
|
||||
SHIM_SET_MEM_32(out_object_ptr, native_ptr);
|
||||
}
|
||||
} else {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t native_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("ObDereferenceObject(%.8X)", native_ptr);
|
||||
|
||||
// Check if a dummy value from ObReferenceObjectByHandle.
|
||||
if (native_ptr == 0xDEADF00D) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
void* object_ptr = SHIM_MEM_ADDR(native_ptr);
|
||||
auto object = XObject::GetNativeObject<XObject>(kernel_state, object_ptr);
|
||||
if (object) {
|
||||
object->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr,
|
||||
dword_t options) {
|
||||
// NOTE: new_handle_ptr can be zero to just close a handle.
|
||||
// NOTE: this function seems to be used to get the current thread handle
|
||||
// (passed handle=-2).
|
||||
// This function actually just creates a new handle to the same object.
|
||||
// Most games use it to get real handles to the current thread or whatever.
|
||||
|
||||
X_HANDLE new_handle = X_INVALID_HANDLE_VALUE;
|
||||
X_STATUS result =
|
||||
kernel_state()->object_table()->DuplicateHandle(handle, &new_handle);
|
||||
|
||||
if (new_handle_ptr) {
|
||||
*new_handle_ptr = new_handle;
|
||||
}
|
||||
|
||||
if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) {
|
||||
// Always close the source object.
|
||||
kernel_state()->object_table()->RemoveHandle(handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtDuplicateObject, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t NtClose(dword_t handle) {
|
||||
return kernel_state()->object_table()->ReleaseHandle(handle);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtClose, ExportTag::kImplemented);
|
||||
|
||||
void RegisterObExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ObOpenObjectByName, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
24
src/xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h
Normal file
24
src/xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ORDINALS_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ORDINALS_H_
|
||||
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
|
||||
// Build an ordinal enum to make it easy to lookup ordinals.
|
||||
#include "xenia/kernel/util/ordinal_table_pre.inc"
|
||||
namespace ordinals {
|
||||
enum {
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_table.inc"
|
||||
};
|
||||
} // namespace ordinals
|
||||
#include "xenia/kernel/util/ordinal_table_post.inc"
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_ORDINALS_H_
|
||||
61
src/xenia/kernel/xboxkrnl/xboxkrnl_private.h
Normal file
61
src/xenia/kernel/xboxkrnl/xboxkrnl_private.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_PRIVATE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_PRIVATE_H_
|
||||
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
xe::cpu::Export* RegisterExport_xboxkrnl(xe::cpu::Export* export_entry);
|
||||
|
||||
// Registration functions, one per file.
|
||||
void RegisterAudioExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterCryptExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterHalExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterIoExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterMemoryExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterMiscExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterModuleExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterObExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterRtlExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterStringExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterUsbcamExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_PRIVATE_H_
|
||||
526
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc
Normal file
526
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc
Normal file
@@ -0,0 +1,526 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_rtl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/string.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/util/xex2.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
||||
// For FileTimeToSystemTime and SystemTimeToFileTime:
|
||||
#include "xenia/base/platform_win.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561778
|
||||
dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2,
|
||||
dword_t length) {
|
||||
uint8_t* p1 = source1;
|
||||
uint8_t* p2 = source2;
|
||||
|
||||
// Note that the return value is the number of bytes that match, so it's best
|
||||
// we just do this ourselves vs. using memcmp.
|
||||
// On Windows we could use the builtin function.
|
||||
|
||||
uint32_t c = 0;
|
||||
for (uint32_t n = 0; n < length; n++, p1++, p2++) {
|
||||
if (*p1 == *p2) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlCompareMemory, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff552123
|
||||
dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length,
|
||||
dword_t pattern) {
|
||||
// Return 0 if source/length not aligned
|
||||
if (source.guest_address() % 4 || length % 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t n = 0;
|
||||
for (uint32_t i = 0; i < (length / 4); i++) {
|
||||
// FIXME: This assumes as_array returns xe::be
|
||||
uint32_t val = source.as_array<uint32_t>()[i];
|
||||
if (val == pattern) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlCompareMemoryUlong, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff552263
|
||||
void RtlFillMemoryUlong(lpvoid_t destination, dword_t length, dword_t pattern) {
|
||||
// NOTE: length must be % 4, so we can work on uint32s.
|
||||
uint32_t count = length >> 2;
|
||||
|
||||
uint32_t* p = destination.as<uint32_t*>();
|
||||
uint32_t swapped_pattern = xe::byte_swap(pattern.value());
|
||||
for (uint32_t n = 0; n < count; n++, p++) {
|
||||
*p = swapped_pattern;
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlFillMemoryUlong, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t RtlCompareString(lpstring_t string_1, lpstring_t string_2,
|
||||
dword_t case_insensitive) {
|
||||
int ret = case_insensitive ? strcasecmp(string_1, string_2)
|
||||
: std::strcmp(string_1, string_2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlCompareString, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t RtlCompareStringN(lpstring_t string_1, dword_t string_1_len,
|
||||
lpstring_t string_2, dword_t string_2_len,
|
||||
dword_t case_insensitive) {
|
||||
uint32_t len1 = string_1_len;
|
||||
uint32_t len2 = string_2_len;
|
||||
|
||||
if (string_1_len == 0xFFFF) {
|
||||
len1 = uint32_t(std::strlen(string_1));
|
||||
}
|
||||
if (string_2_len == 0xFFFF) {
|
||||
len2 = uint32_t(std::strlen(string_2));
|
||||
}
|
||||
auto len = std::min(string_1_len, string_2_len);
|
||||
|
||||
int ret = case_insensitive ? strncasecmp(string_1, string_2, len)
|
||||
: std::strncmp(string_1, string_2, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlCompareStringN, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561918
|
||||
void RtlInitAnsiString(pointer_t<X_ANSI_STRING> destination,
|
||||
lpstring_t source) {
|
||||
if (source) {
|
||||
uint16_t length = (uint16_t)strlen(source);
|
||||
destination->length = length;
|
||||
destination->maximum_length = length + 1;
|
||||
} else {
|
||||
destination->reset();
|
||||
}
|
||||
|
||||
destination->pointer = source.guest_address();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlInitAnsiString, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561899
|
||||
void RtlFreeAnsiString(pointer_t<X_ANSI_STRING> string) {
|
||||
if (string->pointer) {
|
||||
kernel_memory()->SystemHeapFree(string->pointer);
|
||||
}
|
||||
|
||||
string->reset();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlFreeAnsiString, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561934
|
||||
void RtlInitUnicodeString(pointer_t<X_UNICODE_STRING> destination,
|
||||
lpwstring_t source) {
|
||||
if (source) {
|
||||
destination->length = (uint16_t)source.value().size() * 2;
|
||||
destination->maximum_length = (uint16_t)(source.value().size() + 1) * 2;
|
||||
destination->pointer = source.guest_address();
|
||||
} else {
|
||||
destination->reset();
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlInitUnicodeString, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561903
|
||||
void RtlFreeUnicodeString(pointer_t<X_UNICODE_STRING> string) {
|
||||
if (string->pointer) {
|
||||
kernel_memory()->SystemHeapFree(string->pointer);
|
||||
}
|
||||
|
||||
string->reset();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlFreeUnicodeString, ExportTag::kImplemented);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff562969
|
||||
SHIM_CALL RtlUnicodeStringToAnsiString_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t alloc_dest = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("RtlUnicodeStringToAnsiString(%.8X, %.8X, %d)", destination_ptr,
|
||||
source_ptr, alloc_dest);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PANSI_STRING DestinationString,
|
||||
// _In_ PCUNICODE_STRING SourceString,
|
||||
// _In_ BOOLEAN AllocateDestinationString
|
||||
|
||||
std::wstring unicode_str = xe::load_and_swap<std::wstring>(
|
||||
SHIM_MEM_ADDR(SHIM_MEM_32(source_ptr + 4)));
|
||||
std::string ansi_str = xe::to_string(unicode_str);
|
||||
if (ansi_str.size() > 0xFFFF - 1) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER_2);
|
||||
return;
|
||||
}
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
if (alloc_dest) {
|
||||
uint32_t buffer_ptr =
|
||||
kernel_state->memory()->SystemHeapAlloc(uint32_t(ansi_str.size() + 1));
|
||||
memcpy(SHIM_MEM_ADDR(buffer_ptr), ansi_str.data(), ansi_str.size() + 1);
|
||||
SHIM_SET_MEM_16(destination_ptr + 0,
|
||||
static_cast<uint16_t>(ansi_str.size()));
|
||||
SHIM_SET_MEM_16(destination_ptr + 2,
|
||||
static_cast<uint16_t>(ansi_str.size() + 1));
|
||||
SHIM_SET_MEM_32(destination_ptr + 4, static_cast<uint32_t>(buffer_ptr));
|
||||
} else {
|
||||
uint32_t buffer_capacity = SHIM_MEM_16(destination_ptr + 2);
|
||||
uint32_t buffer_ptr = SHIM_MEM_32(destination_ptr + 4);
|
||||
if (buffer_capacity < ansi_str.size() + 1) {
|
||||
// Too large - we just write what we can.
|
||||
result = X_STATUS_BUFFER_OVERFLOW;
|
||||
memcpy(SHIM_MEM_ADDR(buffer_ptr), ansi_str.data(), buffer_capacity - 1);
|
||||
} else {
|
||||
memcpy(SHIM_MEM_ADDR(buffer_ptr), ansi_str.data(), ansi_str.size() + 1);
|
||||
}
|
||||
SHIM_SET_MEM_8(buffer_ptr + buffer_capacity - 1, 0); // \0
|
||||
}
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL RtlMultiByteToUnicodeN_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t destination_len = SHIM_GET_ARG_32(1);
|
||||
uint32_t written_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t source_len = SHIM_GET_ARG_32(4);
|
||||
|
||||
uint32_t copy_len = destination_len >> 1;
|
||||
copy_len = copy_len < source_len ? copy_len : source_len;
|
||||
|
||||
// TODO(benvanik): maybe use MultiByteToUnicode on Win32? would require
|
||||
// swapping.
|
||||
|
||||
for (uint32_t i = 0; i < copy_len; i++) {
|
||||
xe::store_and_swap<uint16_t>(
|
||||
SHIM_MEM_ADDR(destination_ptr + i * 2),
|
||||
xe::load<uint8_t>(SHIM_MEM_ADDR(source_ptr + i)));
|
||||
}
|
||||
|
||||
if (written_ptr != 0) {
|
||||
SHIM_SET_MEM_32(written_ptr, copy_len << 1);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
SHIM_CALL RtlUnicodeToMultiByteN_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t destination_len = SHIM_GET_ARG_32(1);
|
||||
uint32_t written_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t source_len = SHIM_GET_ARG_32(4);
|
||||
|
||||
uint32_t copy_len = source_len >> 1;
|
||||
copy_len = copy_len < destination_len ? copy_len : destination_len;
|
||||
|
||||
// TODO(benvanik): maybe use UnicodeToMultiByte on Win32?
|
||||
|
||||
auto source = reinterpret_cast<uint16_t*>(SHIM_MEM_ADDR(source_ptr));
|
||||
auto destination = reinterpret_cast<uint8_t*>(SHIM_MEM_ADDR(destination_ptr));
|
||||
for (uint32_t i = 0; i < copy_len; i++) {
|
||||
uint16_t c = xe::byte_swap(*source++);
|
||||
*destination++ = c < 256 ? (uint8_t)c : '?';
|
||||
}
|
||||
|
||||
if (written_ptr != 0) {
|
||||
SHIM_SET_MEM_32(written_ptr, copy_len);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
pointer_result_t RtlImageXexHeaderField(pointer_t<xex2_header> xex_header,
|
||||
dword_t field_dword) {
|
||||
uint32_t field_value = 0;
|
||||
uint32_t field = field_dword; // VS acts weird going from dword_t -> enum
|
||||
|
||||
UserModule::GetOptHeader(kernel_memory()->virtual_membase(), xex_header,
|
||||
xe_xex2_header_keys(field), &field_value);
|
||||
|
||||
return field_value;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlImageXexHeaderField, ExportTag::kImplemented);
|
||||
|
||||
// Unfortunately the Windows RTL_CRITICAL_SECTION object is bigger than the one
|
||||
// on the 360 (32b vs. 28b). This means that we can't do in-place splatting of
|
||||
// the critical sections. Also, the 360 never calls RtlDeleteCriticalSection
|
||||
// so we can't clean up the native handles.
|
||||
//
|
||||
// Because of this, we reimplement it poorly. Hooray.
|
||||
// We have 28b to work with so we need to be careful. We map our struct directly
|
||||
// into guest memory, as it should be opaque and so long as our size is right
|
||||
// the user code will never know.
|
||||
//
|
||||
// Ref: http://msdn.microsoft.com/en-us/magazine/cc164040.aspx
|
||||
// Ref:
|
||||
// http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/critical.c?view=markup
|
||||
|
||||
// This structure tries to match the one on the 360 as best I can figure out.
|
||||
// Unfortunately some games have the critical sections pre-initialized in
|
||||
// their embedded data and InitializeCriticalSection will never be called.
|
||||
#pragma pack(push, 1)
|
||||
struct X_RTL_CRITICAL_SECTION {
|
||||
xe::be<uint8_t> unk_00; // 0x0
|
||||
xe::be<uint8_t> spin_count_div_256; // 0x1
|
||||
xe::be<uint16_t> __padding0; // 0x2
|
||||
xe::be<uint32_t> unk_04; // 0x4 maybe the handle to the event?
|
||||
xe::be<uint32_t> queue_head; // 0x8 head of queue, pointing to this offset
|
||||
xe::be<uint32_t> queue_tail; // 0xC tail of queue?
|
||||
int32_t lock_count; // 0x10 -1 -> 0 on first lock 0x10
|
||||
xe::be<int32_t> recursion_count; // 0x14 0 -> 1 on first lock 0x14
|
||||
xe::be<uint32_t> owning_thread_id; // 0x18 0 unless locked 0x18
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert_size(X_RTL_CRITICAL_SECTION, 28);
|
||||
|
||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||
uint32_t cs_ptr) {
|
||||
cs->unk_00 = 1;
|
||||
cs->spin_count_div_256 = 0;
|
||||
cs->queue_head = cs_ptr + 8;
|
||||
cs->queue_tail = cs_ptr + 8;
|
||||
cs->lock_count = -1;
|
||||
cs->recursion_count = 0;
|
||||
cs->owning_thread_id = 0;
|
||||
}
|
||||
|
||||
void RtlInitializeCriticalSection(pointer_t<X_RTL_CRITICAL_SECTION> cs) {
|
||||
xeRtlInitializeCriticalSection(cs, cs.guest_address());
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlInitializeCriticalSection, ExportTag::kImplemented);
|
||||
|
||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||
uint32_t cs_ptr,
|
||||
uint32_t spin_count) {
|
||||
// Spin count is rounded up to 256 intervals then packed in.
|
||||
// uint32_t spin_count_div_256 = (uint32_t)floor(spin_count / 256.0f + 0.5f);
|
||||
uint32_t spin_count_div_256 = (spin_count + 255) >> 8;
|
||||
if (spin_count_div_256 > 255) {
|
||||
spin_count_div_256 = 255;
|
||||
}
|
||||
|
||||
cs->unk_00 = 1;
|
||||
cs->spin_count_div_256 = spin_count_div_256;
|
||||
cs->queue_head = cs_ptr + 8;
|
||||
cs->queue_tail = cs_ptr + 8;
|
||||
cs->lock_count = -1;
|
||||
cs->recursion_count = 0;
|
||||
cs->owning_thread_id = 0;
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dword_result_t RtlInitializeCriticalSectionAndSpinCount(
|
||||
pointer_t<X_RTL_CRITICAL_SECTION> cs, dword_t spin_count) {
|
||||
return xeRtlInitializeCriticalSectionAndSpinCount(cs, cs.guest_address(),
|
||||
spin_count);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlInitializeCriticalSectionAndSpinCount,
|
||||
ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
// VOID
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
// XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
uint32_t thread_id = XThread::GetCurrentThreadId();
|
||||
|
||||
auto cs = reinterpret_cast<X_RTL_CRITICAL_SECTION*>(SHIM_MEM_ADDR(cs_ptr));
|
||||
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
||||
|
||||
spin:
|
||||
if (xe::atomic_inc(&cs->lock_count) != 0) {
|
||||
// If this thread already owns the CS increment the recursion count.
|
||||
if (cs->owning_thread_id == thread_id) {
|
||||
cs->recursion_count++;
|
||||
return;
|
||||
}
|
||||
xe::atomic_dec(&cs->lock_count);
|
||||
|
||||
// Thread was locked - spin wait.
|
||||
if (spin_wait_remaining) {
|
||||
spin_wait_remaining--;
|
||||
goto spin;
|
||||
}
|
||||
|
||||
// All out of spin waits, create a full waiter.
|
||||
// TODO(benvanik): contention - do a real wait!
|
||||
// XELOGE("RtlEnterCriticalSection tried to really lock!");
|
||||
spin_wait_remaining = 0; // HACK: spin forever
|
||||
xe::threading::MaybeYield();
|
||||
goto spin;
|
||||
}
|
||||
|
||||
// Now own the lock.
|
||||
cs->owning_thread_id = thread_id;
|
||||
cs->recursion_count = 1;
|
||||
}
|
||||
|
||||
SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
// DWORD
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
// XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
uint32_t thread_id = XThread::GetCurrentThreadId();
|
||||
|
||||
auto cs = reinterpret_cast<X_RTL_CRITICAL_SECTION*>(SHIM_MEM_ADDR(cs_ptr));
|
||||
|
||||
uint32_t result = 0;
|
||||
if (xe::atomic_cas(-1, 0, &cs->lock_count)) {
|
||||
// Able to steal the lock right away.
|
||||
cs->owning_thread_id = thread_id;
|
||||
cs->recursion_count = 1;
|
||||
result = 1;
|
||||
} else if (cs->owning_thread_id == thread_id) {
|
||||
xe::atomic_inc(&cs->lock_count);
|
||||
++cs->recursion_count;
|
||||
result = 1;
|
||||
}
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL RtlLeaveCriticalSection_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
// VOID
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
// XELOGD("RtlLeaveCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
// FYI: No need to check if the owning thread is calling this, as that should
|
||||
// be the only case.
|
||||
|
||||
auto cs = reinterpret_cast<X_RTL_CRITICAL_SECTION*>(SHIM_MEM_ADDR(cs_ptr));
|
||||
|
||||
// Drop recursion count - if we are still not zero'ed return.
|
||||
int32_t recursion_count = --cs->recursion_count;
|
||||
assert_true(recursion_count > -1);
|
||||
if (recursion_count) {
|
||||
assert_true(cs->recursion_count > 0);
|
||||
|
||||
xe::atomic_dec(&cs->lock_count);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not owned - unlock!
|
||||
cs->owning_thread_id = 0;
|
||||
if (xe::atomic_dec(&cs->lock_count) != -1) {
|
||||
// There were waiters - wake one of them.
|
||||
// TODO(benvanik): wake a waiter.
|
||||
XELOGE("RtlLeaveCriticalSection would have woken a waiter");
|
||||
}
|
||||
|
||||
XThread::GetCurrentThread()->CheckApcs();
|
||||
}
|
||||
|
||||
struct X_TIME_FIELDS {
|
||||
xe::be<uint16_t> year;
|
||||
xe::be<uint16_t> month;
|
||||
xe::be<uint16_t> day;
|
||||
xe::be<uint16_t> hour;
|
||||
xe::be<uint16_t> minute;
|
||||
xe::be<uint16_t> second;
|
||||
xe::be<uint16_t> milliseconds;
|
||||
xe::be<uint16_t> weekday;
|
||||
};
|
||||
static_assert(sizeof(X_TIME_FIELDS) == 16, "Must be LARGEINTEGER");
|
||||
|
||||
void RtlTimeToTimeFields(lpqword_t time_ptr,
|
||||
pointer_t<X_TIME_FIELDS> time_fields_ptr) {
|
||||
// TODO(benvanik): replace with our own version.
|
||||
FILETIME ft;
|
||||
ft.dwHighDateTime = static_cast<uint32_t>(time_ptr.value() >> 32);
|
||||
ft.dwLowDateTime = static_cast<uint32_t>(time_ptr.value());
|
||||
SYSTEMTIME st;
|
||||
FileTimeToSystemTime(&ft, &st);
|
||||
|
||||
time_fields_ptr->year = st.wYear;
|
||||
time_fields_ptr->month = st.wMonth;
|
||||
time_fields_ptr->day = st.wDay;
|
||||
time_fields_ptr->hour = st.wHour;
|
||||
time_fields_ptr->minute = st.wMinute;
|
||||
time_fields_ptr->second = st.wSecond;
|
||||
time_fields_ptr->milliseconds = st.wMilliseconds;
|
||||
time_fields_ptr->weekday = st.wDayOfWeek;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlTimeToTimeFields, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t RtlTimeFieldsToTime(pointer_t<X_TIME_FIELDS> time_fields_ptr,
|
||||
lpqword_t time_ptr) {
|
||||
// TODO(benvanik): replace with our own version.
|
||||
SYSTEMTIME st;
|
||||
st.wYear = time_fields_ptr->year;
|
||||
st.wMonth = time_fields_ptr->month;
|
||||
st.wDay = time_fields_ptr->day;
|
||||
st.wHour = time_fields_ptr->hour;
|
||||
st.wMinute = time_fields_ptr->minute;
|
||||
st.wSecond = time_fields_ptr->second;
|
||||
st.wMilliseconds = time_fields_ptr->milliseconds;
|
||||
st.wDayOfWeek = time_fields_ptr->weekday;
|
||||
FILETIME ft;
|
||||
if (!SystemTimeToFileTime(&st, &ft)) {
|
||||
// set last error = ERROR_INVALID_PARAMETER
|
||||
return 0;
|
||||
}
|
||||
uint64_t time = (uint64_t(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
*time_ptr = time;
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(RtlTimeFieldsToTime, ExportTag::kImplemented);
|
||||
|
||||
void RegisterRtlExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeStringToAnsiString, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlMultiByteToUnicodeN, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeToMultiByteN, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlEnterCriticalSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTryEnterCriticalSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlLeaveCriticalSection, state);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
31
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.h
Normal file
31
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_RTL_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_RTL_H_
|
||||
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
struct X_RTL_CRITICAL_SECTION;
|
||||
|
||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||
uint32_t cs_ptr);
|
||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||
uint32_t cs_ptr,
|
||||
uint32_t spin_count);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_RTL_H_
|
||||
1046
src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc
Normal file
1046
src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc
Normal file
File diff suppressed because it is too large
Load Diff
872
src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc
Normal file
872
src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc
Normal file
@@ -0,0 +1,872 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
// This is a partial file designed to be included by other files when
|
||||
// constructing various tables.
|
||||
|
||||
|
||||
XE_EXPORT(xboxkrnl, 0x00000001, DbgBreakPoint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000002, DbgBreakPointWithStatus, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000003, DbgPrint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000004, DbgPrompt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000005, DumpGetRawDumpInfo, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000006, DumpWriteDump, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000007, ExAcquireReadWriteLockExclusive, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000008, ExAcquireReadWriteLockShared, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000009, ExAllocatePool, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000A, ExAllocatePoolWithTag, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000B, ExAllocatePoolTypeWithTag, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000C, ExConsoleGameRegion, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000D, ExCreateThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000E, ExEventObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000F, ExFreePool, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000010, ExGetXConfigSetting, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000011, ExInitializeReadWriteLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000012, ExMutantObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000013, ExQueryPoolBlockSize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000014, ExRegisterThreadNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000015, ExRegisterTitleTerminateNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000016, ExReleaseReadWriteLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000017, ExSemaphoreObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000018, ExSetXConfigSetting, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000019, ExTerminateThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001A, ExTerminateTitleProcess, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001B, ExThreadObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001C, ExTimerObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001D, MmDoubleMapMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001E, MmUnmapMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001F, XeKeysGetConsoleCertificate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000020, FscGetCacheElementCount, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000021, FscSetCacheElementCount, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000022, HalGetCurrentAVPack, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000023, HalGpioControl, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000024, HalOpenCloseODDTray, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000025, HalReadWritePCISpace, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000026, HalRegisterPowerDownNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000027, HalRegisterSMCNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000028, HalReturnToFirmware, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000029, HalSendSMCMessage, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002A, HalSetAudioEnable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002B, InterlockedFlushSList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002C, InterlockedPopEntrySList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002D, InterlockedPushEntrySList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002E, IoAcquireDeviceObjectLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002F, IoAllocateIrp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000030, IoBuildAsynchronousFsdRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000031, IoBuildDeviceIoControlRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000032, IoBuildSynchronousFsdRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000033, IoCallDriver, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000034, IoCheckShareAccess, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000035, IoCompleteRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000036, IoCompletionObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000037, IoCreateDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000038, IoCreateFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000039, IoDeleteDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003A, IoDeviceObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003B, IoDismountVolume, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003C, IoDismountVolumeByFileHandle, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003D, IoDismountVolumeByName, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003E, IoFileObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003F, IoFreeIrp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000040, IoInitializeIrp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000041, IoInvalidDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000042, ExSetBetaFeaturesEnabled, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000043, IoQueueThreadIrp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000044, IoReleaseDeviceObjectLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000045, IoRemoveShareAccess, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000046, IoSetIoCompletion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000047, IoSetShareAccess, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000048, IoStartNextPacket, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000049, IoStartNextPacketByKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004A, IoStartPacket, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004B, IoSynchronousDeviceIoControlRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004C, IoSynchronousFsdRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004D, KeAcquireSpinLockAtRaisedIrql, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004E, KeAlertResumeThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004F, KeAlertThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000050, KeBlowFuses, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000051, KeBoostPriorityThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000052, KeBugCheck, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000053, KeBugCheckEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000054, KeCancelTimer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000055, KeConnectInterrupt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000056, KeContextFromKframes, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000057, KeContextToKframes, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000058, KeCreateUserMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000059, KeDebugMonitorData, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005A, KeDelayExecutionThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005B, KeDeleteUserMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005C, KeDisconnectInterrupt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005D, KeEnableFpuExceptions, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005E, KeEnablePPUPerformanceMonitor, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005F, KeEnterCriticalRegion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000060, KeEnterUserMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000061, KeFlushCacheRange, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000062, KeFlushCurrentEntireTb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000063, KeFlushEntireTb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000064, KeFlushUserModeCurrentTb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000065, KeFlushUserModeTb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000066, KeGetCurrentProcessType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000067, KeGetPMWRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000068, KeGetPRVRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000069, KeGetSocRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006A, KeGetSpecialPurposeRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006B, KeLockL2, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006C, KeUnlockL2, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006D, KeInitializeApc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006E, KeInitializeDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006F, KeInitializeDpc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000070, KeInitializeEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000071, KeInitializeInterrupt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000072, KeInitializeMutant, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000073, KeInitializeQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000074, KeInitializeSemaphore, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000075, KeInitializeTimerEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000076, KeInsertByKeyDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000077, KeInsertDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000078, KeInsertHeadQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000079, KeInsertQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007A, KeInsertQueueApc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007B, KeInsertQueueDpc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007C, KeIpiGenericCall, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007D, KeLeaveCriticalRegion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007E, KeLeaveUserMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007F, KePulseEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000080, KeQueryBackgroundProcessors, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000081, KeQueryBasePriorityThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000082, KeQueryInterruptTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000083, KeQueryPerformanceFrequency, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000084, KeQuerySystemTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000085, KeRaiseIrqlToDpcLevel, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000086, KeRegisterDriverNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000087, KeReleaseMutant, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000088, KeReleaseSemaphore, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000089, KeReleaseSpinLockFromRaisedIrql, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008A, KeRemoveByKeyDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008B, KeRemoveDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008C, KeRemoveEntryDeviceQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008D, KeRemoveQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008E, KeRemoveQueueDpc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008F, KeResetEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000090, KeRestoreFloatingPointState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000091, KeRestoreVectorUnitState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000092, KeResumeThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000093, KeRetireDpcList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000094, KeRundownQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000095, KeSaveFloatingPointState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000096, KeSaveVectorUnitState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000097, KeSetAffinityThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000098, KeSetBackgroundProcessors, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000099, KeSetBasePriorityThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009A, KeSetCurrentProcessType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009B, KeSetCurrentStackPointers, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009C, KeSetDisableBoostThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009D, KeSetEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009E, KeSetEventBoostPriority, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009F, KeSetPMWRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A0, KeSetPowerMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A1, KeSetPRVRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A2, KeSetPriorityClassThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A3, KeSetPriorityThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A4, KeSetSocRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A5, KeSetSpecialPurposeRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A6, KeSetTimer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A7, KeSetTimerEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A8, KeStallExecutionProcessor, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A9, KeSuspendThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AA, KeSweepDcacheRange, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AB, KeSweepIcacheRange, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AC, KeTestAlertThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AD, KeTimeStampBundle, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AE, KeTryToAcquireSpinLockAtRaisedIrql, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AF, KeWaitForMultipleObjects, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B0, KeWaitForSingleObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B1, KfAcquireSpinLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B2, KfRaiseIrql, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B3, KfLowerIrql, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B4, KfReleaseSpinLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B5, KiBugCheckData, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B6, LDICreateDecompression, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B7, LDIDecompress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B8, LDIDestroyDecompression, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B9, MmAllocatePhysicalMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BA, MmAllocatePhysicalMemoryEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BB, MmCreateKernelStack, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BC, MmDeleteKernelStack, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BD, MmFreePhysicalMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BE, MmGetPhysicalAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BF, MmIsAddressValid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C0, MmLockAndMapSegmentArray, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C1, MmLockUnlockBufferPages, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C2, MmMapIoSpace, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C3, MmPersistPhysicalMemoryAllocation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C4, MmQueryAddressProtect, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C5, MmQueryAllocationSize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C6, MmQueryStatistics, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C7, MmSetAddressProtect, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C8, MmSplitPhysicalMemoryAllocation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C9, MmUnlockAndUnmapSegmentArray, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CA, MmUnmapIoSpace, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CB, Nls844UnicodeCaseTable, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CC, NtAllocateVirtualMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CD, NtCancelTimer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CE, NtClearEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CF, NtClose, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D0, NtCreateDirectoryObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D1, NtCreateEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D2, NtCreateFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D3, NtCreateIoCompletion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D4, NtCreateMutant, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D5, NtCreateSemaphore, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D6, NtCreateSymbolicLinkObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D7, NtCreateTimer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D8, NtDeleteFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D9, NtDeviceIoControlFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DA, NtDuplicateObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DB, NtFlushBuffersFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DC, NtFreeVirtualMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DD, NtMakeTemporaryObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DE, NtOpenDirectoryObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DF, NtOpenFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E0, NtOpenSymbolicLinkObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E1, NtProtectVirtualMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E2, NtPulseEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E3, NtQueueApcThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E4, NtQueryDirectoryFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E5, NtQueryDirectoryObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E6, NtQueryEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E7, NtQueryFullAttributesFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E8, NtQueryInformationFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E9, NtQueryIoCompletion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EA, NtQueryMutant, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EB, NtQuerySemaphore, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EC, NtQuerySymbolicLinkObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000ED, NtQueryTimer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EE, NtQueryVirtualMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EF, NtQueryVolumeInformationFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F0, NtReadFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F1, NtReadFileScatter, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F2, NtReleaseMutant, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F3, NtReleaseSemaphore, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F4, NtRemoveIoCompletion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F5, NtResumeThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F6, NtSetEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F7, NtSetInformationFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F8, NtSetIoCompletion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F9, NtSetSystemTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FA, NtSetTimerEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FB, NtSignalAndWaitForSingleObjectEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FC, NtSuspendThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FD, NtWaitForSingleObjectEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FE, NtWaitForMultipleObjectsEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FF, NtWriteFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000100, NtWriteFileGather, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000101, NtYieldExecution, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000102, ObCreateObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000103, ObCreateSymbolicLink, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000104, ObDeleteSymbolicLink, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000105, ObDereferenceObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000106, ObDirectoryObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000107, ObGetWaitableObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000108, ObInsertObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000109, ObIsTitleObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010A, ObLookupAnyThreadByThreadId, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010B, ObLookupThreadByThreadId, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010C, ObMakeTemporaryObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010D, ObOpenObjectByName, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010E, ObOpenObjectByPointer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010F, ObReferenceObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000110, ObReferenceObjectByHandle, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000111, ObReferenceObjectByName, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000112, ObSymbolicLinkObjectType, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000113, ObTranslateSymbolicLink, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000114, RtlAnsiStringToUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000115, RtlAppendStringToString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000116, RtlAppendUnicodeStringToString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000117, RtlAppendUnicodeToString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000118, RtlAssert, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000119, RtlCaptureContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011A, RtlCompareMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011B, RtlCompareMemoryUlong, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011C, RtlCompareString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011D, RtlCompareStringN, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011E, RtlCompareUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011F, RtlCompareUnicodeStringN, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000120, RtlCompareUtf8ToUnicode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000121, RtlCopyString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000122, RtlCopyUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000123, RtlCreateUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000124, RtlDowncaseUnicodeChar, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000125, RtlEnterCriticalSection, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000126, RtlFillMemoryUlong, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000127, RtlFreeAnsiString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000128, RtlFreeUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000129, RtlGetCallersAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012A, RtlGetStackLimits, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012B, RtlImageXexHeaderField, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012C, RtlInitAnsiString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012D, RtlInitUnicodeString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012E, RtlInitializeCriticalSection, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012F, RtlInitializeCriticalSectionAndSpinCount, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000130, RtlLeaveCriticalSection, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000131, RtlLookupFunctionEntry, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000132, RtlLowerChar, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000133, RtlMultiByteToUnicodeN, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000134, RtlMultiByteToUnicodeSize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000135, RtlNtStatusToDosError, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000136, RtlRaiseException, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000137, RtlRaiseStatus, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000138, RtlRip, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000139, _scprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013A, _snprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013B, sprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013C, _scwprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013D, _snwprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013E, swprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013F, RtlTimeFieldsToTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000140, RtlTimeToTimeFields, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000141, RtlTryEnterCriticalSection, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000142, RtlUnicodeStringToAnsiString, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000143, RtlUnicodeToMultiByteN, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000144, RtlUnicodeToMultiByteSize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000145, RtlUnicodeToUtf8, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000146, RtlUnicodeToUtf8Size, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000147, RtlUnwind, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000148, RtlUnwind2, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000149, RtlUpcaseUnicodeChar, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014A, RtlUpperChar, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014B, RtlVirtualUnwind, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014C, _vscprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014D, _vsnprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014E, vsprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014F, _vscwprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000150, _vsnwprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000151, vswprintf, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000152, KeTlsAlloc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000153, KeTlsFree, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000154, KeTlsGetValue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000155, KeTlsSetValue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000156, XboxHardwareInfo, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000157, XboxKrnlBaseVersion, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000158, XboxKrnlVersion, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000159, XeCryptAesKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015A, XeCryptAesEcb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015B, XeCryptAesCbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015C, XeCryptBnDwLeDhEqualBase, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015D, XeCryptBnDwLeDhInvalBase, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015E, XeCryptBnDwLeDhModExp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015F, XeCryptBnDw_Copy, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000160, XeCryptBnDw_SwapLeBe, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000161, XeCryptBnDw_Zero, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000162, XeCryptBnDwLePkcs1Format, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000163, XeCryptBnDwLePkcs1Verify, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000164, XeCryptBnQwBeSigCreate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000165, XeCryptBnQwBeSigFormat, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000166, XeCryptBnQwBeSigVerify, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000167, XeCryptBnQwNeModExp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000168, XeCryptBnQwNeModExpRoot, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000169, XeCryptBnQwNeModInv, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016A, XeCryptBnQwNeModMul, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016B, XeCryptBnQwNeRsaKeyGen, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016C, XeCryptBnQwNeRsaPrvCrypt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016D, XeCryptBnQwNeRsaPubCrypt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016E, XeCryptBnQw_Copy, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016F, XeCryptBnQw_SwapDwQw, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000170, XeCryptBnQw_SwapDwQwLeBe, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000171, XeCryptBnQw_SwapLeBe, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000172, XeCryptBnQw_Zero, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000173, XeCryptChainAndSumMac, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000174, XeCryptDesParity, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000175, XeCryptDesKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000176, XeCryptDesEcb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000177, XeCryptDesCbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000178, XeCryptDes3Key, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000179, XeCryptDes3Ecb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017A, XeCryptDes3Cbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017B, XeCryptHmacMd5Init, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017C, XeCryptHmacMd5Update, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017D, XeCryptHmacMd5Final, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017E, XeCryptHmacMd5, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017F, XeCryptHmacShaInit, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000180, XeCryptHmacShaUpdate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000181, XeCryptHmacShaFinal, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000182, XeCryptHmacSha, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000183, XeCryptHmacShaVerify, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000184, XeCryptMd5Init, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000185, XeCryptMd5Update, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000186, XeCryptMd5Final, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000187, XeCryptMd5, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000188, XeCryptParveEcb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000189, XeCryptParveCbcMac, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018A, XeCryptRandom, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018B, XeCryptRc4Key, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018C, XeCryptRc4Ecb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018D, XeCryptRc4, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018E, XeCryptRotSumSha, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018F, XeCryptShaInit, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000190, XeCryptShaUpdate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000191, XeCryptShaFinal, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000192, XeCryptSha, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000193, XexExecutableModuleHandle, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000194, XexCheckExecutablePrivilege, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000195, XexGetModuleHandle, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000196, XexGetModuleSection, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000197, XexGetProcedureAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000198, XexLoadExecutable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000199, XexLoadImage, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019A, XexLoadImageFromMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019B, XexLoadImageHeaders, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019C, XexPcToFileHeader, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019D, KiApcNormalRoutineNop_, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019E, XexRegisterPatchDescriptor, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019F, XexSendDeferredNotifications, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A0, XexStartExecutable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A1, XexUnloadImage, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A2, XexUnloadImageAndExitThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A3, XexUnloadTitleModules, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A4, XexVerifyImageHeaders, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A5, __C_specific_handler, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A6, DbgLoadImageSymbols, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A7, DbgUnLoadImageSymbols, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A8, RtlImageDirectoryEntryToData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A9, RtlImageNtHeader, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AA, ExDebugMonitorService, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AB, MmDbgReadCheck, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AC, MmDbgReleaseAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AD, MmDbgWriteCheck, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AE, ExLoadedCommandLine, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AF, ExLoadedImageName, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B0, VdBlockUntilGUIIdle, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B1, VdCallGraphicsNotificationRoutines, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B2, VdDisplayFatalError, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B3, VdEnableClosedCaption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B4, VdEnableDisableClockGating, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B5, VdEnableDisablePowerSavingMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B6, VdEnableRingBufferRPtrWriteBack, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B7, VdGenerateGPUCSCCoefficients, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B8, VdGetClosedCaptionReadyStatus, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B9, VdGetCurrentDisplayGamma, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BA, VdGetCurrentDisplayInformation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BB, VdGetDisplayModeOverride, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BC, VdGetGraphicsAsicID, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BD, VdGetSystemCommandBuffer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BE, VdGlobalDevice, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BF, VdGlobalXamDevice, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C0, VdGpuClockInMHz, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C1, VdHSIOCalibrationLock, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C2, VdInitializeEngines, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C3, VdInitializeRingBuffer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C4, VdInitializeScaler, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C5, VdInitializeScalerCommandBuffer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C6, VdIsHSIOTrainingSucceeded, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C7, VdPersistDisplay, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C8, VdQuerySystemCommandBuffer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C9, VdQueryVideoFlags, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CA, VdQueryVideoMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CB, VdReadDVERegisterUlong, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CC, VdReadWriteHSIOCalibrationFlag, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CD, VdRegisterGraphicsNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CE, VdRegisterXamGraphicsNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CF, VdSendClosedCaptionData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D0, VdSetCGMSOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D1, VdSetColorProfileAdjustment, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D2, VdSetCscMatricesOverride, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D3, VdSetDisplayMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D4, VdSetDisplayModeOverride, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D5, VdSetGraphicsInterruptCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D6, VdSetHDCPOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D7, VdSetMacrovisionOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D8, VdSetSystemCommandBuffer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D9, VdSetSystemCommandBufferGpuIdentifierAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DA, VdSetWSSData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DB, VdSetWSSOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DC, VdShutdownEngines, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DD, VdTurnDisplayOff, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DE, VdTurnDisplayOn, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DF, KiApcNormalRoutineNop, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E0, VdWriteDVERegisterUlong, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E1, XVoicedHeadsetPresent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E2, XVoicedSubmitPacket, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E3, XVoicedClose, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E4, XVoicedActivate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E5, XInputdGetCapabilities, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E6, XInputdReadState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E7, XInputdWriteState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E8, XInputdNotify, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E9, XInputdRawState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EA, HidGetCapabilities, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EB, HidReadKeys, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EC, XInputdGetDeviceStats, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001ED, XInputdResetDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EE, XInputdSetRingOfLight, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EF, XInputdSetRFPowerMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F0, XInputdSetRadioFrequency, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F1, HidGetLastInputTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F2, XAudioRenderDriverInitialize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F3, XAudioRegisterRenderDriverClient, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F4, XAudioUnregisterRenderDriverClient, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F5, XAudioSubmitRenderDriverFrame, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F6, XAudioRenderDriverLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F7, XAudioGetVoiceCategoryVolumeChangeMask, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F8, XAudioGetVoiceCategoryVolume, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F9, XAudioSetVoiceCategoryVolume, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FA, XAudioBeginDigitalBypassMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FB, XAudioEndDigitalBypassMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FC, XAudioSubmitDigitalPacket, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FD, XAudioQueryDriverPerformance, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FE, XAudioGetRenderDriverThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FF, XAudioGetSpeakerConfig, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000200, XAudioSetSpeakerConfig, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000201, NicSetUnicastAddress, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000202, NicAttach, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000203, NicDetach, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000204, NicXmit, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000205, NicUpdateMcastMembership, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000206, NicFlushXmitQueue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000207, NicShutdown, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000208, NicGetLinkState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000209, NicGetStats, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020A, NicGetOpt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020B, NicSetOpt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020C, DrvSetSysReqCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020D, DrvSetUserBindingCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020E, DrvSetContentStorageCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020F, DrvSetAutobind, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000210, DrvGetContentStorageNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000211, MtpdBeginTransaction, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000212, MtpdCancelTransaction, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000213, MtpdEndTransaction, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000214, MtpdGetCurrentDevices, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000215, MtpdReadData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000216, MtpdReadEvent, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000217, MtpdResetDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000218, MtpdSendData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000219, MtpdVerifyProximity, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021A, XUsbcamSetCaptureMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021B, XUsbcamGetConfig, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021C, XUsbcamSetConfig, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021D, XUsbcamGetState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021E, XUsbcamReadFrame, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021F, XUsbcamSnapshot, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000220, XUsbcamSetView, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000221, XUsbcamGetView, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000222, XUsbcamCreate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000223, XUsbcamDestroy, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000224, XMACreateContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000225, XMAInitializeContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000226, XMAReleaseContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000227, XMAEnableContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000228, XMADisableContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000229, XMAGetOutputBufferWriteOffset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022A, XMASetOutputBufferReadOffset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022B, XMAGetOutputBufferReadOffset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022C, XMASetOutputBufferValid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022D, XMAIsOutputBufferValid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022E, XMASetInputBuffer0Valid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022F, XMAIsInputBuffer0Valid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000230, XMASetInputBuffer1Valid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000231, XMAIsInputBuffer1Valid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000232, XMASetInputBuffer0, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000233, XMASetInputBuffer1, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000234, XMAGetPacketMetadata, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000235, XMABlockWhileInUse, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000236, XMASetLoopData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000237, XMASetInputBufferReadOffset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000238, XMAGetInputBufferReadOffset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000239, ExIsBetaFeatureEnabled, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023A, XeKeysGetFactoryChallenge, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023B, XeKeysSetFactoryResponse, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023C, XeKeysInitializeFuses, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023D, XeKeysSaveBootLoader, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023E, XeKeysSaveKeyVault, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023F, XeKeysGetStatus, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000240, XeKeysGeneratePrivateKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000241, XeKeysGetKeyProperties, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000242, XeKeysSetKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000243, XeKeysGenerateRandomKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000244, XeKeysGetKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000245, XeKeysGetDigest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000246, XeKeysGetConsoleID, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000247, XeKeysGetConsoleType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000248, XeKeysQwNeRsaPrvCrypt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000249, XeKeysHmacSha, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024A, XInputdPassThroughRFCommand, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024B, XeKeysAesCbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024C, XeKeysDes2Cbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024D, XeKeysDesCbc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024E, XeKeysObscureKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024F, XeKeysHmacShaUsingKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000250, XeKeysSaveBootLoaderEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000251, XeKeysAesCbcUsingKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000252, XeKeysDes2CbcUsingKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000253, XeKeysDesCbcUsingKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000254, XeKeysObfuscate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000255, XeKeysUnObfuscate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000256, XeKeysConsolePrivateKeySign, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000257, XeKeysConsoleSignatureVerification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000258, XeKeysVerifyRSASignature, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000259, StfsCreateDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025A, StfsControlDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025B, VdSwap, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025C, HalFsbInterruptCount, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025D, XeKeysSaveSystemUpdate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025E, XeKeysLockSystemUpdate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025F, XeKeysExecute, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000260, XeKeysGetVersions, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000261, XInputdPowerDownDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000262, AniBlockOnAnimation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000263, AniTerminateAnimation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000264, XUsbcamReset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000265, AniSetLogo, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000266, KeCertMonitorData, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000267, HalIsExecutingPowerDownDpc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000268, VdInitializeEDRAM, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000269, VdRetrainEDRAM, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026A, VdRetrainEDRAMWorker, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026B, VdHSIOTrainCount, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026C, HalGetPowerUpCause, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026D, VdHSIOTrainingStatus, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026E, RgcBindInfo, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026F, VdReadEEDIDBlock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000270, VdEnumerateVideoModes, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000271, VdEnableHDCP, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000272, VdRegisterHDCPNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000273, HidReadMouseChanges, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000274, DumpSetCollectionFacility, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000275, XexTransformImageKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000276, XAudioOverrideSpeakerConfig, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000277, XInputdReadTextKeystroke, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000278, DrvXenonButtonPressed, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000279, DrvBindToUser, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027A, XexGetModuleImportVersions, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027B, RtlComputeCrc32, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027C, XeKeysSetRevocationList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027D, HalRegisterPowerDownCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027E, VdGetDisplayDiscoveryData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027F, XInputdSendStayAliveRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000280, XVoicedSendVPort, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000281, XVoicedGetBatteryStatus, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000282, XInputdFFGetDeviceInfo, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000283, XInputdFFSetEffect, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000284, XInputdFFUpdateEffect, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000285, XInputdFFEffectOperation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000286, XInputdFFDeviceControl, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000287, XInputdFFSetDeviceGain, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000288, XInputdFFCancelIo, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000289, XInputdFFSetRumble, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028A, NtAllocateEncryptedMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028B, NtFreeEncryptedMemory, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028C, XeKeysExSaveKeyVault, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028D, XeKeysExSetKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028E, XeKeysExGetKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028F, DrvSetDeviceConfigChangeCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000290, DrvDeviceConfigChange, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000291, HalRegisterHdDvdRomNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000292, XeKeysSecurityInitialize, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000293, XeKeysSecurityLoadSettings, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000294, XeKeysSecuritySaveSettings, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000295, XeKeysSecuritySetDetected, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000296, XeKeysSecurityGetDetected, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000297, XeKeysSecuritySetActivated, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000298, XeKeysSecurityGetActivated, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000299, XeKeysDvdAuthAP25InstallTable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029A, XeKeysDvdAuthAP25GetTableVersion, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029B, XeKeysGetProtectedFlag, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029C, XeKeysSetProtectedFlag, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029D, KeEnablePFMInterrupt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029E, KeDisablePFMInterrupt, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029F, KeSetProfilerISR, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A0, VdStartDisplayDiscovery, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A1, VdSetHDCPRevocationList, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A2, XeKeysGetUpdateSequence, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A3, XeKeysDvdAuthExActivate, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A4, KeGetImagePageTableEntry, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A5, HalRegisterBackgroundModeTransitionCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A6, AniStartBootAnimation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A7, HalClampUnclampOutputDACs, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A8, HalPowerDownToBackgroundMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A9, HalNotifyAddRemoveBackgroundTask, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AA, HalCallBackgroundModeNotificationRoutines, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AB, HalFsbResetCount, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AC, HalGetMemoryInformation, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AD, XInputdGetLastTextInputTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AE, VdEnableWMAProOverHDMI, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AF, XeKeysRevokeSaveSettings, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B0, XInputdSetTextMessengerIndicator, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B1, MicDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B2, XeKeysGetMediaID, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B3, XeKeysLoadKeyVault, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B4, KeGetVidInfo, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B5, HalNotifyBackgroundModeTransitionComplete, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B6, IoAcquireCancelSpinLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B7, IoReleaseCancelSpinLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B8, NtCancelIoFile, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B9, NtCancelIoFileEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BA, HalFinalizePowerLossRecovery, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BB, HalSetPowerLossRecovery, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BC, ExReadModifyWriteXConfigSettingUlong, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BD, HalRegisterXamPowerDownCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BE, ExCancelAlarm, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BF, ExInitializeAlarm, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C0, ExSetAlarm, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C1, XexActivationGetNonce, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C2, XexActivationSetLicense, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C3, IptvSetBoundaryKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C4, IptvSetSessionKey, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C5, IptvVerifyOmac1Signature, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C6, IptvGetAesCtrTransform, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C7, SataCdRomRecordReset, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C8, XInputdSetTextDeviceKeyLocks, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C9, XInputdGetTextDeviceKeyLocks, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CA, XexActivationVerifyOwnership, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CB, XexDisableVerboseDbgPrint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CC, SvodCreateDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CD, RtlCaptureStackBackTrace, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CE, XeKeysRevokeUpdateDynamic, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CF, XexImportTraceEnable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D0, ExRegisterXConfigNotification, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D1, XeKeysSecuritySetStat, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D2, VdQueryRealVideoMode, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D3, XexSetExecutablePrivilege, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D4, XAudioSuspendRenderDriverClients, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D5, IptvGetSessionKeyHash, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D6, VdSetCGMSState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D7, VdSetSCMSState, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D8, KeFlushMultipleTb, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D9, VdGetOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DA, VdSetOption, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DB, UsbdBootEnumerationDoneEvent, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DC, StfsDeviceErrorEvent, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DD, ExTryToAcquireReadWriteLockExclusive, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DE, ExTryToAcquireReadWriteLockShared, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DF, XexSetLastKdcTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E0, XInputdControl, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E1, RmcDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E2, LDIResetDecompression, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E3, NicRegisterDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E4, UsbdAddDeviceComplete, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E5, UsbdCancelAsyncTransfer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E6, UsbdGetDeviceSpeed, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E7, UsbdGetDeviceTopology, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E8, UsbdGetEndpointDescriptor, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E9, UsbdIsDeviceAuthenticated, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EA, UsbdOpenDefaultEndpoint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EB, UsbdOpenEndpoint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EC, UsbdQueueAsyncTransfer, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002ED, UsbdQueueCloseDefaultEndpoint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EE, UsbdQueueCloseEndpoint, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EF, UsbdRemoveDeviceComplete, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F0, KeRemoveQueueApc, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F1, UsbdDriverLoadRequiredEvent, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F2, UsbdGetRequiredDrivers, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F3, UsbdRegisterDriverObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F4, UsbdUnregisterDriverObject, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F5, UsbdCallAndBlockOnDpcRoutine, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F6, UsbdResetDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F7, UsbdGetDeviceDescriptor, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F8, NomnilGetExtension, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F9, NomnilStartCloseDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FA, WifiBeginAuthentication, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FB, WifiCheckCounterMeasures, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FC, WifiChooseAuthenCipherSetFromBSSID, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FD, WifiCompleteAuthentication, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FE, WifiGetAssociationIE, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FF, WifiOnMICError, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000300, WifiPrepareAuthenticationContext, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000301, WifiRecvEAPOLPacket, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000302, WifiDeduceNetworkType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000303, NicUnregisterDevice, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000304, DumpXitThread, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000305, XInputdSetWifiChannel, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000306, NomnilSetLed, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000307, WifiCalculateRegulatoryDomain, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000308, WifiSelectAdHocChannel, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000309, WifiChannelToFrequency, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030A, MmGetPoolPagesType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030B, ExExpansionInstall, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030C, ExExpansionCall, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030D, PsCamDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030E, McaDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030F, DetroitDeviceRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000310, XeCryptSha256Init, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000311, XeCryptSha256Update, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000312, XeCryptSha256Final, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000313, XeCryptSha256, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000314, XeCryptSha384Init, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000315, XeCryptSha384Update, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000316, XInputdGetDevicePid, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000317, HalGetNotedArgonErrors, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000318, XeCryptSha384Final, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000319, HalReadArgonEeprom, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031A, HalWriteArgonEeprom, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031B, XeKeysFcrtLoad, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031C, XeKeysFcrtSave, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031D, XeKeysFcrtSet, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031E, XeCryptSha384, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031F, XeCryptSha512Init, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000320, XAudioRegisterRenderDriverMECClient, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000321, XAudioUnregisterRenderDriverMECClient, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000322, XAudioCaptureRenderDriverFrame, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000323, XeCryptSha512Update, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000324, XeCryptSha512Final, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000325, XeCryptSha512, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000326, XeCryptBnQwNeCompare, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000327, XVoicedGetDirectionalData, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000328, DrvSetMicArrayStartCallback, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000329, DevAuthGetStatistics, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032A, NullCableRequest, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032B, XeKeysRevokeIsDeviceRevoked, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032C, DumpUpdateDumpSettings, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032D, EtxConsumerDisableEventType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032E, EtxConsumerEnableEventType, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032F, EtxConsumerProcessLogs, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000330, EtxConsumerRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000331, EtxConsumerUnregister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000332, EtxProducerLog, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000333, EtxProducerLogV, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000334, EtxProducerRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000335, EtxProducerUnregister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000336, EtxConsumerFlushBuffers, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000337, EtxProducerLogXwpp, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000338, EtxProducerLogXwppV, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000339, UsbdEnableDisableRootHubPort, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033A, EtxBufferRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033B, EtxBufferUnregister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033C, DumpRegisterDedicatedDataBlock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033D, XeKeysDvdAuthExSave, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033E, XeKeysDvdAuthExInstall, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033F, XexShimDisable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000340, XexShimEnable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000341, XexShimEntryDisable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000342, XexShimEntryEnable, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000343, XexShimEntryRegister, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000344, XexShimLock, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000345, XboxKrnlVersion4Digit, kVariable),
|
||||
XE_EXPORT(xboxkrnl, 0x00000346, XeKeysObfuscateEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000347, XeKeysUnObfuscateEx, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000348, XexTitleHash, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000349, XexTitleHashClose, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034A, XexTitleHashContinue, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034B, XexTitleHashOpen, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034C, XAudioGetRenderDriverTic, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034D, XAudioEnableDucker, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034E, XAudioSetDuckerLevel, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034F, XAudioIsDuckerEnabled, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000350, XAudioGetDuckerLevel, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000351, XAudioGetDuckerThreshold, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000352, XAudioSetDuckerThreshold, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000353, XAudioGetDuckerAttackTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000354, XAudioSetDuckerAttackTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000355, XAudioGetDuckerReleaseTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000356, XAudioSetDuckerReleaseTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000357, XAudioGetDuckerHoldTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000358, XAudioSetDuckerHoldTime, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x00000359, DevAuthShouldAlwaysEnforce, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000035A, XAudioGetUnderrunCount, kFunction),
|
||||
XE_EXPORT(xboxkrnl, 0x0000035C, XVoicedIsActiveProcess, kFunction),
|
||||
1465
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc
Normal file
1465
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc
Normal file
File diff suppressed because it is too large
Load Diff
32
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.h
Normal file
32
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_THREADING_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_THREADING_H_
|
||||
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
dword_result_t NtSetEvent(dword_t handle, lpdword_t previous_state_ptr);
|
||||
dword_result_t NtClearEvent(dword_t handle);
|
||||
|
||||
dword_result_t NtWaitForMultipleObjectsEx(
|
||||
dword_t count, pointer_t<xe::be<uint32_t>> handles, dword_t wait_type,
|
||||
dword_t wait_mode, dword_t alertable,
|
||||
pointer_t<xe::be<uint64_t>> timeout_ptr);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_THREADING_H_
|
||||
39
src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc
Normal file
39
src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
dword_result_t XUsbcamCreate(unknown_t unk1, // E
|
||||
unknown_t unk2, // 0x4B000
|
||||
lpunknown_t unk3_ptr) {
|
||||
// 0 = success.
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XUsbcamCreate, ExportTag::kStub);
|
||||
|
||||
dword_result_t XUsbcamGetState() {
|
||||
// 0 = not connected.
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(XUsbcamGetState, ExportTag::kStub);
|
||||
|
||||
void RegisterUsbcamExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
420
src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc
Normal file
420
src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc
Normal file
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/gpu/graphics_system.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_rtl.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_video.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
// http://www.tweakoz.com/orkid/
|
||||
// http://www.tweakoz.com/orkid/dox/d3/d52/xb360init_8cpp_source.html
|
||||
// https://github.com/Free60Project/xenosfb/
|
||||
// https://github.com/Free60Project/xenosfb/blob/master/src/xe.h
|
||||
// https://github.com/gligli/libxemit
|
||||
// http://web.archive.org/web/20090428095215/http://msdn.microsoft.com/en-us/library/bb313877.aspx
|
||||
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313961.aspx
|
||||
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313878.aspx
|
||||
// http://web.archive.org/web/20090510235238/http://msdn.microsoft.com/en-us/library/bb313942.aspx
|
||||
// http://svn.dd-wrt.com/browser/src/linux/universal/linux-3.8/drivers/gpu/drm/radeon/radeon_ring.c
|
||||
// http://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped
|
||||
// Down Direct3D: Xbox 360 Command Buffer and Resource Management"
|
||||
|
||||
void VdGetCurrentDisplayGamma(lpdword_t arg0_ptr, lpfloat_t arg1_ptr) {
|
||||
*arg0_ptr = 2;
|
||||
*arg1_ptr = 2.22222233f;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdGetCurrentDisplayGamma, ExportTag::kVideo);
|
||||
|
||||
struct X_D3DPRIVATE_RECT {
|
||||
xe::be<uint32_t> x1; // 0x0
|
||||
xe::be<uint32_t> y1; // 0x4
|
||||
xe::be<uint32_t> x2; // 0x8
|
||||
xe::be<uint32_t> y2; // 0xC
|
||||
};
|
||||
static_assert_size(X_D3DPRIVATE_RECT, 0x10);
|
||||
|
||||
struct X_D3DFILTER_PARAMETERS {
|
||||
xe::be<float> nyquist; // 0x0
|
||||
xe::be<float> flicker_filter; // 0x4
|
||||
xe::be<float> beta; // 0x8
|
||||
};
|
||||
static_assert_size(X_D3DFILTER_PARAMETERS, 0xC);
|
||||
|
||||
struct X_D3DPRIVATE_SCALER_PARAMETERS {
|
||||
X_D3DPRIVATE_RECT scaler_source_rect; // 0x0
|
||||
xe::be<uint32_t> scaled_output_width; // 0x10
|
||||
xe::be<uint32_t> scaled_output_height; // 0x14
|
||||
xe::be<uint32_t> vertical_filter_type; // 0x18
|
||||
X_D3DFILTER_PARAMETERS vertical_filter_parameters; // 0x1C
|
||||
xe::be<uint32_t> horizontal_filter_type; // 0x28
|
||||
X_D3DFILTER_PARAMETERS horizontal_filter_parameters; // 0x2C
|
||||
};
|
||||
static_assert_size(X_D3DPRIVATE_SCALER_PARAMETERS, 0x38);
|
||||
|
||||
struct X_DISPLAY_INFO {
|
||||
xe::be<uint16_t> front_buffer_width; // 0x0
|
||||
xe::be<uint16_t> front_buffer_height; // 0x2
|
||||
xe::be<uint8_t> front_buffer_color_format; // 0x4
|
||||
xe::be<uint8_t> front_buffer_pixel_format; // 0x5
|
||||
X_D3DPRIVATE_SCALER_PARAMETERS scaler_parameters; // 0x6
|
||||
xe::be<uint16_t> display_window_overscan_left; // 0x40
|
||||
xe::be<uint16_t> display_window_overscan_top; // 0x42
|
||||
xe::be<uint16_t> display_window_overscan_right; // 0x44
|
||||
xe::be<uint16_t> display_window_overscan_bottom; // 0x46
|
||||
xe::be<uint16_t> display_width; // 0x48
|
||||
xe::be<uint16_t> display_height; // 0x4A
|
||||
xe::be<float> display_refresh_rate; // 0x4C
|
||||
xe::be<uint32_t> display_interlaced; // 0x50
|
||||
xe::be<uint8_t> display_color_format; // 0x54
|
||||
xe::be<uint16_t> actual_display_width; // 0x56
|
||||
};
|
||||
static_assert_size(X_DISPLAY_INFO, 0x58);
|
||||
|
||||
void VdQueryVideoMode(pointer_t<X_VIDEO_MODE> video_mode);
|
||||
|
||||
void VdGetCurrentDisplayInformation(pointer_t<X_DISPLAY_INFO> display_info) {
|
||||
X_VIDEO_MODE mode;
|
||||
VdQueryVideoMode(&mode);
|
||||
|
||||
display_info.Zero();
|
||||
display_info->front_buffer_width = (uint16_t)mode.display_width;
|
||||
display_info->front_buffer_height = (uint16_t)mode.display_height;
|
||||
|
||||
display_info->scaler_parameters.scaler_source_rect.x2 = mode.display_width;
|
||||
display_info->scaler_parameters.scaler_source_rect.y2 = mode.display_height;
|
||||
display_info->scaler_parameters.scaled_output_width = mode.display_width;
|
||||
display_info->scaler_parameters.scaled_output_height = mode.display_height;
|
||||
display_info->scaler_parameters.horizontal_filter_type = 1;
|
||||
display_info->scaler_parameters.vertical_filter_type = 1;
|
||||
|
||||
display_info->display_window_overscan_left = 320;
|
||||
display_info->display_window_overscan_top = 180;
|
||||
display_info->display_window_overscan_right = 320;
|
||||
display_info->display_window_overscan_bottom = 180;
|
||||
display_info->display_width = (uint16_t)mode.display_width;
|
||||
display_info->display_height = (uint16_t)mode.display_height;
|
||||
display_info->display_refresh_rate = mode.refresh_rate;
|
||||
display_info->actual_display_width = (uint16_t)mode.display_width;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdGetCurrentDisplayInformation, ExportTag::kVideo);
|
||||
|
||||
void VdQueryVideoMode(pointer_t<X_VIDEO_MODE> video_mode) {
|
||||
// TODO(benvanik): get info from actual display.
|
||||
video_mode.Zero();
|
||||
video_mode->display_width = 1280;
|
||||
video_mode->display_height = 720;
|
||||
video_mode->is_interlaced = 0;
|
||||
video_mode->is_widescreen = 1;
|
||||
video_mode->is_hi_def = 1;
|
||||
video_mode->refresh_rate = 60.0f;
|
||||
video_mode->video_standard = 1; // NTSC
|
||||
video_mode->unknown_0x8a = 0x4A;
|
||||
video_mode->unknown_0x01 = 0x01;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdQueryVideoMode, ExportTag::kVideo);
|
||||
|
||||
dword_result_t VdQueryVideoFlags() {
|
||||
X_VIDEO_MODE mode;
|
||||
VdQueryVideoMode(&mode);
|
||||
|
||||
uint32_t flags = 0;
|
||||
flags |= mode.is_widescreen ? 1 : 0;
|
||||
flags |= mode.display_width >= 1024 ? 2 : 0;
|
||||
flags |= mode.display_width >= 1920 ? 4 : 0;
|
||||
|
||||
return flags;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdQueryVideoFlags, ExportTag::kVideo);
|
||||
|
||||
dword_result_t VdSetDisplayMode(dword_t mode) {
|
||||
// Often 0x40000000.
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdSetDisplayMode, ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
dword_result_t VdSetDisplayModeOverride(unknown_t unk0, unknown_t unk1,
|
||||
double_t refresh_rate, unknown_t unk3,
|
||||
unknown_t unk4) {
|
||||
// refresh_rate = 0, 50, 59.9, etc.
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdSetDisplayModeOverride,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
dword_result_t VdInitializeEngines(unknown_t unk0, function_t callback,
|
||||
unknown_t unk1, lpunknown_t unk2_ptr,
|
||||
lpunknown_t unk3_ptr) {
|
||||
// r3 = 0x4F810000
|
||||
// r4 = function ptr (cleanup callback?)
|
||||
// r5 = 0
|
||||
// r6/r7 = some binary data in .data
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdInitializeEngines,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
void VdShutdownEngines() {
|
||||
// Ignored for now.
|
||||
// Games seem to call an Initialize/Shutdown pair to query info, then
|
||||
// re-initialize.
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdShutdownEngines,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
dword_result_t VdGetGraphicsAsicID() {
|
||||
// Games compare for < 0x10 and do VdInitializeEDRAM, else other
|
||||
// (retrain/etc).
|
||||
return 0x11;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdGetGraphicsAsicID, ExportTag::kVideo);
|
||||
|
||||
dword_result_t VdEnableDisableClockGating(dword_t enabled) {
|
||||
// Ignored, as it really doesn't matter.
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdEnableDisableClockGating, ExportTag::kVideo);
|
||||
|
||||
void VdSetGraphicsInterruptCallback(function_t callback, lpvoid_t user_data) {
|
||||
// callback takes 2 params
|
||||
// r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble
|
||||
// r4 = user_data (r4 of VdSetGraphicsInterruptCallback)
|
||||
auto graphics_system = kernel_state()->emulator()->graphics_system();
|
||||
graphics_system->SetInterruptCallback(callback, user_data);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdSetGraphicsInterruptCallback, ExportTag::kVideo);
|
||||
|
||||
void VdInitializeRingBuffer(lpvoid_t ptr, int_t page_count) {
|
||||
// r3 = result of MmGetPhysicalAddress
|
||||
// r4 = number of pages? page size?
|
||||
// 0x8000 -> cntlzw=16 -> 0x1C - 16 = 12
|
||||
// Buffer pointers are from MmAllocatePhysicalMemory with WRITE_COMBINE.
|
||||
// Sizes could be zero? XBLA games seem to do this. Default sizes?
|
||||
// D3D does size / region_count - must be > 1024
|
||||
auto graphics_system = kernel_state()->emulator()->graphics_system();
|
||||
graphics_system->InitializeRingBuffer(ptr, page_count);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdInitializeRingBuffer, ExportTag::kVideo);
|
||||
|
||||
void VdEnableRingBufferRPtrWriteBack(lpvoid_t ptr, int_t block_size) {
|
||||
// r4 = 6, usually --- <=19
|
||||
auto graphics_system = kernel_state()->emulator()->graphics_system();
|
||||
graphics_system->EnableReadPointerWriteBack(ptr, block_size);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdEnableRingBufferRPtrWriteBack, ExportTag::kVideo);
|
||||
|
||||
void VdGetSystemCommandBuffer(lpunknown_t p0_ptr, lpunknown_t p1_ptr) {
|
||||
p0_ptr.Zero(0x94);
|
||||
xe::store_and_swap<uint32_t>(p0_ptr, 0xBEEF0000);
|
||||
xe::store_and_swap<uint32_t>(p1_ptr, 0xBEEF0001);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdGetSystemCommandBuffer,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
void VdSetSystemCommandBufferGpuIdentifierAddress(lpunknown_t unk) {
|
||||
// r3 = 0x2B10(d3d?) + 8
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdSetSystemCommandBufferGpuIdentifierAddress,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
// VdVerifyMEInitCommand
|
||||
// r3
|
||||
// r4 = 19
|
||||
// no op?
|
||||
|
||||
dword_result_t VdInitializeScalerCommandBuffer(
|
||||
unknown_t unk0, // 0?
|
||||
unknown_t unk1, // 0x050002d0 size of ?
|
||||
unknown_t unk2, // 0?
|
||||
unknown_t unk3, // 0x050002d0 size of ?
|
||||
unknown_t unk4, // 0x050002d0 size of ?
|
||||
unknown_t unk5, // 7?
|
||||
lpunknown_t unk6, // 0x2004909c <-- points to zeros?
|
||||
unknown_t unk7, // 7?
|
||||
lpvoid_t dest_ptr // Points to the first 80000000h where the memcpy
|
||||
// sources from.
|
||||
) {
|
||||
// We could fake the commands here, but I'm not sure the game checks for
|
||||
// anything but success (non-zero ret).
|
||||
// For now, we just fill it with NOPs.
|
||||
uint32_t total_words = 0x1CC / 4;
|
||||
auto dest = dest_ptr.as_array<uint32_t>();
|
||||
for (size_t i = 0; i < total_words; ++i) {
|
||||
dest[i] = 0x80000000;
|
||||
}
|
||||
|
||||
// returns memcpy size >> 2 for memcpy(...,...,ret << 2)
|
||||
return total_words >> 2;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdInitializeScalerCommandBuffer,
|
||||
ExportTag::kVideo | ExportTag::kSketchy);
|
||||
|
||||
// We use these to shuffle data to VdSwap.
|
||||
// This way it gets properly stored in the command buffer (for replay/etc).
|
||||
uint32_t last_frontbuffer_width_ = 1280;
|
||||
uint32_t last_frontbuffer_height_ = 720;
|
||||
|
||||
struct BufferScaling {
|
||||
xe::be<uint16_t> fb_width;
|
||||
xe::be<uint16_t> fb_height;
|
||||
xe::be<uint16_t> bb_width;
|
||||
xe::be<uint16_t> bb_height;
|
||||
};
|
||||
void AppendParam(StringBuffer* string_buffer, pointer_t<BufferScaling> param) {
|
||||
string_buffer->AppendFormat(
|
||||
"%.8X(scale %dx%d -> %dx%d))", param.guest_address(),
|
||||
uint16_t(param->bb_width), uint16_t(param->bb_height),
|
||||
uint16_t(param->fb_width), uint16_t(param->fb_height));
|
||||
}
|
||||
|
||||
dword_result_t VdCallGraphicsNotificationRoutines(
|
||||
unknown_t unk0, pointer_t<BufferScaling> args_ptr) {
|
||||
assert_true(unk0 == 1);
|
||||
|
||||
// TODO(benvanik): what does this mean, I forget:
|
||||
// callbacks get 0, r3, r4
|
||||
|
||||
// For use by VdSwap.
|
||||
last_frontbuffer_width_ = args_ptr->fb_width;
|
||||
last_frontbuffer_height_ = args_ptr->fb_height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdCallGraphicsNotificationRoutines,
|
||||
ExportTag::kVideo | ExportTag::kSketchy);
|
||||
|
||||
dword_result_t VdIsHSIOTrainingSucceeded() {
|
||||
// Not really sure what this should be - code does weird stuff here:
|
||||
// (cntlzw r11, r3 / extrwi r11, r11, 1, 26)
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdIsHSIOTrainingSucceeded,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
dword_result_t VdPersistDisplay(unknown_t unk0, lpdword_t unk1_ptr) {
|
||||
// unk1_ptr needs to be populated with a pointer passed to
|
||||
// MmFreePhysicalMemory(1, *unk1_ptr).
|
||||
if (unk1_ptr) {
|
||||
auto heap = kernel_memory()->LookupHeapByType(true, 16 * 1024);
|
||||
uint32_t unk1_value;
|
||||
heap->Alloc(64, 32, kMemoryAllocationReserve | kMemoryAllocationCommit,
|
||||
kMemoryProtectNoAccess, false, &unk1_value);
|
||||
*unk1_ptr = unk1_value;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdPersistDisplay,
|
||||
ExportTag::kVideo | ExportTag::kSketchy);
|
||||
|
||||
dword_result_t VdRetrainEDRAMWorker(unknown_t unk0) { return 0; }
|
||||
DECLARE_XBOXKRNL_EXPORT(VdRetrainEDRAMWorker,
|
||||
ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
dword_result_t VdRetrainEDRAM(unknown_t unk0, unknown_t unk1, unknown_t unk2,
|
||||
unknown_t unk3, unknown_t unk4, unknown_t unk5) {
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdRetrainEDRAM, ExportTag::kVideo | ExportTag::kStub);
|
||||
|
||||
void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
|
||||
lpvoid_t fetch_ptr, // frontbuffer texture fetch
|
||||
unknown_t unk2, //
|
||||
lpunknown_t unk3, // buffer from VdGetSystemCommandBuffer
|
||||
lpunknown_t unk4, // from VdGetSystemCommandBuffer (0xBEEF0001)
|
||||
lpdword_t frontbuffer_ptr, // ptr to frontbuffer address
|
||||
lpdword_t color_format_ptr, lpdword_t color_space_ptr,
|
||||
lpunknown_t unk8, unknown_t unk9) {
|
||||
gpu::xenos::xe_gpu_texture_fetch_t fetch;
|
||||
xe::copy_and_swap_32_unaligned(
|
||||
reinterpret_cast<uint32_t*>(&fetch),
|
||||
reinterpret_cast<uint32_t*>(fetch_ptr.host_address()), 6);
|
||||
|
||||
auto color_format = gpu::xenos::ColorFormat(color_format_ptr.value());
|
||||
auto color_space = *color_space_ptr;
|
||||
assert_true(color_format == gpu::xenos::ColorFormat::k_8_8_8_8 ||
|
||||
color_format == gpu::xenos::ColorFormat::kUnknown0x36);
|
||||
assert_true(color_space == 0);
|
||||
assert_true(*frontbuffer_ptr == fetch.address << 12);
|
||||
assert_true(last_frontbuffer_width_ == 1 + fetch.size_2d.width);
|
||||
assert_true(last_frontbuffer_height_ == 1 + fetch.size_2d.height);
|
||||
|
||||
// The caller seems to reserve 64 words (256b) in the primary ringbuffer
|
||||
// for this method to do what it needs. We just zero them out and send a
|
||||
// token value. It'd be nice to figure out what this is really doing so
|
||||
// that we could simulate it, though due to TCR I bet all games need to
|
||||
// use this method.
|
||||
buffer_ptr.Zero(64 * 4);
|
||||
|
||||
namespace xenos = xe::gpu::xenos;
|
||||
|
||||
auto dwords = buffer_ptr.as_array<uint32_t>();
|
||||
dwords[0] = xenos::MakePacketType3<xenos::PM4_XE_SWAP, 63>();
|
||||
dwords[1] = 'SWAP';
|
||||
dwords[2] = *frontbuffer_ptr;
|
||||
|
||||
// Set by VdCallGraphicsNotificationRoutines.
|
||||
dwords[3] = last_frontbuffer_width_;
|
||||
dwords[4] = last_frontbuffer_height_;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(VdSwap, ExportTag::kVideo | ExportTag::kImportant);
|
||||
|
||||
void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver,
|
||||
KernelState* kernel_state) {
|
||||
auto memory = kernel_state->memory();
|
||||
|
||||
// VdGlobalDevice (4b)
|
||||
// Pointer to a global D3D device. Games only seem to set this, so we don't
|
||||
// have to do anything. We may want to read it back later, though.
|
||||
uint32_t pVdGlobalDevice =
|
||||
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
|
||||
export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGlobalDevice,
|
||||
pVdGlobalDevice);
|
||||
xe::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGlobalDevice), 0);
|
||||
|
||||
// VdGlobalXamDevice (4b)
|
||||
// Pointer to the XAM D3D device, which we don't have.
|
||||
uint32_t pVdGlobalXamDevice =
|
||||
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdGlobalXamDevice, pVdGlobalXamDevice);
|
||||
xe::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGlobalXamDevice), 0);
|
||||
|
||||
// VdGpuClockInMHz (4b)
|
||||
// GPU clock. Xenos is 500MHz. Hope nothing is relying on this timing...
|
||||
uint32_t pVdGpuClockInMHz =
|
||||
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
|
||||
export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGpuClockInMHz,
|
||||
pVdGpuClockInMHz);
|
||||
xe::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGpuClockInMHz), 500);
|
||||
|
||||
// VdHSIOCalibrationLock (28b)
|
||||
// CriticalSection.
|
||||
uint32_t pVdHSIOCalibrationLock =
|
||||
memory->SystemHeapAlloc(28, 32, kSystemHeapPhysical);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock);
|
||||
auto hsio_lock =
|
||||
memory->TranslateVirtual<X_RTL_CRITICAL_SECTION*>(pVdHSIOCalibrationLock);
|
||||
xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock,
|
||||
10000);
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
26
src/xenia/kernel/xboxkrnl/xboxkrnl_video.h
Normal file
26
src/xenia/kernel/xboxkrnl/xboxkrnl_video.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_VIDEO_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_VIDEO_H_
|
||||
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
void VdQueryVideoMode(pointer_t<X_VIDEO_MODE> video_mode);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_VIDEO_H_
|
||||
Reference in New Issue
Block a user