diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 3a56e8a88..019b890d5 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -68,6 +68,7 @@ KernelState::KernelState(Emulator* emulator) shared_kernel_state_ = this; process_info_block_address_ = memory_->SystemHeapAlloc(0x60); + auto pib = memory_->TranslateVirtual(process_info_block_address_); // TODO(benvanik): figure out what this list is. @@ -188,6 +189,17 @@ void KernelState::SetExecutableModule(object_ref module) { pib->tls_raw_data_size = header->tls_info.raw_data_size; pib->tls_slot_size = header->tls_info.slot_count * 4; } + + // Setup the kernel's XexExecutableModuleHandle field + auto exp = processor()->export_resolver()->GetExportByOrdinal( + "xboxkrnl.exe", ordinals::XexExecutableModuleHandle); + + if (exp) { + auto variable_ptr = + memory()->TranslateVirtual*>(exp->variable_ptr); + + *variable_ptr = module->hmodule_ptr(); + } } void KernelState::LoadKernelModule(object_ref kernel_module) { diff --git a/src/xenia/kernel/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl_module.cc index 047f3da32..016da3eb9 100644 --- a/src/xenia/kernel/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl_module.cc @@ -89,17 +89,9 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // 0x80101058 <- pointer to xex header // 0x80101100 <- xex header base uint32_t ppXexExecutableModuleHandle = memory_->SystemHeapAlloc(4); - auto lppXexExecutableModuleHandle = - memory_->TranslateVirtual(ppXexExecutableModuleHandle); export_resolver_->SetVariableMapping("xboxkrnl.exe", ordinals::XexExecutableModuleHandle, ppXexExecutableModuleHandle); - uint32_t pXexExecutableModuleHandle = memory_->SystemHeapAlloc(256); - auto lpXexExecutableModuleHandle = - memory_->TranslateVirtual(pXexExecutableModuleHandle); - xe::store_and_swap(lppXexExecutableModuleHandle, - pXexExecutableModuleHandle); - xe::store_and_swap(lpXexExecutableModuleHandle + 0x58, 0x80101100); // ExLoadedCommandLine (char*) // The name of the xex. Not sure this is ever really used on real devices. diff --git a/src/xenia/kernel/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl_rtl.cc index 993344ec3..0ff82a422 100644 --- a/src/xenia/kernel/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl_rtl.cc @@ -385,49 +385,22 @@ SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_context, 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("RtlImageXexHeaderField(%.8X, %.8X)", xex_header_base, image_field); - // PVOID - // PVOID XexHeaderBase - // DWORD ImageField - - // 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. - - // TODO(benvanik): use xex_header_base to dereference this. - // Right now we are only concerned with games making this call on their main - // module, so this hack is fine. - assert_true(xex_header_base == 0x80101100); - auto module = kernel_state->GetExecutableModule(); - - const xe_xex2_header_t* xex_header = module->xex_header(); - for (size_t n = 0; n < xex_header->header_count; n++) { - if (xex_header->headers[n].key == image_field) { - uint32_t value = xex_header->headers[n].value; - SHIM_SET_RETURN_32(value); - return; - } + auto header = + kernel_memory()->TranslateVirtual(xex_header_base); + if (!header) { + SHIM_SET_RETURN_32(X_STATUS_UNSUCCESSFUL); + return; } - // Some games seem to expect 0xC0000225 for not-found results, while - // others will explode if it's not zero. Maybe there are default headers? - switch (image_field) { - case 0x20401: // XEX_HEADER_DEFAULT_HEAP_SIZE - SHIM_SET_RETURN_32(0); - break; - default: - SHIM_SET_RETURN_32(X_STATUS_NOT_FOUND); - break; + uint8_t* hdr = xex2_get_opt_header(header, image_field); + if (!hdr) { + SHIM_SET_RETURN_32(X_STATUS_NOT_FOUND); + return; } + + SHIM_SET_RETURN_32((uint32_t)(hdr - kernel_memory()->virtual_membase())); } // Unfortunately the Windows RTL_CRITICAL_SECTION object is bigger than the one