Cleaned up of the loader project, added environment checks and documented it somewhat.
This commit is contained in:
parent
2295a10e77
commit
420d689d82
|
@ -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 <pvanlogchem@gmail.com>
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// *
|
||||
// * 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;
|
||||
}
|
||||
|
|
|
@ -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 <pvanlogchem@gmail.com>
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// *
|
||||
// * 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <pvanlogchem@gmail.com>
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// *
|
||||
// * 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<size_t>(!(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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue