diff --git a/src/core/kernel/exports/EmuKrnlXe.cpp b/src/core/kernel/exports/EmuKrnlXe.cpp index 7a105f63d..48c26ec30 100644 --- a/src/core/kernel/exports/EmuKrnlXe.cpp +++ b/src/core/kernel/exports/EmuKrnlXe.cpp @@ -75,11 +75,6 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection if (sectionData != nullptr) { // If the reference count was zero, load the section if (Section->SectionReferenceCount == 0) { - // Clear the memory the section requires - memset(Section->VirtualAddress, 0, Section->VirtualSize); - // Copy the section data - memcpy(Section->VirtualAddress, sectionData, Section->FileSize); - // REMARK: Some titles have sections less than PAGE_SIZE, which will cause an overlap with the next section // since both will have the same aligned starting address. // Test case: Dead or Alive 3, section XGRPH has a size of 764 bytes @@ -89,7 +84,15 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection VAddr BaseAddress = (VAddr)Section->VirtualAddress; size_t SectionSize = (VAddr)Section->VirtualSize; - ret = g_VMManager.XbAllocateVirtualMemory(&BaseAddress, 0, &SectionSize, XBOX_MEM_COMMIT, XBOX_PAGE_EXECUTE_READWRITE); + ret = g_VMManager.XbAllocateVirtualMemory(&BaseAddress, 0, &SectionSize, XBOX_MEM_COMMIT, XBOX_PAGE_EXECUTE_READWRITE); + if (ret != STATUS_SUCCESS) { + RETURN(ret); + } + + // Clear the memory the section requires + memset(Section->VirtualAddress, 0, Section->VirtualSize); + // Copy the section data + memcpy(Section->VirtualAddress, sectionData, Section->FileSize); // Increment the head/tail page reference counters (*Section->HeadReferenceCount)++; diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index fa4ce9524..1a22491e8 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -1231,7 +1231,7 @@ void CxbxKrnlMain(int argc, char* argv[]) if ((sectionHeaders[i].Flags & XBEIMAGE_SECTION_PRELOAD) != 0) { NTSTATUS result = xboxkrnl::XeLoadSection(§ionHeaders[i]); if (FAILED(result)) { - CxbxKrnlCleanupEx(LOG_PREFIX_INIT, "Failed to preload XBE section: %s", CxbxKrnl_Xbe->m_szSectionName[i]); + EmuLogEx(LOG_PREFIX_INIT, LOG_LEVEL::WARNING, "Failed to preload XBE section: %s", CxbxKrnl_Xbe->m_szSectionName[i]); } } } diff --git a/src/core/kernel/memory-manager/VMManager.cpp b/src/core/kernel/memory-manager/VMManager.cpp index 35de293b6..ca2578bbf 100644 --- a/src/core/kernel/memory-manager/VMManager.cpp +++ b/src/core/kernel/memory-manager/VMManager.cpp @@ -1744,6 +1744,19 @@ xboxkrnl::NTSTATUS VMManager::XbAllocateVirtualMemory(VAddr* addr, ULONG ZeroBit goto Exit; } + // Attempt to commit the requested range with VirtualAlloc *before* setting up and reserving the PT + // This allows an early-out in a failure scenario (Test Case: Star Wars Battlefront DVD Demo: LA-018 v1.02) + if (AlignedCapturedBase >= XBE_MAX_VA) + { + if (!VirtualAlloc((void*)AlignedCapturedBase, AlignedCapturedSize, MEM_COMMIT, + (ConvertXboxToWinProtection(PatchXboxPermissions(Protect))) & ~(PAGE_WRITECOMBINE | PAGE_NOCACHE))) + { + DBG_PRINTF("%s: VirtualAlloc failed to commit the memory! The error was %d\n", __func__, GetLastError()); + status = STATUS_NO_MEMORY; + goto Exit; + } + } + // Check if we have to construct the PT's for this allocation if (!AllocatePT(AlignedCapturedSize, AlignedCapturedBase)) @@ -1769,18 +1782,6 @@ xboxkrnl::NTSTATUS VMManager::XbAllocateVirtualMemory(VAddr* addr, ULONG ZeroBit PointerPte++; } - // Actually commit the requested range but don't if it's inside the placeholder or we are committing an xbe section so that - // XeLoadSection works as expected - - if (AlignedCapturedBase >= XBE_MAX_VA) - { - if (!VirtualAlloc((void*)AlignedCapturedBase, AlignedCapturedSize, MEM_COMMIT, - (ConvertXboxToWinProtection(PatchXboxPermissions(Protect))) & ~(PAGE_WRITECOMBINE | PAGE_NOCACHE))) - { - DBG_PRINTF("%s: VirtualAlloc failed to commit the memory! The error was %d\n", __func__, GetLastError()); - } - } - // Because VirtualAlloc always zeros the memory for us, XBOX_MEM_NOZERO is still unsupported if (AllocationType & XBOX_MEM_NOZERO) { DBG_PRINTF("XBOX_MEM_NOZERO flag is not supported!\n"); }