Shuffling kernel/.

This commit is contained in:
Ben Vanik
2015-09-06 18:07:52 -07:00
parent 494cba7131
commit e5fbf840d2
118 changed files with 749 additions and 620 deletions

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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_

View 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

View 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

View 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, &region_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

View 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

View 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

View 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_

View 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, &section_data, &section_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

View 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

View 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_

View 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_

View 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

View 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_

File diff suppressed because it is too large Load Diff

View 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),

File diff suppressed because it is too large Load Diff

View 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_

View 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

View 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

View 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_