diff --git a/src/CxbxLoader/loader.cpp b/src/CxbxLoader/loader.cpp index e9e6f999f..973aeeb31 100644 --- a/src/CxbxLoader/loader.cpp +++ b/src/CxbxLoader/loader.cpp @@ -28,7 +28,7 @@ // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * -// * (c) 2017 Patrick van Logchem +// * (c) 2017-2019 Patrick van Logchem // * // * All rights reserved // * @@ -46,7 +46,7 @@ // This variable *MUST* be this large, for it to take up address space // so that all other code and data in this module are placed outside of the // maximum virtual memory range. -#define VM_PLACEHOLDER_SIZE 128 * 1024 * 1024 +#define VM_PLACEHOLDER_SIZE MB(128) // Enough to cover MemLowVirtual (Cihiro/Devkit) // Note : In the old setup, we used #pragma section(".text"); __declspec(allocate(".text")) // to put this variable at the exact image base address 0x00010000, but that resulted in @@ -59,58 +59,119 @@ unsigned char virtual_memory_placeholder[VM_PLACEHOLDER_SIZE] = { 0 }; // = { OP // Note : This executable is meant to be as tiny as humanly possible. // The C++ runtime library is removed using https://stackoverflow.com/a/39220245/12170 +// This Cxbx loader is tailored to bootstrapping an Xbox environment under Windows. +// This requires : +// * user-access to the lowest possible virtual memory address (0x00010000), +// * complete access to as much as possible of the rest 32 bit address space. +// +// This implies running it as a 32 bit process under WOW64 (64 bit Windows). +// This is done by initially relying on no other code than our own and +// kernel32.DLL (which the Windows kernel loads into all it's processes). +// Also, the linker options for this loader are specified such, that the +// executable will be loaded by Windows at the pre-defined address, and +// won't contain any other code not under our control. +// +// When executed, this loader starts by validating the correct run environment, +// then reserves all memory ranges that Xbox emulation requires, and only then +// loads in the actual emulation code by dynamically loading in our library +// and transfer control to it. +// +// Note, that since the emulation code will have to overwrite the memory where +// this loader resides, no code or data may be used by the emulation code, +// nor may the emulator ever return to this code! + +// Important linker flags : +// /MACHINE:X86 +// /NODEFAULTLIB +// /DYNAMICBASE:NO +// /BASE:"0x00010000" +// /FIXED +// /LARGEADDRESSAWARE +// /SUBSYSTEM:CONSOLE +// /ENTRY:"rawMain" + DWORD CALLBACK rawMain() { (void)virtual_memory_placeholder; // prevent optimization removing this data + // Verify we're running under WOW64 + BOOL bIsWow64Process; + + if (!IsWow64Process(GetCurrentProcess(), &bIsWow64Process)) { + bIsWow64Process = false; + } + + if (!bIsWow64Process) { + OutputDebugString("Not running as a WOW64 process!"); + return ERROR_BAD_ENVIRONMENT; + } + + // We have hard-code BLOCK_SIZE to 64 KiB, check this against the system's allocation granularity. + SYSTEM_INFO SystemInfo; + + GetSystemInfo(&SystemInfo); + if (SystemInfo.dwAllocationGranularity != BLOCK_SIZE) { + OutputDebugString("Unsupported system allocation granularity!"); + return ERROR_BAD_ENVIRONMENT; + } + + if (SystemInfo.dwPageSize != PAGE_SIZE) { + OutputDebugString("Unsupported system page size!"); + return ERROR_BAD_ENVIRONMENT; + } + + if (SystemInfo.lpMaximumApplicationAddress < (void*)0xFFFEFFFF) { + // Note : If this fails, the large-address-aware linker flag must be restored + OutputDebugString("Maximum applocation address too low!"); + return ERROR_BAD_ENVIRONMENT; + } + + int system = SYSTEM_XBOX; // By default, we'll emulate a retail Xbox + + // Note : Since we only have kernel32 API's available (not even the standard libary), + // we use the (exclusively wide-char) FindStringOrdinal() here instead of strstr(): LPWSTR CommandLine = GetCommandLineW(); + if (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /chihiro", -1, true) >= 0) { + system = SYSTEM_CHIHIRO; + } else { + if (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /devkit", -1, true) >= 0) { + system = SYSTEM_DEVKIT; + } + } - // Note : Since we only have kernel32 API's available, use FindStringOrdinal() here instead of strstr(): - int flags = (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /devkit", -1, true) >= 0 ? RangeFlags::D : 0) - | (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /chihiro", -1, true) >= 0 ? RangeFlags::C : 0); - - if (!ReserveAddressRanges(flags)) { + if (!ReserveAddressRanges(system)) { // If we get here, emulation lacks important address ranges; Don't launch - OutputDebugStringA("Required address range couldn't be reserved!"); + OutputDebugString("Required address range couldn't be reserved!"); return ERROR_NOT_ENOUGH_MEMORY; } // Only after the required memory ranges are reserved, load our emulation DLL HMODULE hEmulationDLL = LoadLibraryA("CxbxEmulator.dll"); if (!hEmulationDLL) { - // TODO : Move the following towards a tooling function - DWORD err = GetLastError(); - - // Translate ErrorCode to String. - LPTSTR Error = nullptr; - if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - err, - 0, - (LPTSTR)&Error, - 0, - NULL) == 0) { - // Failed in translating. - } - - // Free the buffer. + LPTSTR Error = GetLastErrorString(); if (Error) { OutputDebugString(Error); - ::LocalFree(Error); - Error = nullptr; + FreeLastErrorString(Error); } return ERROR_RESOURCE_NOT_FOUND; } // Find the main emulation function in our DLL - typedef DWORD (WINAPI * Emulate_t)(); + typedef void (WINAPI *Emulate_t)(); Emulate_t pfnEmulate = (Emulate_t)GetProcAddress(hEmulationDLL, "Emulate"); if (!pfnEmulate) { + OutputDebugString("Entrypoint not found!"); return ERROR_RESOURCE_NOT_FOUND; } // Call the main emulation function in our DLL, passing in the results // of the address range reservations - return pfnEmulate(); // TODO : Pass along the command line + pfnEmulate(); // TODO : Pass along all data that we've gathered up until here (or rebuild it over there) + + // Once the Emulate function has control, it may never return here + // because all code and data that have been used up until now are + // overwritten. From now on, only emulated code is allowed to access + // this memory! + return ERROR_APP_DATA_CORRUPT; } diff --git a/src/common/XboxAddressRanges.cpp b/src/common/XboxAddressRanges.cpp index a05ea355b..fe4a18eca 100644 --- a/src/common/XboxAddressRanges.cpp +++ b/src/common/XboxAddressRanges.cpp @@ -28,7 +28,7 @@ // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * -// * (c) 2017 Patrick van Logchem +// * (c) 2017-2019 Patrick van Logchem // * // * All rights reserved // * @@ -40,21 +40,6 @@ #include "XboxAddressRanges.h" -// Maps an XboxAddressRangeType to page protection flags, for use by VirtualAlloc -DWORD XboxAddressRangeTypeToVirtualAllocPageProtectionFlags(int type) -{ - if (XboxAddressRanges[type].Flags & RangeFlags::E) - return PAGE_EXECUTE_READWRITE; - - if (XboxAddressRanges[type].Flags & RangeFlags::R) - return PAGE_READWRITE; - - if (XboxAddressRanges[type].Flags & RangeFlags::N) - return PAGE_NOACCESS; - - return 0; // UNHANDLED -} - typedef struct { int Index; unsigned __int32 Start; @@ -68,13 +53,12 @@ ReservedRange ReservedRanges[128]; int ReservedRangeCount = 0; // Reserve an address range up to the extend of what the host allows. -bool ReserveMemoryRange(int xart) +bool ReserveMemoryRange(int index) { - // assert(XboxAddressRanges[xart].Type == xart); - unsigned __int32 Start = XboxAddressRanges[xart].Start; - int Size = XboxAddressRanges[xart].Size; - + unsigned __int32 Start = XboxAddressRanges[index].Start; + int Size = XboxAddressRanges[index].Size; bool HadAnyFailure = false; + if (Start == 0) { // The zero page (the entire first 64 KB block) can't be reserved (if we would // try to reserve VirtualAlloc at address zero, it would hand us another address) @@ -86,7 +70,7 @@ bool ReserveMemoryRange(int xart) // Safeguard against bounds overflow if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) { // Initialize the reservation of a new range - ReservedRanges[ReservedRangeCount].Index = xart; + ReservedRanges[ReservedRangeCount].Index = index; ReservedRanges[ReservedRangeCount].Start = Start; ReservedRanges[ReservedRangeCount].Size = 0; } @@ -94,7 +78,7 @@ bool ReserveMemoryRange(int xart) // Reserve this range in 64 Kb block increments, so later on our // memory-management code can VirtualFree() each block individually : bool HadFailure = HadAnyFailure; - const DWORD Protect = XboxAddressRangeTypeToVirtualAllocPageProtectionFlags(xart); + const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection; while (Size > 0) { SIZE_T BlockSize = (SIZE_T)(Size > BLOCK_SIZE) ? BLOCK_SIZE : Size; LPVOID Result = VirtualAlloc((LPVOID)Start, BlockSize, MEM_RESERVE, Protect); @@ -111,7 +95,7 @@ bool ReserveMemoryRange(int xart) if (ReservedRanges[ReservedRangeCount].Size > 0) { // Then start a new range, and copy over the current type ReservedRangeCount++; - ReservedRanges[ReservedRangeCount].Index = xart; + ReservedRanges[ReservedRangeCount].Index = index; } // Register a new ranges starting address @@ -141,21 +125,21 @@ bool ReserveMemoryRange(int xart) return !HadAnyFailure; } -bool AddressRangeMatchesFlags(const int xart, const int flags) +bool AddressRangeMatchesFlags(const int index, const int flags) { - return XboxAddressRanges[xart].Flags & flags; + return XboxAddressRanges[index].RangeFlags & flags; } -bool IsOptionalAddressRange(const int xart) +bool IsOptionalAddressRange(const int index) { - return AddressRangeMatchesFlags(xart, RangeFlags::O); + return AddressRangeMatchesFlags(index, MAY_FAIL); } -bool ReserveAddressRanges(const int flags) { +bool ReserveAddressRanges(const int system) { // Loop over all Xbox address ranges for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) { // Skip address ranges that don't match the given flags - if (!AddressRangeMatchesFlags(i, flags)) + if (!AddressRangeMatchesFlags(i, system)) continue; // Try to reserve each address range @@ -171,12 +155,10 @@ bool ReserveAddressRanges(const int flags) { return true; } -bool VerifyAddressRange(int xart) +bool VerifyAddressRange(int index) { - const int PAGE_SIZE = KB(4); - - unsigned __int32 BaseAddress = XboxAddressRanges[xart].Start; - int Size = XboxAddressRanges[xart].Size; + unsigned __int32 BaseAddress = XboxAddressRanges[index].Start; + int Size = XboxAddressRanges[index].Size; if (BaseAddress == 0) { // The zero page (the entire first 64 KB block) can't be verified @@ -186,7 +168,7 @@ bool VerifyAddressRange(int xart) // Verify this range in 64 Kb block increments, as they are supposed // to have been reserved like that too: - const DWORD AllocationProtect = (XboxAddressRanges[xart].Start == 0) ? PAGE_EXECUTE_WRITECOPY : XboxAddressRangeTypeToVirtualAllocPageProtectionFlags(xart); + const DWORD AllocationProtect = (XboxAddressRanges[index].Start == 0) ? PAGE_EXECUTE_WRITECOPY : XboxAddressRanges[index].InitialMemoryProtection; MEMORY_BASIC_INFORMATION mbi; while (Size > 0) { // Expected values @@ -197,7 +179,7 @@ bool VerifyAddressRange(int xart) DWORD Type = MEM_PRIVATE; // Allowed deviations - if (XboxAddressRanges[xart].Start == 0) { + if (XboxAddressRanges[index].Start == 0) { AllocationBase = (PVOID)0x10000; switch (BaseAddress) { case 0x10000: // Image Header @@ -245,7 +227,7 @@ bool VerifyAddressRange(int xart) Okay = (mbi.Type == Type); if (!Okay) - if (!IsOptionalAddressRange(xart)) + if (!IsOptionalAddressRange(index)) return false; // Handle the next region @@ -256,10 +238,14 @@ bool VerifyAddressRange(int xart) return true; } -bool VerifyAddressRanges() +bool VerifyAddressRanges(const int system) { // Loop over all Xbox address ranges for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) { + // Skip address ranges that don't match the given flags + if (!AddressRangeMatchesFlags(i, system)) + continue; + if (!VerifyAddressRange(i)) { if (!IsOptionalAddressRange(i)) { return false; @@ -270,23 +256,22 @@ bool VerifyAddressRanges() return true; } -void UnreserveMemoryRange(int xart) +void UnreserveMemoryRange(const int index) { - unsigned __int32 Start = XboxAddressRanges[xart].Start; - int Size = XboxAddressRanges[xart].Size; + unsigned __int32 Start = XboxAddressRanges[index].Start; + int Size = XboxAddressRanges[index].Size; while (Size > 0) { - // To release, dwSize must be zero! - VirtualFree((LPVOID)Start, (SIZE_T)0, MEM_RELEASE); + VirtualFree((LPVOID)Start, (SIZE_T)0, MEM_RELEASE); // To release, dwSize must be zero! Start += BLOCK_SIZE; Size -= BLOCK_SIZE; } } -bool AllocateMemoryRange(int xart) +bool AllocateMemoryRange(const int index) { - unsigned __int32 Start = XboxAddressRanges[xart].Start; - int Size = XboxAddressRanges[xart].Size; + unsigned __int32 Start = XboxAddressRanges[index].Start; + int Size = XboxAddressRanges[index].Size; while (Size > 0) { int BlockSize = (Size > BLOCK_SIZE) ? BLOCK_SIZE : Size; @@ -300,3 +285,31 @@ bool AllocateMemoryRange(int xart) return true; } + +LPTSTR GetLastErrorString() +{ + DWORD err = GetLastError(); + + // Translate ErrorCode to String. + LPTSTR Error = nullptr; + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, + 0, + (LPTSTR)&Error, + 0, + NULL) == 0) { + // Failed in translating. + } + + return Error; +} + +void FreeLastErrorString(LPTSTR Error) +{ + if (Error) { + ::LocalFree(Error); + Error = nullptr; + } +} + diff --git a/src/common/XboxAddressRanges.h b/src/common/XboxAddressRanges.h index 8537b71be..10afcffd0 100644 --- a/src/common/XboxAddressRanges.h +++ b/src/common/XboxAddressRanges.h @@ -28,7 +28,7 @@ // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * -// * (c) 2017 Patrick van Logchem +// * (c) 2017-2019 Patrick van Logchem // * // * All rights reserved // * @@ -38,59 +38,72 @@ #define KB(x) ((x) * 1024 ) // = 0x00000400 #define MB(x) ((x) * KB(1024)) // = 0x00100000 -// TODO : Instead of hard-coding the blocksize, read it from system's allocation granularity. -// In practice though, nearly all will be using 64 Kib. +// Windows' address space allocation granularity; +// See https://blogs.msdn.microsoft.com/oldnewthing/20031008-00/?p=42223 const int BLOCK_SIZE = KB(64); +// One allocation block consists of 16 pages (since PAGE_SIZE is 4 kilobytes) +const int PAGE_SIZE = KB(4); + #define ARRAY_SIZE(a) \ ((sizeof(a) / sizeof(*(a))) / \ static_cast(!(sizeof(a) % sizeof(*(a))))) -// Range Flags -typedef enum { - X = (1 << 0), // Xbox (Retail) - C = (1 << 1), // Chihro (Console) - D = (1 << 2), // DevKit - O = (1 << 3), // Optional (may fail address range reservation) - E = (1 << 4), // PAGE_EXECUTE_READWRITE - R = (1 << 5), // PAGE_READWRITE - N = (1 << 6), // PAGE_NOACCESS -} RangeFlags; - typedef struct { const char *Name; unsigned __int32 Start; int Size; - unsigned int Flags; + DWORD InitialMemoryProtection; // Memory page protection, for use by VirtualAlloc + unsigned int RangeFlags; } XboxAddressRange; +// Shortend symbol aliasses for memory page protection +#define PROT_UNH 0 // UNHANDLED +#define PROT_RW PAGE_READWRITE +#define PROT_XRW PAGE_EXECUTE_READWRITE +#define PROT_NAC PAGE_NOACCESS + +// Range flags (used for system selection and optional marker) +#define SYSTEM_XBOX (1 << 0) +#define SYSTEM_DEVKIT (1 << 1) +#define SYSTEM_CHIHIRO (1 << 2) +#define MAY_FAIL (1 << 3) // Optional (may fail address range reservation) + +// Short-hand for sets of system configurations +#define SYSTEM_ALL (SYSTEM_XBOX | SYSTEM_DEVKIT | SYSTEM_CHIHIRO) +#define SYSTEM_RETAIL (SYSTEM_XBOX | SYSTEM_DEVKIT ) +#define SYSTEM_128MB ( SYSTEM_DEVKIT | SYSTEM_CHIHIRO) + const XboxAddressRange XboxAddressRanges[] = { // See http://xboxdevwiki.net/Memory // and http://xboxdevwiki.net/Boot_Process#Paging - { "MemLowVirtual", 0x00000000, MB( 64), X | O | E }, // - 0x07FFFFFF (Retail Xbox) Optional (already reserved via virtual_memory_placeholder) - { "MemLowVirtual", 0x00000000, MB(128), C | D | O | E }, // - 0x07FFFFFF (Chihiro / DevKit) - { "MemPhysical", 0x80000000, MB( 64), X | E }, // - 0x87FFFFFF (Retail) - { "MemPhysical", 0x80000000, MB(128), C | D | E }, // - 0x87FFFFFF (Chihiro / DevKit) - { "DevKitMemory", 0xB0000000, MB(128), D | N }, // - 0xBFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled) + Flag [O]ptional? - { "MemPageTable", 0xC0000000, KB(128), X | C | D | R }, // - 0xC001FFFF TODO : MB(4)? - { "SystemMemory", 0xD0000000, MB(512), X | C | D | O | 0 }, // - 0xEFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled) - { "MemTiled", 0xF0000000, MB( 64), X | C | D | O | 0 }, // - 0xF3FFFFFF Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?) - { "DeviceNV2A_a", 0xFD000000, MB( 7), X | C | D | N }, // - 0xFD6FFFFF (GPU) - { "MemNV2APRAMIN", 0xFD700000, MB( 1), X | C | D | R }, // - 0xFD7FFFFF - { "DeviceNV2A_b", 0xFD800000, MB( 8), X | C | D | N }, // - 0xFDFFFFFF (GPU) - { "DeviceAPU", 0xFE800000, KB(512), X | C | D | N }, // - 0xFE87FFFF - { "DeviceAC97", 0xFEC00000, KB( 4), X | C | D | N }, // - 0xFEC00FFF (ACI) - { "DeviceUSB0", 0xFED00000, KB( 4), X | C | D | N }, // - 0xFED00FFF - { "DeviceUSB1", 0xFED08000, KB( 4), X | C | D | N }, // - 0xFED08FFF Optional (won't be emulated for a long while?) - { "DeviceNVNet", 0xFEF00000, KB( 1), X | C | D | N }, // - 0xFEF003FF - { "DeviceFlash_a", 0xFF000000, MB( 4), X | C | D | N }, // - 0xFF3FFFFF (Flash mirror 1) - { "DeviceFlash_b", 0xFF400000, MB( 4), X | C | D | N }, // - 0xFF7FFFFF (Flash mirror 2) - { "DeviceFlash_c", 0xFF800000, MB( 4), X | C | D | N }, // - 0xFFBFFFFF (Flash mirror 3) - { "DeviceFlash_d", 0xFFC00000, MB( 4), X | C | D | O | N }, // - 0xFFFFFFFF (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine - { "DeviceMCPX", 0xFFFFFE00, 512 , X | D | O | N }, // - 0xFFFFFFFF (not Chihiro, Xbox - if enabled) Optional (can safely be ignored) + { "MemLowVirtual", 0x00000000, MB( 64), PROT_XRW, SYSTEM_XBOX | MAY_FAIL }, // - 0x07FFFFFF (Retail Xbox) Optional (already reserved via virtual_memory_placeholder) + { "MemLowVirtual", 0x00000000, MB(128), PROT_XRW, SYSTEM_128MB | MAY_FAIL }, // - 0x07FFFFFF (Chihiro / DevKit) + { "MemPhysical", 0x80000000, MB( 64), PROT_XRW, SYSTEM_XBOX }, // - 0x87FFFFFF (Retail) + { "MemPhysical", 0x80000000, MB(128), PROT_XRW, SYSTEM_128MB }, // - 0x87FFFFFF (Chihiro / DevKit) + { "DevKitMemory", 0xB0000000, MB(128), PROT_NAC, SYSTEM_DEVKIT }, // - 0xBFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled) + Flag [O]ptional? + { "MemPageTable", 0xC0000000, KB(128), PROT_RW, SYSTEM_ALL }, // - 0xC001FFFF TODO : MB(4)? + { "SystemMemory", 0xD0000000, MB(512), PROT_UNH, SYSTEM_ALL | MAY_FAIL }, // - 0xEFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled) + { "MemTiled", 0xF0000000, MB( 64), PROT_UNH, SYSTEM_ALL | MAY_FAIL }, // - 0xF3FFFFFF Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?) + { "DeviceNV2A_a", 0xFD000000, MB( 7), PROT_NAC, SYSTEM_ALL }, // - 0xFD6FFFFF (GPU) + { "MemNV2APRAMIN", 0xFD700000, MB( 1), PROT_RW, SYSTEM_ALL }, // - 0xFD7FFFFF + { "DeviceNV2A_b", 0xFD800000, MB( 8), PROT_NAC, SYSTEM_ALL }, // - 0xFDFFFFFF (GPU) + { "DeviceAPU", 0xFE800000, KB(512), PROT_NAC, SYSTEM_ALL }, // - 0xFE87FFFF + { "DeviceAC97", 0xFEC00000, KB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFEC00FFF (ACI) + { "DeviceUSB0", 0xFED00000, KB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFED00FFF + { "DeviceUSB1", 0xFED08000, KB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL }, // - 0xFED08FFF Optional (won't be emulated for a long while?) + { "DeviceNVNet", 0xFEF00000, KB( 1), PROT_NAC, SYSTEM_ALL }, // - 0xFEF003FF + { "DeviceFlash_a", 0xFF000000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFF3FFFFF (Flash mirror 1) + { "DeviceFlash_b", 0xFF400000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFF7FFFFF (Flash mirror 2) + { "DeviceFlash_c", 0xFF800000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFFBFFFFF (Flash mirror 3) + { "DeviceFlash_d", 0xFFC00000, MB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL }, // - 0xFFFFFFFF (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine + { "DeviceMCPX", 0xFFFFFE00, 512 , PROT_NAC, SYSTEM_RETAIL | MAY_FAIL }, // - 0xFFFFFFFF (not Chihiro, Xbox - if enabled) Optional (can safely be ignored) }; -extern bool ReserveAddressRanges(const int flags); -extern bool VerifyAddressRanges(); -extern void UnreserveMemoryRange(XboxAddressRange& xart); -extern bool AllocateMemoryRange(XboxAddressRange& xart); +extern bool ReserveAddressRanges(const int system); +extern bool VerifyAddressRanges(const int system); +extern void UnreserveMemoryRange(const int index); +extern bool AllocateMemoryRange(const int index); + +extern LPTSTR GetLastErrorString(); +extern void FreeLastErrorString(LPTSTR Error); diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 826ece1a0..266543511 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -1063,7 +1063,7 @@ void CxbxKrnlMain(int argc, char* argv[]) #endif #ifdef CXBX_LOADER - if (!VerifyAddressRanges()) { + if (!VerifyAddressRanges(SYSTEM_XBOX)) { CxbxPopupMessage("Cxbx-Reloaded hasn't got access to all required address ranges"); return; // TODO : Halt(0); }