diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc index 23c258aad..0c110fae9 100644 --- a/src/xenia/kernel/objects/xuser_module.cc +++ b/src/xenia/kernel/objects/xuser_module.cc @@ -20,9 +20,14 @@ namespace kernel { using namespace xe::cpu; XUserModule::XUserModule(KernelState* kernel_state, const char* path) - : XModule(kernel_state, path), xex_(nullptr) {} + : XModule(kernel_state, path), xex_(nullptr), execution_info_ptr_(0) {} -XUserModule::~XUserModule() { xe_xex2_dealloc(xex_); } +XUserModule::~XUserModule() { + if (execution_info_ptr_) { + kernel_state()->memory()->HeapFree(execution_info_ptr_, 0); + } + xe_xex2_dealloc(xex_); +} xe_xex2_ref XUserModule::xex() { return xex_; } @@ -109,6 +114,22 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) { return X_STATUS_UNSUCCESSFUL; } + // Store execution info for later use. + // TODO(benvanik): just put entire xex header in memory somewhere? + execution_info_ptr_ = + uint32_t(kernel_state()->memory()->HeapAlloc(0, 24, MEMORY_FLAG_ZERO, 0)); + auto eip = kernel_state()->memory()->membase() + execution_info_ptr_; + const auto& ex = xe_xex2_get_header(xex_)->execution_info; + poly::store_and_swap(eip + 0x00, ex.media_id); + poly::store_and_swap(eip + 0x04, ex.version.value); + poly::store_and_swap(eip + 0x08, ex.base_version.value); + poly::store_and_swap(eip + 0x0C, ex.title_id); + poly::store_and_swap(eip + 0x10, ex.platform); + poly::store_and_swap(eip + 0x11, ex.executable_table); + poly::store_and_swap(eip + 0x12, ex.disc_number); + poly::store_and_swap(eip + 0x13, ex.disc_count); + poly::store_and_swap(eip + 0x14, ex.savegame_id); + // Prepare the module for execution. // Runtime takes ownership. auto xex_module = std::make_unique(runtime); diff --git a/src/xenia/kernel/objects/xuser_module.h b/src/xenia/kernel/objects/xuser_module.h index 4ef694e73..201d7b49f 100644 --- a/src/xenia/kernel/objects/xuser_module.h +++ b/src/xenia/kernel/objects/xuser_module.h @@ -27,6 +27,8 @@ class XUserModule : public XModule { xe_xex2_ref xex(); const xe_xex2_header_t* xex_header(); + uint32_t execution_info_ptr() const { return execution_info_ptr_; } + X_STATUS LoadFromFile(const char* path); X_STATUS LoadFromMemory(const void* addr, const size_t length); @@ -42,6 +44,7 @@ class XUserModule : public XModule { int LoadPE(); xe_xex2_ref xex_; + uint32_t execution_info_ptr_; }; } // namespace kernel diff --git a/src/xenia/kernel/xam_info.cc b/src/xenia/kernel/xam_info.cc index 09d8ac5db..1208d4de1 100644 --- a/src/xenia/kernel/xam_info.cc +++ b/src/xenia/kernel/xam_info.cc @@ -10,6 +10,7 @@ #include "xenia/common.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/objects/xenumerator.h" +#include "xenia/kernel/objects/xuser_module.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/xex2.h" #include "xenia/kernel/xam_private.h" @@ -68,6 +69,21 @@ SHIM_CALL XamVoiceIsActiveProcess_shim(PPCContext* ppc_state, SHIM_SET_RETURN_32(0); } +SHIM_CALL XamGetExecutionId_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t info_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XamGetExecutionId(%.8X)", info_ptr); + + auto module = state->GetExecutableModule(); + assert_not_null(module); + + SHIM_SET_MEM_32(info_ptr, module->execution_info_ptr()); + + module->Release(); + + SHIM_SET_RETURN_32(0); +} + SHIM_CALL XamLoaderGetLaunchDataSize_shim(PPCContext* ppc_state, KernelState* state) { uint32_t size_ptr = SHIM_GET_ARG_32(0); @@ -176,6 +192,7 @@ void xe::kernel::xam::RegisterInfoExports(ExportResolver* export_resolver, SHIM_SET_MAPPING("xam.xex", XamVoiceIsActiveProcess, state); + SHIM_SET_MAPPING("xam.xex", XamGetExecutionId, state); SHIM_SET_MAPPING("xam.xex", XamLoaderGetLaunchDataSize, state); SHIM_SET_MAPPING("xam.xex", XamLoaderGetLaunchData, state); SHIM_SET_MAPPING("xam.xex", XamLoaderLaunchTitle, state);