Merge pull request #768 from LukeUsher/xbe-loading
Xbe loading & FileSystem Tweaks
This commit is contained in:
commit
e305ff48bb
|
@ -144,7 +144,7 @@ Xbe::Xbe(const char *x_szFilename)
|
|||
char Dir[_MAX_DIR];
|
||||
char Filename[_MAX_FNAME];
|
||||
_splitpath(x_szFilename, nullptr, Dir, Filename, nullptr);
|
||||
if (stricmp(Filename, "default") != 0) {
|
||||
if (_stricmp(Filename, "default") != 0) {
|
||||
strcpy(m_szAsciiTitle, Filename);
|
||||
}
|
||||
else {
|
||||
|
@ -187,18 +187,18 @@ Xbe::Xbe(const char *x_szFilename)
|
|||
{
|
||||
printf("Xbe::Xbe: Reading Section Names...\n");
|
||||
|
||||
m_szSectionName = new char[m_Header.dwSections][9];
|
||||
m_szSectionName = new char[m_Header.dwSections][10];
|
||||
for(uint32 v=0;v<m_Header.dwSections;v++)
|
||||
{
|
||||
printf("Xbe::Xbe: Reading Section Name 0x%.04X...", v);
|
||||
|
||||
uint08 *sn = GetAddr(m_SectionHeader[v].dwSectionNameAddr);
|
||||
|
||||
memset(m_szSectionName[v], 0, 9);
|
||||
memset(m_szSectionName[v], 0, 10);
|
||||
|
||||
if(sn != 0)
|
||||
{
|
||||
for(int b=0;b<8;b++)
|
||||
for(int b=0;b<9;b++)
|
||||
{
|
||||
m_szSectionName[v][b] = sn[b];
|
||||
|
||||
|
|
|
@ -222,8 +222,8 @@ class Xbe : public Error
|
|||
#include "AlignPosfix1.h"
|
||||
*m_TLS;
|
||||
|
||||
// Xbe section names, each 8 bytes max and null terminated
|
||||
char (*m_szSectionName)[9];
|
||||
// Xbe section names, stored null terminated
|
||||
char (*m_szSectionName)[10];
|
||||
|
||||
// Xbe sections
|
||||
uint08 **m_bzSection;
|
||||
|
@ -360,4 +360,11 @@ const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_HARD_DISK = 0x40000000;
|
|||
const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_MODE = 0x80000000;
|
||||
const uint32 XBEIMAGE_MEDIA_TYPE_MEDIA_MASK = 0x00FFFFFF;
|
||||
|
||||
// section type flags for Xbe
|
||||
const uint32 XBEIMAGE_SECTION_WRITEABLE = 0x00000001;
|
||||
const uint32 XBEIMAGE_SECTION_PRELOAD = 0x00000002;
|
||||
const uint32 XBEIMAGE_SECTION_EXECUTABLE = 0x00000004;
|
||||
const uint32 XBEIMAGE_SECTION_INSERTFILE = 0x00000008;
|
||||
const uint32 XBEIMAGE_SECTION_HEAD_PAGE_READONLY = 0x00000010;
|
||||
const uint32 XBEIMAGE_SECTION_TAIL_PAGE_READONLY = 0x00000020;
|
||||
#endif
|
||||
|
|
|
@ -177,7 +177,6 @@ void CxbxLaunchXbe(void(*Entry)())
|
|||
__try
|
||||
{
|
||||
Entry();
|
||||
|
||||
}
|
||||
__except (EmuException(GetExceptionInformation()))
|
||||
{
|
||||
|
@ -503,29 +502,21 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
// Determine memory size accordingly :
|
||||
SIZE_T memorySize = (g_bIsChihiro ? CHIHIRO_MEMORY_SIZE : XBOX_MEMORY_SIZE);
|
||||
|
||||
// Copy over loaded Xbe Header to specified base address
|
||||
// Copy over loaded Xbe Headers to specified base address
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header));
|
||||
// Copy over the certificate
|
||||
memcpy((void*)(CxbxKrnl_Xbe->m_Header.dwBaseAddr + sizeof(Xbe::Header)), CxbxKrnl_Xbe->m_HeaderEx, CxbxKrnl_Xbe->m_ExSize);
|
||||
// Copy over the library versions
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwLibraryVersionsAddr, CxbxKrnl_Xbe->m_LibraryVersion, CxbxKrnl_Xbe->m_Header.dwLibraryVersions * sizeof(DWORD));
|
||||
// TODO : Actually, instead of copying from CxbxKrnl_Xbe, we should load the entire Xbe directly into memory, like Dxbx does - see _ReadXbeBlock()
|
||||
|
||||
// Verify no section would load outside virtual_memory_placeholder (which would overwrite Cxbx code)
|
||||
// Load all sections marked as preload using the in-memory copy of the xbe header
|
||||
xboxkrnl::PXBEIMAGE_SECTION sectionHeaders = (xboxkrnl::PXBEIMAGE_SECTION)CxbxKrnl_Xbe->m_Header.dwSectionHeadersAddr;
|
||||
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
|
||||
xbaddr section_end = CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr + CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw;
|
||||
if (section_end >= XBE_MAX_VA)
|
||||
{
|
||||
CxbxPopupMessage("Couldn't load XBE section - please report this!");
|
||||
return; // TODO : Halt(0);
|
||||
if ((sectionHeaders[i].Flags & XBEIMAGE_SECTION_PRELOAD) != 0) {
|
||||
NTSTATUS result = xboxkrnl::XeLoadSection(§ionHeaders[i]);
|
||||
if (FAILED(result)) {
|
||||
CxbxKrnlCleanup("Failed to preload XBE section: %s", CxbxKrnl_Xbe->m_szSectionName[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load all sections to their requested Virtual Address :
|
||||
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr, CxbxKrnl_Xbe->m_bzSection[i], CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw);
|
||||
}
|
||||
|
||||
// We need to remember a few XbeHeader fields, so we can switch between a valid ExeHeader and XbeHeader :
|
||||
StoreXbeImageHeader();
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#define CXBXKRNL_H
|
||||
|
||||
#include "Cxbx.h"
|
||||
|
||||
#include "Common/Xbe.h"
|
||||
|
||||
#undef FIELD_OFFSET // prevent macro redefinition warnings
|
||||
|
|
|
@ -193,7 +193,8 @@ NTSTATUS CxbxConvertFilePath(
|
|||
std::string RelativeXboxPath,
|
||||
OUT std::wstring &RelativeHostPath,
|
||||
OUT NtDll::HANDLE *RootDirectory,
|
||||
std::string aFileAPIName)
|
||||
std::string aFileAPIName,
|
||||
bool partitionHeader)
|
||||
{
|
||||
std::string OriginalPath = RelativeXboxPath;
|
||||
std::string RelativePath = RelativeXboxPath;
|
||||
|
@ -278,7 +279,15 @@ NTSTATUS CxbxConvertFilePath(
|
|||
}
|
||||
|
||||
XboxFullPath = NtSymbolicLinkObject->XboxSymbolicLinkPath;
|
||||
*RootDirectory = NtSymbolicLinkObject->RootDirectoryHandle;
|
||||
|
||||
// If directly accessing a partition header, redirect to the partitionX.bin file
|
||||
if (partitionHeader) {
|
||||
RelativePath = DrivePrefix + HostPath.substr(0, HostPath.length()) + ".bin";
|
||||
} else {
|
||||
// If accessing a partition as a directly, set the root directory handle and keep relative path as is
|
||||
*RootDirectory = NtSymbolicLinkObject->RootDirectoryHandle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check for special case : Partition0
|
||||
|
@ -317,7 +326,8 @@ NTSTATUS CxbxConvertFilePath(
|
|||
NTSTATUS CxbxObjectAttributesToNT(
|
||||
xboxkrnl::POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
OUT NativeObjectAttributes& nativeObjectAttributes,
|
||||
const std::string aFileAPIName)
|
||||
const std::string aFileAPIName,
|
||||
bool partitionHeader)
|
||||
{
|
||||
if (ObjectAttributes == NULL)
|
||||
{
|
||||
|
@ -346,7 +356,7 @@ NTSTATUS CxbxObjectAttributesToNT(
|
|||
if (aFileAPIName.size() > 0)
|
||||
{
|
||||
// Then interpret the ObjectName as a filename, and update it to host relative :
|
||||
NTSTATUS result = CxbxConvertFilePath(ObjectName, /*OUT*/RelativeHostPath, /*OUT*/&RootDirectory, aFileAPIName);
|
||||
NTSTATUS result = CxbxConvertFilePath(ObjectName, /*OUT*/RelativeHostPath, /*OUT*/&RootDirectory, aFileAPIName, partitionHeader);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
}
|
||||
|
@ -400,6 +410,18 @@ int CxbxRegisterDeviceHostPath(std::string XboxDevicePath, std::string HostDevic
|
|||
}
|
||||
else
|
||||
{
|
||||
// All HDD partitions have a .bin file to allow direct file io on the partition info
|
||||
if (_strnicmp(XboxDevicePath.c_str(), DeviceHarddisk0PartitionPrefix.c_str(), DeviceHarddisk0PartitionPrefix.length()) == 0) {
|
||||
std::string partitionHeaderPath = (HostDevicePath + ".bin").c_str();
|
||||
if (!PathFileExists(partitionHeaderPath.c_str())) {
|
||||
HANDLE hf = CreateFile(partitionHeaderPath.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
|
||||
SetFilePointer(hf, 512 * 1024, 0, FILE_BEGIN);
|
||||
SetEndOfFile(hf);
|
||||
CloseHandle(hf);
|
||||
}
|
||||
}
|
||||
|
||||
int status = SHCreateDirectoryEx(NULL, HostDevicePath.c_str(), NULL);
|
||||
if (status == STATUS_SUCCESS || status == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
|
|
|
@ -165,8 +165,8 @@ struct NativeObjectAttributes {
|
|||
NtDll::POBJECT_ATTRIBUTES NtObjAttrPtr;
|
||||
};
|
||||
|
||||
NTSTATUS CxbxObjectAttributesToNT(xboxkrnl::POBJECT_ATTRIBUTES ObjectAttributes, NativeObjectAttributes& nativeObjectAttributes, std::string aFileAPIName = "");
|
||||
NTSTATUS CxbxConvertFilePath(std::string RelativeXboxPath, OUT std::wstring &RelativeHostPath, OUT NtDll::HANDLE *RootDirectory, std::string aFileAPIName = "");
|
||||
NTSTATUS CxbxObjectAttributesToNT(xboxkrnl::POBJECT_ATTRIBUTES ObjectAttributes, NativeObjectAttributes& nativeObjectAttributes, std::string aFileAPIName = "", bool partitionHeader = false);
|
||||
NTSTATUS CxbxConvertFilePath(std::string RelativeXboxPath, OUT std::wstring &RelativeHostPath, OUT NtDll::HANDLE *RootDirectory, std::string aFileAPIName = "", bool partitionHeader = false);
|
||||
|
||||
// ******************************************************************
|
||||
// * Wrapper of a handle object
|
||||
|
|
|
@ -259,7 +259,23 @@ XBSYSAPI EXPORTNUM(66) xboxkrnl::NTSTATUS NTAPI xboxkrnl::IoCreateFile
|
|||
|
||||
NativeObjectAttributes nativeObjectAttributes;
|
||||
|
||||
NTSTATUS ret = CxbxObjectAttributesToNT(ObjectAttributes, /*OUT*/nativeObjectAttributes, "IoCreateFile");
|
||||
// If we are NOT accessing a directory, and we match a partition path, we need to redirect to a partition.bin file
|
||||
bool isDirectPartitionAccess = false;
|
||||
std::string objectName = std::string(ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length);
|
||||
if ((CreateOptions & FILE_DIRECTORY_FILE) == 0 && _strnicmp(objectName.c_str(), DeviceHarddisk0PartitionPrefix.c_str(), DeviceHarddisk0PartitionPrefix.length()) == 0) {
|
||||
isDirectPartitionAccess = true;
|
||||
}
|
||||
|
||||
NTSTATUS ret = CxbxObjectAttributesToNT(ObjectAttributes, /*OUT*/nativeObjectAttributes, "IoCreateFile", isDirectPartitionAccess);
|
||||
|
||||
// When a Synchronous CreateOption is specified, DesiredAccess must have SYNCHRONIZE set
|
||||
if ((CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT) != 0 ||
|
||||
(CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) != 0) {
|
||||
DesiredAccess |= SYNCHRONIZE;
|
||||
}
|
||||
|
||||
// Force ShareAccess to all
|
||||
ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
|
||||
if (!FAILED(ret))
|
||||
// redirect to NtCreateFile
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace xboxkrnl
|
|||
#include <xboxkrnl/xboxkrnl.h> // For XeImageFileName, etc.
|
||||
};
|
||||
|
||||
#include "CxbxKrnl.h" // For CxbxKrnl_Xbe
|
||||
#include "Logging.h" // For LOG_FUNC()
|
||||
#include "EmuKrnlLogging.h"
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
|
@ -76,12 +77,24 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
|
|||
LOG_FUNC_ARG(Section)
|
||||
LOG_FUNC_END;
|
||||
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
NTSTATUS ret = STATUS_INVALID_HANDLE;
|
||||
|
||||
if (Section->SectionReferenceCount++ == 0) {
|
||||
LOG_INCOMPLETE(); // TODO : Load section - probably lock this too
|
||||
void* sectionData = CxbxKrnl_Xbe->FindSection((char*)std::string(Section->SectionName, 9).c_str());
|
||||
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);
|
||||
}
|
||||
|
||||
// Increment the reference count
|
||||
Section->SectionReferenceCount++;
|
||||
|
||||
ret = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
|
@ -101,15 +114,20 @@ XBSYSAPI EXPORTNUM(328) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeUnloadSection
|
|||
LOG_FUNC_ARG(Section)
|
||||
LOG_FUNC_END;
|
||||
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
NTSTATUS ret = STATUS_INVALID_PARAMETER;
|
||||
|
||||
// If the section was loaded, process it
|
||||
if (Section->SectionReferenceCount > 0) {
|
||||
if (--Section->SectionReferenceCount == 0) {
|
||||
LOG_INCOMPLETE(); // TODO : Unload section - probably lock this too
|
||||
// Decrement the reference count
|
||||
Section->SectionReferenceCount -= 1;
|
||||
|
||||
// Free the section if necessary
|
||||
if (Section->SectionReferenceCount == 0) {
|
||||
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
||||
}
|
||||
|
||||
ret = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
ret = STATUS_INVALID_PARAMETER;
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue