diff --git a/include/xenia/byte_order.h b/include/xenia/byte_order.h index bd50ce4ef..e0cdfdca4 100644 --- a/include/xenia/byte_order.h +++ b/include/xenia/byte_order.h @@ -64,5 +64,14 @@ #define XEGETINT64LE(p) ( (int64_t)XESWAP64LE(*(uint64_t*)(p))) #define XEGETUINT64LE(p) ((uint64_t)XESWAP64LE(*(uint64_t*)(p))) +#define XESETINT8BE(p, v) (*( (int8_t*)(p)) = (int8_t)v) +#define XESETUINT8BE(p, v) (*( (uint8_t*)(p)) = (uint8_t)v) +#define XESETINT16BE(p, v) (*( (int16_t*)(p)) = XESWAP16BE( (int16_t)v)) +#define XESETUINT16BE(p, v) (*((uint16_t*)(p)) = XESWAP16BE((uint16_t)v)) +#define XESETINT32BE(p, v) (*( (int32_t*)(p)) = XESWAP32BE( (int32_t)v)) +#define XESETUINT32BE(p, v) (*((uint32_t*)(p)) = XESWAP32BE((uint32_t)v)) +#define XESETINT64BE(p, v) (*( (int64_t*)(p)) = XESWAP64BE( (int64_t)v)) +#define XESETUINT64BE(p, v) (*((uint64_t*)(p)) = XESWAP64BE((uint64_t)v)) + #endif // XENIA_BYTE_ORDER_H_ diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc b/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc index 036934021..e15858e50 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc @@ -67,6 +67,8 @@ XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory, // TODO(benvanik): alloc heap memory somewhere in user space // TODO(benvanik): tools for reading/writing to heap memory + uint8_t* mem = xe_memory_addr(memory, 0); + // HACK: register some dummy globals for now. // KeDebugMonitorData resolver->SetVariableMapping( @@ -76,12 +78,21 @@ XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory, resolver->SetVariableMapping( "xboxkrnl.exe", 0x00000156, 0x40002000); + // 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 resolver->SetVariableMapping( "xboxkrnl.exe", 0x00000193, - 0x40000000); - - // 0x0000012B, RtlImageXexHeaderField + 0x80100FFC); + XESETUINT32BE(mem + 0x80100FFC, 0x80101000); + XESETUINT32BE(mem + 0x80101058, 0x80101100); } XboxkrnlModule::~XboxkrnlModule() { diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc b/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc index 2440657ff..a2235b4de 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc @@ -9,6 +9,8 @@ #include "kernel/modules/xboxkrnl/xboxkrnl_rtl.h" +#include + #include "kernel/shim_utils.h" #include "kernel/modules/xboxkrnl/xboxkrnl.h" @@ -21,6 +23,50 @@ using namespace xe::kernel::xboxkrnl; namespace { +void RtlImageXexHeaderField_shim( + xe_ppc_state_t* ppc_state, KernelState* state) { + // PVOID + // PVOID XexHeaderBase + // DWORD ImageField + + uint32_t xex_header_base = SHIM_GET_ARG_32(0); + uint32_t image_field = SHIM_GET_ARG_32(1); + + // NOTE: this is totally faked! + // We set the XexExecutableModuleHandle pointer to a block that has at offset + // 0x58 a pointer to our XexHeaderBase. If the value passed doesn't match + // then die. + // The only ImageField I've seen in the wild is + // 0x20401 (XEX_HEADER_DEFAULT_HEAP_SIZE), so that's all we'll support. + + XELOGD( + XT("RtlImageXexHeaderField(%.8X, %.8X)"), + xex_header_base, image_field); + + if (xex_header_base != 0x80101100) { + XELOGE(XT("RtlImageXexHeaderField with non-magic base NOT IMPLEMENTED")); + SHIM_SET_RETURN(0); + return; + } + + uint32_t return_value = 0; + switch (image_field) { + case XEX_HEADER_DEFAULT_HEAP_SIZE: + // TODO(benvanik): pull from running module + // This is header->exe_heap_size. + return_value = 0; + break; + default: + XELOGE(XT("RtlImageXexHeaderField header field %.8X NOT IMPLEMENTED"), + image_field); + SHIM_SET_RETURN(0); + return; + } + + SHIM_SET_RETURN(return_value); +} + + } @@ -30,5 +76,7 @@ void xe::kernel::xboxkrnl::RegisterRtlExports( export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \ state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl) + SHIM_SET_MAPPING(0x0000012B, RtlImageXexHeaderField_shim, NULL); + #undef SET_MAPPING }