Updated memory functions to work with the loader
This commit is contained in:
parent
a8e8f0c071
commit
52f0d6f03b
|
@ -20,6 +20,7 @@
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||||
|
// * (c) 2019 ergo720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -71,7 +72,6 @@ const struct {
|
||||||
#define SYSTEM_CHIHIRO (1 << 3)
|
#define SYSTEM_CHIHIRO (1 << 3)
|
||||||
// Short-hand for sets of system configurations
|
// Short-hand for sets of system configurations
|
||||||
#define SYSTEM_ALL (SYSTEM_XBOX | SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
|
#define SYSTEM_ALL (SYSTEM_XBOX | SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
|
||||||
#define SYSTEM_RETAIL (SYSTEM_XBOX | SYSTEM_DEVKIT )
|
|
||||||
#define SYSTEM_128MB ( SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
|
#define SYSTEM_128MB ( SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
const char *Comment;
|
const char *Comment;
|
||||||
|
@ -84,31 +84,26 @@ const struct {
|
||||||
#endif
|
#endif
|
||||||
// See http://xboxdevwiki.net/Memory
|
// See http://xboxdevwiki.net/Memory
|
||||||
// and http://xboxdevwiki.net/Boot_Process#Paging
|
// and http://xboxdevwiki.net/Boot_Process#Paging
|
||||||
// Entry : Start , End , Size , Protect , RangeFlags , Comment
|
// Entry : Start , End , Size , Protect , RangeFlags , Comment
|
||||||
RANGE_ENTRY(0x00000000, 0x03FFFFFF, MB( 64), PROT_XRW, SYSTEM_XBOX | MAY_FAIL, "MemLowVirtual (Retail Xbox) Optional (already reserved via virtual_memory_placeholder)"),
|
RANGE_ENTRY(0x00010000, 0x03FFFFFF, MB( 64) - KB(64), PROT_XRW, SYSTEM_XBOX | MAY_FAIL, "MemLowVirtual (Retail Xbox) Optional (already reserved via virtual_memory_placeholder)"),
|
||||||
RANGE_ENTRY(0x00000000, 0x07FFFFFF, MB(128), PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit)"),
|
RANGE_ENTRY(0x00010000, 0x07FFFFFF, MB(128) - KB(64), PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit)"),
|
||||||
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64), PROT_XRW, SYSTEM_XBOX , "MemPhysical (Retail)"),
|
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64) , PROT_UNH, SYSTEM_XBOX , "MemPhysical (Retail)"),
|
||||||
RANGE_ENTRY(0x80000000, 0x87FFFFFF, MB(128), PROT_XRW, SYSTEM_128MB , "MemPhysical (Chihiro / DevKit)"),
|
RANGE_ENTRY(0x80000000, 0x87FFFFFF, MB(128) , PROT_UNH, SYSTEM_128MB , "MemPhysical (Chihiro / DevKit)"),
|
||||||
RANGE_ENTRY(0xB0000000, 0xB7FFFFFF, MB(128), PROT_NAC, SYSTEM_DEVKIT , "DevKitMemory"), // TODO : Check reserved range (might behave like MemTiled)
|
RANGE_ENTRY(0xB0000000, 0xBFFFFFFF, MB(256) , PROT_NAC, SYSTEM_DEVKIT , "DevKitMemory"), // TODO : Check reserved range (might behave like MemTiled)
|
||||||
RANGE_ENTRY(0xC0000000, 0xC03FFFFF, MB( 4), PROT_RW, SYSTEM_ALL , "MemPageTable"), // See PAGE_TABLES_SIZE, which contains one 4 byte entry per PAGE_SIZE
|
RANGE_ENTRY(0xC0000000, 0xC03FFFFF, MB( 4) , PROT_RW, SYSTEM_ALL , "MemPageTable"), // See PAGE_TABLES_SIZE, which contains one 4 byte entry per PAGE_SIZE
|
||||||
RANGE_ENTRY(0xD0000000, 0xEFFFFFFF, MB(512), PROT_UNH, SYSTEM_ALL | MAY_FAIL, "SystemMemory Optional"), // TODO : Check reserved range (might behave like MemTiled)
|
RANGE_ENTRY(0xD0000000, 0xEFFFFFFF, MB(512) , PROT_RW, SYSTEM_ALL | MAY_FAIL, "SystemMemory Optional"), // TODO : Check reserved range (might behave like MemTiled)
|
||||||
RANGE_ENTRY(0xF0000000, 0xF3FFFFFF, MB( 64), PROT_UNH, SYSTEM_ALL | MAY_FAIL, "MemTiled Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?)"),
|
RANGE_ENTRY(0xF0000000, 0xF3FFFFFF, MB( 64) , PROT_UNH, SYSTEM_ALL , "MemTiled Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?)"),
|
||||||
RANGE_ENTRY(0xFD000000, 0xFD6FFFFF, MB( 7), PROT_NAC, SYSTEM_ALL , "DeviceNV2A_a (GPU)"),
|
RANGE_ENTRY(0xFD000000, 0xFD6FFFFF, MB( 7) , PROT_NAC, SYSTEM_ALL , "DeviceNV2A_a (GPU)"),
|
||||||
RANGE_ENTRY(0xFD700000, 0xFD7FFFFF, MB( 1), PROT_RW, SYSTEM_ALL , "MemNV2APRAMIN"),
|
RANGE_ENTRY(0xFD700000, 0xFD7FFFFF, MB( 1) , PROT_RW, SYSTEM_ALL , "MemNV2APRAMIN"),
|
||||||
RANGE_ENTRY(0xFD800000, 0xFDFFFFFF, MB( 8), PROT_NAC, SYSTEM_ALL , "DeviceNV2A_b (GPU)"),
|
RANGE_ENTRY(0xFD800000, 0xFDFFFFFF, MB( 8) , PROT_NAC, SYSTEM_ALL , "DeviceNV2A_b (GPU)"),
|
||||||
RANGE_ENTRY(0xFE800000, 0xFE87FFFF, KB(512), PROT_NAC, SYSTEM_ALL , "DeviceAPU"),
|
RANGE_ENTRY(0xFE800000, 0xFE87FFFF, KB(512) , PROT_NAC, SYSTEM_ALL , "DeviceAPU"),
|
||||||
RANGE_ENTRY(0xFEC00000, 0xFEC00FFF, KB( 4), PROT_NAC, SYSTEM_ALL , "DeviceAC97 (ACI)"),
|
RANGE_ENTRY(0xFEC00000, 0xFEC00FFF, KB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceAC97 (ACI)"),
|
||||||
RANGE_ENTRY(0xFED00000, 0xFED00FFF, KB( 4), PROT_NAC, SYSTEM_ALL , "DeviceUSB"),
|
RANGE_ENTRY(0xFED00000, 0xFED00FFF, KB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceUSB"),
|
||||||
RANGE_ENTRY(0xFEF00000, 0xFEF003FF, KB( 1), PROT_NAC, SYSTEM_ALL , "DeviceNVNet"),
|
RANGE_ENTRY(0xFEF00000, 0xFEF003FF, KB( 1) , PROT_NAC, SYSTEM_ALL , "DeviceNVNet"),
|
||||||
RANGE_ENTRY(0xFF000000, 0xFF3FFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_a (Flash mirror 1)"),
|
RANGE_ENTRY(0xFF000000, 0xFF3FFFFF, MB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceFlash_a (Flash mirror 1)"),
|
||||||
RANGE_ENTRY(0xFF400000, 0xFF7FFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_b (Flash mirror 2)"),
|
RANGE_ENTRY(0xFF400000, 0xFF7FFFFF, MB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceFlash_b (Flash mirror 2)"),
|
||||||
RANGE_ENTRY(0xFF800000, 0xFFBFFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_c (Flash mirror 3)"),
|
RANGE_ENTRY(0xFF800000, 0xFFBFFFFF, MB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceFlash_c (Flash mirror 3)"),
|
||||||
RANGE_ENTRY(0xFFC00000, 0xFFFFFFFF, MB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL, "DeviceFlash_d (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine"),
|
RANGE_ENTRY(0xFFC00000, 0xFFFFFFFF, MB( 4) , PROT_NAC, SYSTEM_ALL | MAY_FAIL, "DeviceFlash_d (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine"),
|
||||||
/* This region is only relevant if we were running the original Xbox boot sequence (including MCPX),
|
|
||||||
so it's completely redundant to use it: By the time the Kernel has started execution, this region is disabled
|
|
||||||
and cannot be re-enabled. Xbox software (and the kernel) have no access to this region whatsoever once 2BL has completed.
|
|
||||||
RANGE_ENTRY(0xFFFFFE00, 0xFFFFFFFF, 512 , PROT_NAC, SYSTEM_RETAIL | MAY_FAIL, "DeviceMCPX (not Chihiro, Xbox - if enabled) Optional (can safely be ignored)"),
|
|
||||||
*/
|
|
||||||
#undef RANGE_ENTRY
|
#undef RANGE_ENTRY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,3 +114,4 @@ extern bool VerifyWow64();
|
||||||
|
|
||||||
extern LPTSTR GetLastErrorString();
|
extern LPTSTR GetLastErrorString();
|
||||||
extern void FreeLastErrorString(LPTSTR Error);
|
extern void FreeLastErrorString(LPTSTR Error);
|
||||||
|
extern void OutputMessage(const char* msg);
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef enum class _IPC_UPDATE_GUI {
|
||||||
, XBOX_LED_COLOUR
|
, XBOX_LED_COLOUR
|
||||||
, LOG_ENABLED
|
, LOG_ENABLED
|
||||||
, KRNL_IS_READY
|
, KRNL_IS_READY
|
||||||
|
, VM_PERSIST_MEM
|
||||||
} IPC_UPDATE_GUI;
|
} IPC_UPDATE_GUI;
|
||||||
|
|
||||||
void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value);
|
void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||||
|
// * (c) 2019 ergo720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -30,35 +31,75 @@
|
||||||
#include "AddressRanges.h"
|
#include "AddressRanges.h"
|
||||||
|
|
||||||
// Reserve an address range up to the extend of what the host allows.
|
// Reserve an address range up to the extend of what the host allows.
|
||||||
bool ReserveMemoryRange(int index)
|
bool ReserveMemoryRange(int index, uint32_t blocks_reserved[384])
|
||||||
{
|
{
|
||||||
uint32_t Start = XboxAddressRanges[index].Start;
|
uint32_t Start = XboxAddressRanges[index].Start;
|
||||||
int Size = XboxAddressRanges[index].Size;
|
int Size = XboxAddressRanges[index].Size;
|
||||||
bool HadAnyFailure = false;
|
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)
|
|
||||||
Start += BLOCK_SIZE;
|
|
||||||
Size -= BLOCK_SIZE;
|
|
||||||
HadAnyFailure = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve this range in 64 Kb block increments, so that during emulation
|
// Reserve this range in 64 Kb block increments, so that during emulation
|
||||||
// our memory-management code can VirtualFree() each block individually :
|
// our memory-management code can VirtualFree() each block individually :
|
||||||
bool HadFailure = HadAnyFailure;
|
|
||||||
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);
|
|
||||||
if (Result == NULL) {
|
|
||||||
HadFailure = true;
|
|
||||||
HadAnyFailure = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the next block
|
const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection;
|
||||||
Start += BLOCK_SIZE;
|
bool NeedsReservationTracking = false;
|
||||||
Size -= BLOCK_SIZE;
|
switch (Start) {
|
||||||
|
case 0x80000000:
|
||||||
|
case 0xF0000000: {
|
||||||
|
static bool NeedsInitialization = true;
|
||||||
|
static HANDLE hFileMapping;
|
||||||
|
if (NeedsInitialization) {
|
||||||
|
hFileMapping = CreateFileMapping(
|
||||||
|
INVALID_HANDLE_VALUE,
|
||||||
|
nullptr,
|
||||||
|
PAGE_EXECUTE_READWRITE,
|
||||||
|
0,
|
||||||
|
Size,
|
||||||
|
nullptr);
|
||||||
|
if (hFileMapping == nullptr) {
|
||||||
|
HadAnyFailure = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NeedsInitialization = false;
|
||||||
|
}
|
||||||
|
LPVOID Result = MapViewOfFileEx(
|
||||||
|
hFileMapping,
|
||||||
|
Start == 0x80000000 ?
|
||||||
|
(FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE) : (FILE_MAP_READ | FILE_MAP_WRITE),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Size,
|
||||||
|
(LPVOID)Start);
|
||||||
|
if (Result == nullptr) {
|
||||||
|
HadAnyFailure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xB0000000:
|
||||||
|
case 0xD0000000: {
|
||||||
|
NeedsReservationTracking = true;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
|
||||||
|
default: {
|
||||||
|
while (Size > 0) {
|
||||||
|
static int arr_index = 0;
|
||||||
|
SIZE_T BlockSize = (SIZE_T)(Size > BLOCK_SIZE) ? BLOCK_SIZE : Size;
|
||||||
|
LPVOID Result = VirtualAlloc((LPVOID)Start, BlockSize, MEM_RESERVE, Protect);
|
||||||
|
if (Result == nullptr) {
|
||||||
|
HadAnyFailure = true;
|
||||||
|
}
|
||||||
|
// Handle the next block
|
||||||
|
Start += BLOCK_SIZE;
|
||||||
|
Size -= BLOCK_SIZE;
|
||||||
|
if (NeedsReservationTracking) {
|
||||||
|
if (Result != nullptr) {
|
||||||
|
blocks_reserved[arr_index / 32] |= (1 << (arr_index % 32));
|
||||||
|
}
|
||||||
|
arr_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only a complete success when the entire request was reserved in a single range
|
// Only a complete success when the entire request was reserved in a single range
|
||||||
|
@ -66,7 +107,7 @@ bool ReserveMemoryRange(int index)
|
||||||
return !HadAnyFailure;
|
return !HadAnyFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReserveAddressRanges(const int system) {
|
bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]) {
|
||||||
// Loop over all Xbox address ranges
|
// Loop over all Xbox address ranges
|
||||||
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
|
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
|
||||||
// Skip address ranges that don't match the given flags
|
// Skip address ranges that don't match the given flags
|
||||||
|
@ -74,7 +115,7 @@ bool ReserveAddressRanges(const int system) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Try to reserve each address range
|
// Try to reserve each address range
|
||||||
if (ReserveMemoryRange(i))
|
if (ReserveMemoryRange(i, blocks_reserved))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Some ranges are allowed to fail reserving
|
// Some ranges are allowed to fail reserving
|
||||||
|
|
|
@ -26,4 +26,4 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern bool ReserveAddressRanges(const int system);
|
extern bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||||
|
// * (c) 2019 ego720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -51,13 +52,6 @@ bool VerifyAddressRange(int index)
|
||||||
int Size = XboxAddressRanges[index].Size;
|
int Size = XboxAddressRanges[index].Size;
|
||||||
bool HadAnyFailure = false;
|
bool HadAnyFailure = false;
|
||||||
|
|
||||||
if (BaseAddress == 0) {
|
|
||||||
// The zero page (the entire first 64 KB block) can't be verified
|
|
||||||
// so to avoid verification failures, we just skip it, knowing it'll be alright
|
|
||||||
BaseAddress += BLOCK_SIZE;
|
|
||||||
Size -= BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safeguard against bounds overflow
|
// Safeguard against bounds overflow
|
||||||
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
|
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
|
||||||
// Initialize the reservation of a new range
|
// Initialize the reservation of a new range
|
||||||
|
@ -69,8 +63,9 @@ bool VerifyAddressRange(int index)
|
||||||
// Verify this range in 64 Kb block increments, as they are supposed
|
// Verify this range in 64 Kb block increments, as they are supposed
|
||||||
// to have been reserved like that too:
|
// to have been reserved like that too:
|
||||||
bool HadFailure = HadAnyFailure;
|
bool HadFailure = HadAnyFailure;
|
||||||
const DWORD AllocationProtect = (XboxAddressRanges[index].Start == 0) ? PAGE_EXECUTE_WRITECOPY : XboxAddressRanges[index].InitialMemoryProtection;
|
const DWORD AllocationProtect = (XboxAddressRanges[index].Start == 0x10000) ? PAGE_EXECUTE_WRITECOPY : XboxAddressRanges[index].InitialMemoryProtection;
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
bool Okay;
|
||||||
while (Size > 0) {
|
while (Size > 0) {
|
||||||
// Expected values
|
// Expected values
|
||||||
PVOID AllocationBase = (PVOID)BaseAddress;
|
PVOID AllocationBase = (PVOID)BaseAddress;
|
||||||
|
@ -78,9 +73,9 @@ bool VerifyAddressRange(int index)
|
||||||
DWORD State = MEM_RESERVE;
|
DWORD State = MEM_RESERVE;
|
||||||
DWORD Protect = 0;
|
DWORD Protect = 0;
|
||||||
DWORD Type = MEM_PRIVATE;
|
DWORD Type = MEM_PRIVATE;
|
||||||
|
#if 0
|
||||||
// Allowed deviations
|
// Allowed deviations
|
||||||
if (XboxAddressRanges[index].Start == 0) {
|
if (XboxAddressRanges[index].Start == 0x10000) {
|
||||||
AllocationBase = (PVOID)0x10000;
|
AllocationBase = (PVOID)0x10000;
|
||||||
State = MEM_COMMIT;
|
State = MEM_COMMIT;
|
||||||
Type = MEM_IMAGE;
|
Type = MEM_IMAGE;
|
||||||
|
@ -110,23 +105,58 @@ bool VerifyAddressRange(int index)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// Verify each block
|
if (BaseAddress == 0x80000000 || BaseAddress == 0xF0000000) {
|
||||||
bool Okay = (VirtualQuery((LPVOID)BaseAddress, &mbi, sizeof(mbi)) != 0);
|
RegionSize = Size;
|
||||||
if (Okay)
|
Okay = (VirtualQuery((LPVOID)BaseAddress, &mbi, sizeof(mbi)) != 0);
|
||||||
Okay = (mbi.BaseAddress == (LPVOID)BaseAddress);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.BaseAddress == (LPVOID)BaseAddress);
|
||||||
Okay = (mbi.AllocationBase == AllocationBase);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.AllocationBase == AllocationBase);
|
||||||
Okay = (mbi.AllocationProtect == AllocationProtect);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.AllocationProtect == (BaseAddress == 0x80000000 ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE));
|
||||||
Okay = (mbi.RegionSize == RegionSize);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.RegionSize == Size);
|
||||||
Okay = (mbi.State == State);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.State == MEM_COMMIT);
|
||||||
Okay = (mbi.Protect == Protect);
|
if (Okay)
|
||||||
if (Okay)
|
Okay = (mbi.Protect == mbi.AllocationProtect);
|
||||||
Okay = (mbi.Type == Type);
|
if (Okay)
|
||||||
|
Okay = (mbi.Type == MEM_MAPPED);
|
||||||
|
}
|
||||||
|
else if (BaseAddress == 0x10000) {
|
||||||
|
RegionSize = 0;
|
||||||
|
while (BaseAddress <= 0x07FFFFFF) {
|
||||||
|
Okay = (VirtualQuery((LPVOID)BaseAddress, &mbi, sizeof(mbi)) != 0);
|
||||||
|
if (!Okay || mbi.State != MEM_COMMIT || mbi.Type != MEM_IMAGE) {
|
||||||
|
Okay = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BaseAddress += mbi.RegionSize;
|
||||||
|
RegionSize += mbi.RegionSize;
|
||||||
|
}
|
||||||
|
if (Okay) {
|
||||||
|
RegionSize = Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Verify each block
|
||||||
|
Okay = (VirtualQuery((LPVOID)BaseAddress, &mbi, sizeof(mbi)) != 0);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.BaseAddress == (LPVOID)BaseAddress);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.AllocationBase == AllocationBase);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.AllocationProtect == AllocationProtect);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.RegionSize == RegionSize);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.State == State);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.Protect == Protect);
|
||||||
|
if (Okay)
|
||||||
|
Okay = (mbi.Type == Type);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Okay) {
|
if (!Okay) {
|
||||||
HadFailure = true;
|
HadFailure = true;
|
||||||
|
@ -154,9 +184,14 @@ bool VerifyAddressRange(int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the next region
|
if (BaseAddress == 0x80000000 || BaseAddress == 0xF0000000 || XboxAddressRanges[index].Start == 0x10000) {
|
||||||
BaseAddress += RegionSize;
|
Size = 0;
|
||||||
Size -= RegionSize;
|
}
|
||||||
|
else {
|
||||||
|
// Handle the next region
|
||||||
|
BaseAddress += RegionSize;
|
||||||
|
Size -= RegionSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safeguard against bounds overflow
|
// Safeguard against bounds overflow
|
||||||
|
|
|
@ -80,7 +80,7 @@ class EmuShared : public Mutex
|
||||||
// * Check if parent process is emulating title
|
// * Check if parent process is emulating title
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void GetIsEmulating(bool *isEmulating) { Lock(); *isEmulating = m_bEmulating_status; Unlock(); }
|
void GetIsEmulating(bool *isEmulating) { Lock(); *isEmulating = m_bEmulating_status; Unlock(); }
|
||||||
void SetIsEmulating(const bool isEmulating) { Lock(); m_bEmulating_status = isEmulating; Unlock(); }
|
void SetIsEmulating(const bool isEmulating) { Lock(); m_bEmulating_status = isEmulating; Unlock(); }
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * Each child process need to wait until parent process is ready
|
// * Each child process need to wait until parent process is ready
|
||||||
|
@ -199,8 +199,7 @@ class EmuShared : public Mutex
|
||||||
void GetLogModules(unsigned int *value)
|
void GetLogModules(unsigned int *value)
|
||||||
{
|
{
|
||||||
Lock();
|
Lock();
|
||||||
for (int i = 0; i < NUM_INTEGERS_LOG; ++i)
|
for (int i = 0; i < NUM_INTEGERS_LOG; ++i) {
|
||||||
{
|
|
||||||
value[i] = m_core.LoggedModules[i];
|
value[i] = m_core.LoggedModules[i];
|
||||||
}
|
}
|
||||||
Unlock();
|
Unlock();
|
||||||
|
@ -208,12 +207,11 @@ class EmuShared : public Mutex
|
||||||
void SetLogModules(unsigned int *value)
|
void SetLogModules(unsigned int *value)
|
||||||
{
|
{
|
||||||
Lock();
|
Lock();
|
||||||
for (int i = 0; i < NUM_INTEGERS_LOG; ++i)
|
for (int i = 0; i < NUM_INTEGERS_LOG; ++i) {
|
||||||
{
|
|
||||||
m_core.LoggedModules[i] = value[i];
|
m_core.LoggedModules[i] = value[i];
|
||||||
}
|
}
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * File storage location
|
// * File storage location
|
||||||
|
|
|
@ -65,6 +65,10 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value)
|
||||||
cmdParam = ID_GUI_STATUS_KRNL_IS_READY;
|
cmdParam = ID_GUI_STATUS_KRNL_IS_READY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IPC_UPDATE_GUI::VM_PERSIST_MEM:
|
||||||
|
cmdParam = ID_GUI_VM_PERSIST_MEM;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmdParam = 0;
|
cmdParam = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -291,6 +291,7 @@ g_EmuCDPD = {0};
|
||||||
/*XB_MACRO(VOID, WINAPI, D3DDevice_LoadVertexShaderProgram, (CONST DWORD*, DWORD) );*/\
|
/*XB_MACRO(VOID, WINAPI, D3DDevice_LoadVertexShaderProgram, (CONST DWORD*, DWORD) );*/\
|
||||||
/*XB_MACRO(VOID, __stdcall, D3DDevice_LoadVertexShader_0, () );*/\
|
/*XB_MACRO(VOID, __stdcall, D3DDevice_LoadVertexShader_0, () );*/\
|
||||||
/*XB_MACRO(VOID, WINAPI, D3DDevice_LoadVertexShader_4, (DWORD) );*/\
|
/*XB_MACRO(VOID, WINAPI, D3DDevice_LoadVertexShader_4, (DWORD) );*/\
|
||||||
|
XB_MACRO(HRESULT, WINAPI, D3DDevice_PersistDisplay, (VOID) ); \
|
||||||
XB_MACRO(HRESULT, WINAPI, D3DDevice_Reset, (XTL::X_D3DPRESENT_PARAMETERS*) ); \
|
XB_MACRO(HRESULT, WINAPI, D3DDevice_Reset, (XTL::X_D3DPRESENT_PARAMETERS*) ); \
|
||||||
/*XB_MACRO(VOID, WINAPI, D3DDevice_SelectVertexShader, (DWORD, DWORD) );*/\
|
/*XB_MACRO(VOID, WINAPI, D3DDevice_SelectVertexShader, (DWORD, DWORD) );*/\
|
||||||
/*XB_MACRO(VOID, __stdcall, D3DDevice_SelectVertexShader_0, () );*/\
|
/*XB_MACRO(VOID, __stdcall, D3DDevice_SelectVertexShader_0, () );*/\
|
||||||
|
@ -8697,9 +8698,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_PersistDisplay)()
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
|
|
||||||
HRESULT hRet = D3D_OK;
|
LOG_INCOMPLETE();
|
||||||
|
|
||||||
LOG_UNIMPLEMENTED();
|
|
||||||
|
|
||||||
// TODO: This function simply saves a copy of the display to a surface and persists it in contiguous memory
|
// TODO: This function simply saves a copy of the display to a surface and persists it in contiguous memory
|
||||||
// This function, if ever required, can be implemented as the following
|
// This function, if ever required, can be implemented as the following
|
||||||
|
@ -8711,8 +8710,11 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_PersistDisplay)()
|
||||||
// 5. Use MmPersistContigousMemory to persist the surface data across reboot
|
// 5. Use MmPersistContigousMemory to persist the surface data across reboot
|
||||||
// 6. Call AvSetSavedDataAddress, passing the xbox surface data pointer
|
// 6. Call AvSetSavedDataAddress, passing the xbox surface data pointer
|
||||||
|
|
||||||
|
// Call the native Xbox function so that AvSetSavedDataAddress is called and the VMManager can know its correct address
|
||||||
return hRet;
|
if (XB_TRMP(D3DDevice_PersistDisplay)) {
|
||||||
|
return XB_TRMP(D3DDevice_PersistDisplay)();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace xboxkrnl
|
||||||
#include "devices\Xbox.h" // For g_SMBus, SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER
|
#include "devices\Xbox.h" // For g_SMBus, SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER
|
||||||
#include "devices\SMCDevice.h" // For SMC_COMMAND_SCRATCH
|
#include "devices\SMCDevice.h" // For SMC_COMMAND_SCRATCH
|
||||||
#include "common/util/strConverter.hpp" // for utf16_to_ascii
|
#include "common/util/strConverter.hpp" // for utf16_to_ascii
|
||||||
|
#include "core\kernel\memory-manager\VMManager.h"
|
||||||
|
|
||||||
#include <algorithm> // for std::replace
|
#include <algorithm> // for std::replace
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
@ -567,6 +568,8 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
|
||||||
QuickReboot |= BOOT_QUICK_REBOOT;
|
QuickReboot |= BOOT_QUICK_REBOOT;
|
||||||
g_EmuShared->SetBootFlags(&QuickReboot);
|
g_EmuShared->SetBootFlags(&QuickReboot);
|
||||||
|
|
||||||
|
g_VMManager.SavePersistentMemory();
|
||||||
|
|
||||||
// Some titles (Xbox Dashboard and retail/demo discs) use ";" as a current directory path seperator
|
// Some titles (Xbox Dashboard and retail/demo discs) use ";" as a current directory path seperator
|
||||||
// This process is handled during initialization. No speical handling here required.
|
// This process is handled during initialization. No speical handling here required.
|
||||||
|
|
||||||
|
@ -587,11 +590,10 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
|
||||||
|
|
||||||
case ReturnFirmwareFatal:
|
case ReturnFirmwareFatal:
|
||||||
{
|
{
|
||||||
// NOTE: the error code is displayed by ExDisplayFatalError by other code paths so we need to change our corresponding
|
|
||||||
// paths if we want to emulate all the possible fatal errors
|
|
||||||
|
|
||||||
xboxkrnl::HalWriteSMBusValue(SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER, SMC_COMMAND_SCRATCH, 0, SMC_SCRATCH_DISPLAY_FATAL_ERROR);
|
xboxkrnl::HalWriteSMBusValue(SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER, SMC_COMMAND_SCRATCH, 0, SMC_SCRATCH_DISPLAY_FATAL_ERROR);
|
||||||
|
|
||||||
|
g_VMManager.SavePersistentMemory();
|
||||||
|
|
||||||
std::string szProcArgsBuffer;
|
std::string szProcArgsBuffer;
|
||||||
CxbxConvertArgToString(szProcArgsBuffer, szFilePath_CxbxReloaded_Exe, szFilePath_Xbe, CxbxKrnl_hEmuParent, CxbxKrnl_DebugMode, CxbxKrnl_DebugFileName.c_str());
|
CxbxConvertArgToString(szProcArgsBuffer, szFilePath_CxbxReloaded_Exe, szFilePath_Xbe, CxbxKrnl_hEmuParent, CxbxKrnl_DebugMode, CxbxKrnl_DebugFileName.c_str());
|
||||||
|
|
||||||
|
@ -610,7 +612,7 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuShared::Cleanup();
|
EmuShared::Cleanup();
|
||||||
ExitProcess(EXIT_SUCCESS);
|
TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -53,8 +53,6 @@ namespace NtDll
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * 0x0066 - MmGlobalData
|
// * 0x0066 - MmGlobalData
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// ergo720: a couple of these could be implemented, but most cannot. However, I wouldn't bother with these variables
|
|
||||||
// since they are just exported but never used by the kernel
|
|
||||||
XBSYSAPI EXPORTNUM(102) xboxkrnl::PVOID xboxkrnl::MmGlobalData[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
XBSYSAPI EXPORTNUM(102) xboxkrnl::PVOID xboxkrnl::MmGlobalData[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -104,7 +102,7 @@ XBSYSAPI EXPORTNUM(166) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
|
||||||
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
|
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
PVOID pRet = (PVOID)g_VMManager.AllocateContiguous(NumberOfBytes, LowestAcceptableAddress, HighestAcceptableAddress, Alignment, ProtectionType);
|
PVOID pRet = (PVOID)g_VMManager.AllocateContiguousMemory(NumberOfBytes, LowestAcceptableAddress, HighestAcceptableAddress, Alignment, ProtectionType);
|
||||||
|
|
||||||
RETURN(pRet);
|
RETURN(pRet);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +204,7 @@ XBSYSAPI EXPORTNUM(171) xboxkrnl::VOID NTAPI xboxkrnl::MmFreeContiguousMemory
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG(BaseAddress);
|
LOG_FUNC_ONE_ARG(BaseAddress);
|
||||||
|
|
||||||
g_VMManager.DeallocateContiguous((VAddr)BaseAddress);
|
g_VMManager.DeallocateContiguousMemory((VAddr)BaseAddress);
|
||||||
|
|
||||||
// TODO -oDxbx: Sokoban crashes after this, at reset time (press Black + White to hit this).
|
// TODO -oDxbx: Sokoban crashes after this, at reset time (press Black + White to hit this).
|
||||||
// Tracing in assembly shows the crash takes place quite a while further, so it's probably
|
// Tracing in assembly shows the crash takes place quite a while further, so it's probably
|
||||||
|
@ -486,9 +484,6 @@ XBSYSAPI EXPORTNUM(374) xboxkrnl::PVOID NTAPI xboxkrnl::MmDbgAllocateMemory
|
||||||
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, Protect)
|
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, Protect)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// This should only be called by debug xbe's
|
|
||||||
assert(g_bIsDebug);
|
|
||||||
|
|
||||||
PVOID addr = (PVOID)g_VMManager.AllocateSystemMemory(DebuggerType, Protect, NumberOfBytes, false);
|
PVOID addr = (PVOID)g_VMManager.AllocateSystemMemory(DebuggerType, Protect, NumberOfBytes, false);
|
||||||
if (addr) { RtlFillMemoryUlong((void*)addr, ROUND_UP_4K(NumberOfBytes), 0); } // debugger pages are zeroed
|
if (addr) { RtlFillMemoryUlong((void*)addr, ROUND_UP_4K(NumberOfBytes), 0); } // debugger pages are zeroed
|
||||||
|
|
||||||
|
@ -509,9 +504,6 @@ XBSYSAPI EXPORTNUM(375) xboxkrnl::ULONG NTAPI xboxkrnl::MmDbgFreeMemory
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// This should only be called by debug xbe's
|
|
||||||
assert(g_bIsDebug);
|
|
||||||
|
|
||||||
ULONG FreedPagesNumber = g_VMManager.DeallocateSystemMemory(DebuggerType, (VAddr)BaseAddress, NumberOfBytes);
|
ULONG FreedPagesNumber = g_VMManager.DeallocateSystemMemory(DebuggerType, (VAddr)BaseAddress, NumberOfBytes);
|
||||||
|
|
||||||
RETURN(FreedPagesNumber);
|
RETURN(FreedPagesNumber);
|
||||||
|
@ -524,9 +516,6 @@ XBSYSAPI EXPORTNUM(376) xboxkrnl::ULONG NTAPI xboxkrnl::MmDbgQueryAvailablePages
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
|
|
||||||
// This should only be called by debug xbe's
|
|
||||||
assert(g_bIsDebug);
|
|
||||||
|
|
||||||
ULONG FreeDebuggerPageNumber = g_VMManager.QueryNumberOfFreeDebuggerPages();
|
ULONG FreeDebuggerPageNumber = g_VMManager.QueryNumberOfFreeDebuggerPages();
|
||||||
|
|
||||||
RETURN(FreeDebuggerPageNumber);
|
RETURN(FreeDebuggerPageNumber);
|
||||||
|
@ -546,9 +535,6 @@ XBSYSAPI EXPORTNUM(377) xboxkrnl::VOID NTAPI xboxkrnl::MmDbgReleaseAddress
|
||||||
LOG_FUNC_ARG(Opaque)
|
LOG_FUNC_ARG(Opaque)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// This should only be called by debug xbe's
|
|
||||||
assert(g_bIsDebug);
|
|
||||||
|
|
||||||
g_VMManager.DbgTestPte((VAddr)VirtualAddress, (PMMPTE)Opaque, false);
|
g_VMManager.DbgTestPte((VAddr)VirtualAddress, (PMMPTE)Opaque, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,9 +552,6 @@ XBSYSAPI EXPORTNUM(378) xboxkrnl::PVOID NTAPI xboxkrnl::MmDbgWriteCheck
|
||||||
LOG_FUNC_ARG(Opaque)
|
LOG_FUNC_ARG(Opaque)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// This should only be called by debug xbe's
|
|
||||||
assert(g_bIsDebug);
|
|
||||||
|
|
||||||
PVOID addr = (PVOID)g_VMManager.DbgTestPte((VAddr)VirtualAddress, (PMMPTE)Opaque, true);
|
PVOID addr = (PVOID)g_VMManager.DbgTestPte((VAddr)VirtualAddress, (PMMPTE)Opaque, true);
|
||||||
|
|
||||||
RETURN(addr);
|
RETURN(addr);
|
||||||
|
|
|
@ -88,8 +88,6 @@ static std::vector<HANDLE> g_hThreads;
|
||||||
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
||||||
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
|
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
|
||||||
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
||||||
char szFilePath_memory_bin[MAX_PATH] = { 0 };
|
|
||||||
char szFilePath_page_tables[MAX_PATH] = { 0 };
|
|
||||||
char szFilePath_Xbe[MAX_PATH*2] = { 0 }; // NOTE: LAUNCH_DATA_HEADER's szLaunchPath is MAX_PATH*2 = 520
|
char szFilePath_Xbe[MAX_PATH*2] = { 0 }; // NOTE: LAUNCH_DATA_HEADER's szLaunchPath is MAX_PATH*2 = 520
|
||||||
|
|
||||||
std::string CxbxBasePath;
|
std::string CxbxBasePath;
|
||||||
|
@ -290,209 +288,6 @@ std::string CxbxGetLastErrorString(char * lpszFunction)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|
||||||
{
|
|
||||||
// First, try to open an existing memory.bin file :
|
|
||||||
HANDLE hFile = CreateFile(szFilePath_memory_bin,
|
|
||||||
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
/* lpSecurityAttributes */nullptr,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
|
|
||||||
/* hTemplateFile */nullptr);
|
|
||||||
|
|
||||||
bool NeedsInitialization = (hFile == INVALID_HANDLE_VALUE);
|
|
||||||
if (NeedsInitialization)
|
|
||||||
{
|
|
||||||
// If the memory.bin file doesn't exist yet, create it :
|
|
||||||
hFile = CreateFile(szFilePath_memory_bin,
|
|
||||||
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
/* lpSecurityAttributes */nullptr,
|
|
||||||
OPEN_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
|
|
||||||
/* hTemplateFile */nullptr);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : Couldn't create memory.bin file!\n", __func__);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure memory.bin is at least 128 MB in size
|
|
||||||
SetFilePointer(hFile, CHIHIRO_MEMORY_SIZE, nullptr, FILE_BEGIN);
|
|
||||||
SetEndOfFile(hFile);
|
|
||||||
|
|
||||||
HANDLE hFileMapping = CreateFileMapping(
|
|
||||||
hFile,
|
|
||||||
/* lpFileMappingAttributes */nullptr,
|
|
||||||
PAGE_EXECUTE_READWRITE,
|
|
||||||
/* dwMaximumSizeHigh */0,
|
|
||||||
/* dwMaximumSizeLow */CHIHIRO_MEMORY_SIZE,
|
|
||||||
/**/nullptr);
|
|
||||||
if (hFileMapping == NULL)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : Couldn't create contiguous memory.bin file mapping!\n", __func__);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LARGE_INTEGER len_li;
|
|
||||||
GetFileSizeEx(hFile, &len_li);
|
|
||||||
unsigned int FileSize = len_li.u.LowPart;
|
|
||||||
if (FileSize != CHIHIRO_MEMORY_SIZE)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : memory.bin file is not 128 MiB large!\n", __func__);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CXBX_LOADER
|
|
||||||
// TODO : Use ReserveMemoryRange / UnreserveMemoryRange(Mem??) where appropriate
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Map memory.bin contents into memory :
|
|
||||||
void *memory = (void *)MapViewOfFileEx(
|
|
||||||
hFileMapping,
|
|
||||||
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
|
||||||
/* dwFileOffsetHigh */0,
|
|
||||||
/* dwFileOffsetLow */0,
|
|
||||||
CHIHIRO_CONTIGUOUS_MEMORY_SIZE,
|
|
||||||
(void *)CONTIGUOUS_MEMORY_BASE);
|
|
||||||
if (memory != (void *)CONTIGUOUS_MEMORY_BASE)
|
|
||||||
{
|
|
||||||
if (memory)
|
|
||||||
UnmapViewOfFile(memory);
|
|
||||||
|
|
||||||
CxbxKrnlCleanup("%s: Couldn't map contiguous memory.bin to 0x80000000!", __func__);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Mapped %d MiB of Xbox contiguous memory at 0x%.8X to 0x%.8X",
|
|
||||||
CHIHIRO_CONTIGUOUS_MEMORY_SIZE / ONE_MB, CONTIGUOUS_MEMORY_BASE, CONTIGUOUS_MEMORY_BASE + CHIHIRO_CONTIGUOUS_MEMORY_SIZE - 1);
|
|
||||||
|
|
||||||
if (NeedsInitialization)
|
|
||||||
{
|
|
||||||
memset(memory, 0, CHIHIRO_CONTIGUOUS_MEMORY_SIZE);
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Initialized contiguous memory");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Loaded contiguous memory.bin");
|
|
||||||
|
|
||||||
size_t tiledMemorySize = XBOX_WRITE_COMBINED_SIZE;
|
|
||||||
if (g_bIsWine) {
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Wine detected: Using 64MB Tiled Memory Size");
|
|
||||||
// TODO: Figure out why Wine needs this and Windows doesn't.
|
|
||||||
// Perhaps it's a Wine bug, or perhaps Wine reserves this memory for it's own usage?
|
|
||||||
tiledMemorySize = XBOX_WRITE_COMBINED_SIZE / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map memory.bin contents into tiled memory too :
|
|
||||||
void *tiled_memory = (void *)MapViewOfFileEx(
|
|
||||||
hFileMapping,
|
|
||||||
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
||||||
/* dwFileOffsetHigh */0,
|
|
||||||
/* dwFileOffsetLow */0,
|
|
||||||
tiledMemorySize,
|
|
||||||
(void *)XBOX_WRITE_COMBINED_BASE);
|
|
||||||
|
|
||||||
if (tiled_memory != (void *)XBOX_WRITE_COMBINED_BASE)
|
|
||||||
{
|
|
||||||
if (tiled_memory)
|
|
||||||
UnmapViewOfFile(tiled_memory);
|
|
||||||
|
|
||||||
CxbxKrnlCleanup("%s: Couldn't map contiguous memory.bin into tiled memory at 0xF0000000!", __func__);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Mapped contiguous memory to Xbox tiled memory at 0x%.8X to 0x%.8X",
|
|
||||||
XBOX_WRITE_COMBINED_BASE, XBOX_WRITE_COMBINED_BASE + tiledMemorySize - 1);
|
|
||||||
|
|
||||||
|
|
||||||
return hFileMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE CxbxRestorePageTablesMemory(char* szFilePath_page_tables)
|
|
||||||
{
|
|
||||||
// First, try to open an existing PageTables.bin file :
|
|
||||||
HANDLE hFile = CreateFile(szFilePath_page_tables,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
/* lpSecurityAttributes */nullptr,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
|
|
||||||
/* hTemplateFile */nullptr);
|
|
||||||
|
|
||||||
bool NeedsInitialization = (hFile == INVALID_HANDLE_VALUE);
|
|
||||||
if (NeedsInitialization)
|
|
||||||
{
|
|
||||||
// If the PageTables.bin file doesn't exist yet, create it :
|
|
||||||
hFile = CreateFile(szFilePath_page_tables,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
/* lpSecurityAttributes */nullptr,
|
|
||||||
OPEN_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
|
|
||||||
/* hTemplateFile */nullptr);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : Couldn't create PageTables.bin file!\n", __func__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure PageTables.bin is at least 4 MB in size
|
|
||||||
SetFilePointer(hFile, PAGE_TABLES_SIZE, nullptr, FILE_BEGIN);
|
|
||||||
SetEndOfFile(hFile);
|
|
||||||
|
|
||||||
HANDLE hFileMapping = CreateFileMapping(
|
|
||||||
hFile,
|
|
||||||
/* lpFileMappingAttributes */nullptr,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
/* dwMaximumSizeHigh */0,
|
|
||||||
/* dwMaximumSizeLow */PAGE_TABLES_SIZE,
|
|
||||||
/**/nullptr);
|
|
||||||
if (hFileMapping == NULL)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : Couldn't create PageTables.bin file mapping!\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
LARGE_INTEGER len_li;
|
|
||||||
GetFileSizeEx(hFile, &len_li);
|
|
||||||
unsigned int FileSize = len_li.u.LowPart;
|
|
||||||
if (FileSize != PAGE_TABLES_SIZE)
|
|
||||||
{
|
|
||||||
CxbxKrnlCleanup("%s : PageTables.bin file is not 4 MiB large!\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map PageTables.bin contents into memory :
|
|
||||||
void *memory = (void *)MapViewOfFileEx(
|
|
||||||
hFileMapping,
|
|
||||||
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
||||||
/* dwFileOffsetHigh */0,
|
|
||||||
/* dwFileOffsetLow */0,
|
|
||||||
4 * ONE_MB,
|
|
||||||
(void *)PAGE_TABLES_BASE);
|
|
||||||
if (memory != (void *)PAGE_TABLES_BASE)
|
|
||||||
{
|
|
||||||
if (memory)
|
|
||||||
UnmapViewOfFile(memory);
|
|
||||||
|
|
||||||
CxbxKrnlCleanup("%s: Couldn't map PageTables.bin to 0xC0000000!", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Mapped %d MiB of Xbox page tables memory at 0x%.8X to 0x%.8X",
|
|
||||||
4, PAGE_TABLES_BASE, PAGE_TABLES_END);
|
|
||||||
|
|
||||||
if (NeedsInitialization)
|
|
||||||
{
|
|
||||||
memset(memory, 0, 4 * ONE_MB);
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Initialized page tables memory");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EmuLogInit(LOG_LEVEL::INFO, "Loaded PageTables.bin");
|
|
||||||
|
|
||||||
return hFileMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma optimize("", off)
|
#pragma optimize("", off)
|
||||||
|
|
||||||
int CxbxMessageBox(const char* msg, UINT uType, HWND hWnd)
|
int CxbxMessageBox(const char* msg, UINT uType, HWND hWnd)
|
||||||
|
@ -954,7 +749,7 @@ bool HandleFirstLaunch()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CxbxKrnlMain(int argc, char* argv[])
|
void CxbxKrnlMain(int argc, char* argv[], uint32_t blocks_reserved[384])
|
||||||
{
|
{
|
||||||
// NOTE: This is designated for standalone kernel mode launch without GUI
|
// NOTE: This is designated for standalone kernel mode launch without GUI
|
||||||
if (g_Settings != nullptr) {
|
if (g_Settings != nullptr) {
|
||||||
|
@ -1168,13 +963,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CXBX_LOADER
|
|
||||||
if (!VerifyAddressRanges(SYSTEM_XBOX)) {
|
|
||||||
CxbxPopupMessage("Cxbx-Reloaded hasn't got access to all required address ranges");
|
|
||||||
return; // TODO : Halt(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create a safe copy of the complete EXE header:
|
// Create a safe copy of the complete EXE header:
|
||||||
DWORD ExeHeaderSize = ExeOptionalHeader->SizeOfHeaders; // Should end up as 0x400
|
DWORD ExeHeaderSize = ExeOptionalHeader->SizeOfHeaders; // Should end up as 0x400
|
||||||
NewDosHeader = (PIMAGE_DOS_HEADER)VirtualAlloc(nullptr, ExeHeaderSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
NewDosHeader = (PIMAGE_DOS_HEADER)VirtualAlloc(nullptr, ExeHeaderSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
@ -1223,9 +1011,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
||||||
RestoreExeImageHeader();
|
RestoreExeImageHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE hMemoryBin = CxbxRestoreContiguousMemory(szFilePath_memory_bin);
|
|
||||||
HANDLE hPageTables = CxbxRestorePageTablesMemory(szFilePath_page_tables);
|
|
||||||
|
|
||||||
// Load Per-Xbe Keys from the Cxbx-Reloaded AppData directory
|
// Load Per-Xbe Keys from the Cxbx-Reloaded AppData directory
|
||||||
LoadXboxKeys(szFolder_CxbxReloadedData);
|
LoadXboxKeys(szFolder_CxbxReloadedData);
|
||||||
|
|
||||||
|
@ -1326,7 +1111,7 @@ void CxbxKrnlMain(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Initialize the virtual manager
|
// Initialize the virtual manager
|
||||||
g_VMManager.Initialize(hMemoryBin, hPageTables, BootFlags);
|
g_VMManager.Initialize(SYSTEM_XBOX, BootFlags, blocks_reserved);
|
||||||
|
|
||||||
// Commit the memory used by the xbe header
|
// Commit the memory used by the xbe header
|
||||||
size_t HeaderSize = CxbxKrnl_Xbe->m_Header.dwSizeofHeaders;
|
size_t HeaderSize = CxbxKrnl_Xbe->m_Header.dwSizeofHeaders;
|
||||||
|
@ -1788,8 +1573,6 @@ void CxbxInitFilePaths()
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData);
|
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData);
|
||||||
snprintf(szFilePath_memory_bin, MAX_PATH, "%s\\memory.bin", szFolder_CxbxReloadedData);
|
|
||||||
snprintf(szFilePath_page_tables, MAX_PATH, "%s\\PageTables.bin", szFolder_CxbxReloadedData);
|
|
||||||
|
|
||||||
GetModuleFileName(GetModuleHandle(nullptr), szFilePath_CxbxReloaded_Exe, MAX_PATH);
|
GetModuleFileName(GetModuleHandle(nullptr), szFilePath_CxbxReloaded_Exe, MAX_PATH);
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ extern "C" {
|
||||||
// fit in 51 MB. If we ever encounter an even larger XBE, this
|
// fit in 51 MB. If we ever encounter an even larger XBE, this
|
||||||
// value will have to be increased likewise (maybe up to 64 MB
|
// value will have to be increased likewise (maybe up to 64 MB
|
||||||
// for XBOX_MEMORY_SIZE or even 128 MB for CHIHIRO_MEMORY_SIZE).
|
// for XBOX_MEMORY_SIZE or even 128 MB for CHIHIRO_MEMORY_SIZE).
|
||||||
#define XBE_MAX_VA (64 * ONE_MB)
|
#define XBE_MAX_VA (128 * ONE_MB)
|
||||||
|
|
||||||
/*! base address of Cxbx host executable, see Cxbx project options, Linker, Advanced, Base Address */
|
/*! base address of Cxbx host executable, see Cxbx project options, Linker, Advanced, Base Address */
|
||||||
#define CXBX_BASE_ADDR XBE_IMAGE_BASE
|
#define CXBX_BASE_ADDR XBE_IMAGE_BASE
|
||||||
|
@ -235,7 +235,7 @@ bool CreateSettings();
|
||||||
bool HandleFirstLaunch();
|
bool HandleFirstLaunch();
|
||||||
|
|
||||||
/*! Cxbx Kernel Entry Point */
|
/*! Cxbx Kernel Entry Point */
|
||||||
void CxbxKrnlMain(int argc, char* argv[]);
|
void CxbxKrnlMain(int argc, char* argv[], uint32_t blocks_reserved[384]);
|
||||||
|
|
||||||
/*! initialize emulation */
|
/*! initialize emulation */
|
||||||
__declspec(noreturn) void CxbxKrnlInit(void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, const char *szDebugFilename, Xbe::Header *XbeHeader, uint32_t XbeHeaderSize, void (*Entry)(), int BootFlags);
|
__declspec(noreturn) void CxbxKrnlInit(void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, const char *szDebugFilename, Xbe::Header *XbeHeader, uint32_t XbeHeaderSize, void (*Entry)(), int BootFlags);
|
||||||
|
|
|
@ -73,13 +73,7 @@ void PhysicalMemory::InitializePageDirectory()
|
||||||
TempPte.Default += LARGE_PAGE_SIZE; // increase PFN
|
TempPte.Default += LARGE_PAGE_SIZE; // increase PFN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: map memory for the file system cache?
|
||||||
// NOTE: we don't need to unmap the rest of the system physical region because that mapping is done by the 2BL
|
|
||||||
// on the Xbox, which is not present here on Cxbx-Reloaded
|
|
||||||
|
|
||||||
// Here we should also reserve some system pte's for the file system cache. However, the implementation of the kernel
|
|
||||||
// file cache functions is basically non-existent at the moment and relies on ExAllocatePoolWithTag, which is not
|
|
||||||
// correctly implemented. So, for now, we keep on ignoring this allocation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalMemory::WritePfn(PFN pfn_start, PFN pfn_end, PMMPTE pPte, PageType BusyType, bool bZero)
|
void PhysicalMemory::WritePfn(PFN pfn_start, PFN pfn_end, PMMPTE pPte, PageType BusyType, bool bZero)
|
||||||
|
@ -380,7 +374,7 @@ void PhysicalMemory::InsertFree(PFN start, PFN end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicalMemory::ConvertXboxToSystemPteProtection(DWORD perms, PMMPTE pPte)
|
bool PhysicalMemory::ConvertXboxToSystemPtePermissions(DWORD perms, PMMPTE pPte)
|
||||||
{
|
{
|
||||||
ULONG Mask = 0;
|
ULONG Mask = 0;
|
||||||
|
|
||||||
|
@ -437,7 +431,7 @@ bool PhysicalMemory::ConvertXboxToSystemPteProtection(DWORD perms, PMMPTE pPte)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicalMemory::ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte)
|
bool PhysicalMemory::ConvertXboxToPtePermissions(DWORD perms, PMMPTE pPte)
|
||||||
{
|
{
|
||||||
ULONG Mask = 0;
|
ULONG Mask = 0;
|
||||||
ULONG LowNibble;
|
ULONG LowNibble;
|
||||||
|
@ -504,7 +498,7 @@ bool PhysicalMemory::ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD PhysicalMemory::ConvertPteToXboxProtection(ULONG PteMask)
|
DWORD PhysicalMemory::ConvertPteToXboxPermissions(ULONG PteMask)
|
||||||
{
|
{
|
||||||
// This routine assumes that the pte has valid protection bits. If it doesn't, it can produce invalid
|
// This routine assumes that the pte has valid protection bits. If it doesn't, it can produce invalid
|
||||||
// access permissions
|
// access permissions
|
||||||
|
@ -528,7 +522,7 @@ DWORD PhysicalMemory::ConvertPteToXboxProtection(ULONG PteMask)
|
||||||
|
|
||||||
DWORD PhysicalMemory::PatchXboxPermissions(DWORD Perms)
|
DWORD PhysicalMemory::PatchXboxPermissions(DWORD Perms)
|
||||||
{
|
{
|
||||||
// Usage notes: this routine expects the permissions to be already sanitized by ConvertXboxToSystemPteProtection or
|
// Usage notes: this routine expects the permissions to be already sanitized by ConvertXboxToSystemPtePermissions or
|
||||||
// similar. If not, it can produce incorrect results
|
// similar. If not, it can produce incorrect results
|
||||||
|
|
||||||
// ergo720: this checks if the specified Xbox permission mask has the execute flag enabled. If not, it adds it. This is
|
// ergo720: this checks if the specified Xbox permission mask has the execute flag enabled. If not, it adds it. This is
|
||||||
|
@ -581,7 +575,7 @@ DWORD PhysicalMemory::PatchXboxPermissions(DWORD Perms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD PhysicalMemory::ConvertXboxToWinProtection(DWORD Perms)
|
DWORD PhysicalMemory::ConvertXboxToWinPermissions(DWORD Perms)
|
||||||
{
|
{
|
||||||
// This function assumes that the supplied permissions have been sanitized already
|
// This function assumes that the supplied permissions have been sanitized already
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// * If not, write to the Free Software Foundation, Inc.,
|
// * If not, write to the Free Software Foundation, Inc.,
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2018 ergo720
|
// * (c) 2017-2018-2019 ergo720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -52,13 +52,11 @@ typedef unsigned int PFN_COUNT;
|
||||||
typedef struct _FreeBlock
|
typedef struct _FreeBlock
|
||||||
{
|
{
|
||||||
PFN start; // starting page of the block
|
PFN start; // starting page of the block
|
||||||
PFN_COUNT size; // number of pages in the block (edges included)
|
PFN_COUNT size; // number of pages in the block
|
||||||
xboxkrnl::LIST_ENTRY ListEntry;
|
xboxkrnl::LIST_ENTRY ListEntry;
|
||||||
}FreeBlock, *PFreeBlock;
|
}FreeBlock, *PFreeBlock;
|
||||||
|
|
||||||
|
|
||||||
// NOTE: all the bit fields below can have endianess issues...
|
|
||||||
|
|
||||||
/* The Xbox PTE, modelled around the Intel 386 PTE specification */
|
/* The Xbox PTE, modelled around the Intel 386 PTE specification */
|
||||||
typedef struct _XBOX_PTE
|
typedef struct _XBOX_PTE
|
||||||
{
|
{
|
||||||
|
@ -79,36 +77,31 @@ typedef struct _XBOX_PTE
|
||||||
|
|
||||||
|
|
||||||
/* PTE as used by the memory manager */
|
/* PTE as used by the memory manager */
|
||||||
typedef struct _MMPTE
|
typedef union _MMPTE
|
||||||
{
|
{
|
||||||
union
|
ULONG Default;
|
||||||
{
|
XBOX_PTE Hardware;
|
||||||
ULONG Default;
|
}MMPTE, *PMMPTE;
|
||||||
XBOX_PTE Hardware;
|
|
||||||
};
|
|
||||||
} MMPTE, *PMMPTE;
|
|
||||||
|
|
||||||
|
|
||||||
/* PFN entry used by the memory manager */
|
/* PFN entry used by the memory manager */
|
||||||
typedef struct _XBOX_PFN {
|
typedef union _XBOX_PFN
|
||||||
union
|
{
|
||||||
{
|
ULONG Default;
|
||||||
ULONG Default;
|
struct {
|
||||||
struct {
|
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
ULONG Busy : 1; // If set, PFN is in use
|
||||||
ULONG Busy : 1; // If set, PFN is in use
|
ULONG Unused : 1;
|
||||||
ULONG Unused : 1;
|
ULONG PteIndex : 10; // Offset in the PT that maps the pte (it seems to be needed only for page relocations)
|
||||||
ULONG PteIndex : 10; // Offset in the PT that maps the pte (it seems to be needed only for page relocations)
|
ULONG BusyType : 4; // What the page is used for
|
||||||
ULONG BusyType : 4; // What the page is used for
|
} Busy;
|
||||||
} Busy;
|
struct {
|
||||||
struct {
|
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
ULONG Busy : 1; // If set, PFN is in use
|
||||||
ULONG Busy : 1; // If set, PFN is in use
|
ULONG PtesUsed : 11; // Number of used pte's in the PT pointed by the pde
|
||||||
ULONG PtesUsed : 11; // Number of used pte's in the PT pointed by the pde
|
ULONG BusyType : 4; // What the page is used for (must be VirtualPageTableType or SystemPageTableType)
|
||||||
ULONG BusyType : 4; // What the page is used for (must be VirtualPageTableType or SystemPageTableType)
|
} PTPageFrame;
|
||||||
} PTPageFrame;
|
}XBOX_PFN, *PXBOX_PFN;
|
||||||
};
|
|
||||||
} XBOX_PFN, *PXBOX_PFN;
|
|
||||||
|
|
||||||
|
|
||||||
/* enum describing the usage type of the memory pages */
|
/* enum describing the usage type of the memory pages */
|
||||||
|
@ -129,7 +122,7 @@ typedef enum _PageType
|
||||||
}PageType;
|
}PageType;
|
||||||
|
|
||||||
|
|
||||||
/* enum describing the memory layouts available on the Xbox */
|
/* enum describing the memory layouts the memory manager can use */
|
||||||
typedef enum _MmLayout
|
typedef enum _MmLayout
|
||||||
{
|
{
|
||||||
MmChihiro = 1,
|
MmChihiro = 1,
|
||||||
|
@ -173,17 +166,12 @@ typedef enum _MmLayout
|
||||||
#define IsPteOnPdeBoundary(Pte) (((ULONG_PTR)(Pte) & (PAGE_SIZE - 1)) == 0)
|
#define IsPteOnPdeBoundary(Pte) (((ULONG_PTR)(Pte) & (PAGE_SIZE - 1)) == 0)
|
||||||
#define WRITE_ZERO_PTE(pPte) ((pPte)->Default = 0)
|
#define WRITE_ZERO_PTE(pPte) ((pPte)->Default = 0)
|
||||||
#define WRITE_PTE(pPte, Pte) (*(pPte) = Pte)
|
#define WRITE_PTE(pPte, Pte) (*(pPte) = Pte)
|
||||||
// On real hardware, enabling only the cache disable bit would result in an effective caching type of USWC
|
|
||||||
// (uncacheable speculative write combining), so we set both to achieve it
|
|
||||||
#define DISABLE_CACHING(Pte) ((Pte).Hardware.CacheDisable = 1); ((Pte).Hardware.WriteThrough = 1)
|
#define DISABLE_CACHING(Pte) ((Pte).Hardware.CacheDisable = 1); ((Pte).Hardware.WriteThrough = 1)
|
||||||
#define SET_WRITE_COMBINE(Pte) ((Pte).Hardware.CacheDisable = 0); ((Pte).Hardware.WriteThrough = 1)
|
#define SET_WRITE_COMBINE(Pte) ((Pte).Hardware.CacheDisable = 0); ((Pte).Hardware.WriteThrough = 1)
|
||||||
#define ValidKernelPteBits (PTE_VALID_MASK | PTE_WRITE_MASK | PTE_DIRTY_MASK | PTE_ACCESS_MASK) // 0x63
|
#define ValidKernelPteBits (PTE_VALID_MASK | PTE_WRITE_MASK | PTE_DIRTY_MASK | PTE_ACCESS_MASK) // 0x63
|
||||||
#define ValidKernelPdeBits (PTE_VALID_MASK | PTE_WRITE_MASK | PTE_OWNER_MASK | PTE_DIRTY_MASK | PTE_ACCESS_MASK) // 0x67
|
#define ValidKernelPdeBits (PTE_VALID_MASK | PTE_WRITE_MASK | PTE_OWNER_MASK | PTE_DIRTY_MASK | PTE_ACCESS_MASK) // 0x67
|
||||||
// This returns the VAddr in the contiguous region
|
|
||||||
#define CONVERT_PFN_TO_CONTIGUOUS_PHYSICAL(Pfn) ((PCHAR)PHYSICAL_MAP_BASE + ((Pfn) << PAGE_SHIFT))
|
#define CONVERT_PFN_TO_CONTIGUOUS_PHYSICAL(Pfn) ((PCHAR)PHYSICAL_MAP_BASE + ((Pfn) << PAGE_SHIFT))
|
||||||
// This works with both PAddr and VAddr in the contiguous region
|
|
||||||
#define CONVERT_CONTIGUOUS_PHYSICAL_TO_PFN(Va) (((Va) & (BYTES_IN_PHYSICAL_MAP - 1)) >> PAGE_SHIFT)
|
#define CONVERT_CONTIGUOUS_PHYSICAL_TO_PFN(Va) (((Va) & (BYTES_IN_PHYSICAL_MAP - 1)) >> PAGE_SHIFT)
|
||||||
// This returns the address of the PFN entry for Xbox/Chihiro
|
|
||||||
#define XBOX_PFN_ELEMENT(pfn) (&((PXBOX_PFN)XBOX_PFN_ADDRESS)[pfn])
|
#define XBOX_PFN_ELEMENT(pfn) (&((PXBOX_PFN)XBOX_PFN_ADDRESS)[pfn])
|
||||||
#define CHIHIRO_PFN_ELEMENT(pfn) (&((PXBOX_PFN)CHIHIRO_PFN_ADDRESS)[pfn])
|
#define CHIHIRO_PFN_ELEMENT(pfn) (&((PXBOX_PFN)CHIHIRO_PFN_ADDRESS)[pfn])
|
||||||
|
|
||||||
|
@ -253,13 +241,13 @@ class PhysicalMemory
|
||||||
// release a contiguous number of pages
|
// release a contiguous number of pages
|
||||||
void InsertFree(PFN start, PFN end);
|
void InsertFree(PFN start, PFN end);
|
||||||
// convert from Xbox to the desired system pte protection (if possible) and return it
|
// convert from Xbox to the desired system pte protection (if possible) and return it
|
||||||
bool ConvertXboxToSystemPteProtection(DWORD perms, PMMPTE pPte);
|
bool ConvertXboxToSystemPtePermissions(DWORD perms, PMMPTE pPte);
|
||||||
// convert from Xbox to non-system pte protection (if possible) and return it
|
// convert from Xbox to non-system pte protection (if possible) and return it
|
||||||
bool ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte);
|
bool ConvertXboxToPtePermissions(DWORD perms, PMMPTE pPte);
|
||||||
// convert from pte permissions to the corresponding Xbox protection code
|
// convert from pte permissions to the corresponding Xbox protection code
|
||||||
DWORD ConvertPteToXboxProtection(ULONG PteMask);
|
DWORD ConvertPteToXboxPermissions(ULONG PteMask);
|
||||||
// convert from Xbox to Windows permissions
|
// convert from Xbox to Windows permissions
|
||||||
DWORD ConvertXboxToWinProtection(DWORD Perms);
|
DWORD ConvertXboxToWinPermissions(DWORD Perms);
|
||||||
// add execute rights if the permission mask doesn't include it
|
// add execute rights if the permission mask doesn't include it
|
||||||
DWORD PatchXboxPermissions(DWORD Perms);
|
DWORD PatchXboxPermissions(DWORD Perms);
|
||||||
// commit page tables (if necessary)
|
// commit page tables (if necessary)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@
|
||||||
// * If not, write to the Free Software Foundation, Inc.,
|
// * If not, write to the Free Software Foundation, Inc.,
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2018 ergo720
|
// * (c) 2017-2018-2019 ergo720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -28,6 +28,9 @@
|
||||||
#ifndef VMMANAGER_H
|
#ifndef VMMANAGER_H
|
||||||
#define VMMANAGER_H
|
#define VMMANAGER_H
|
||||||
|
|
||||||
|
#define SYSTEM_XBOX (1 << 1)
|
||||||
|
#define SYSTEM_DEVKIT (1 << 2)
|
||||||
|
#define SYSTEM_CHIHIRO (1 << 3)
|
||||||
|
|
||||||
#include "PhysicalMemory.h"
|
#include "PhysicalMemory.h"
|
||||||
|
|
||||||
|
@ -55,8 +58,6 @@ struct VirtualMemoryArea
|
||||||
VMAType type = FreeVma;
|
VMAType type = FreeVma;
|
||||||
// initial vma permissions of the allocation, only used by XbVirtualMemoryStatistics
|
// initial vma permissions of the allocation, only used by XbVirtualMemoryStatistics
|
||||||
DWORD permissions = XBOX_PAGE_NOACCESS;
|
DWORD permissions = XBOX_PAGE_NOACCESS;
|
||||||
// this allocation was served by VirtualAlloc
|
|
||||||
bool bFragmented = false;
|
|
||||||
// tests if this area can be merged to the right with 'next'
|
// tests if this area can be merged to the right with 'next'
|
||||||
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
|
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
|
||||||
};
|
};
|
||||||
|
@ -84,6 +85,15 @@ typedef enum _MemoryRegionType
|
||||||
}MemoryRegionType;
|
}MemoryRegionType;
|
||||||
|
|
||||||
|
|
||||||
|
/* struct used to save the persistent memory between reboots */
|
||||||
|
typedef struct _PersistedMemory
|
||||||
|
{
|
||||||
|
size_t NumOfPtes;
|
||||||
|
VAddr LaunchFrameAddresses[2];
|
||||||
|
uint32_t Data[];
|
||||||
|
}PersistedMemory;
|
||||||
|
|
||||||
|
|
||||||
/* VMManager class */
|
/* VMManager class */
|
||||||
class VMManager : public PhysicalMemory
|
class VMManager : public PhysicalMemory
|
||||||
{
|
{
|
||||||
|
@ -97,19 +107,9 @@ class VMManager : public PhysicalMemory
|
||||||
// process is killed with TerminateProcess and so it doesn't have a chance to perform a cleanup...
|
// process is killed with TerminateProcess and so it doesn't have a chance to perform a cleanup...
|
||||||
//DestroyMemoryRegions();
|
//DestroyMemoryRegions();
|
||||||
DeleteCriticalSection(&m_CriticalSection);
|
DeleteCriticalSection(&m_CriticalSection);
|
||||||
FlushViewOfFile((void*)CONTIGUOUS_MEMORY_BASE, CHIHIRO_MEMORY_SIZE);
|
|
||||||
FlushViewOfFile((void*)PAGE_TABLES_BASE, PAGE_TABLES_SIZE);
|
|
||||||
FlushFileBuffers(m_hContiguousFile);
|
|
||||||
FlushFileBuffers(m_hPTFile);
|
|
||||||
UnmapViewOfFile((void *)CONTIGUOUS_MEMORY_BASE);
|
|
||||||
UnmapViewOfFile((void *)PAGE_TABLES_BASE);
|
|
||||||
UnmapViewOfFile((void*)XBOX_WRITE_COMBINED_BASE);
|
|
||||||
VirtualFree((void*)PAGE_TABLES_BASE, 0, MEM_RELEASE);
|
|
||||||
CloseHandle(m_hContiguousFile);
|
|
||||||
CloseHandle(m_hPTFile);
|
|
||||||
}
|
}
|
||||||
// initializes the memory manager to the default configuration
|
// initializes the memory manager to the default configuration
|
||||||
void Initialize(HANDLE memory_view, HANDLE pagetables_view, int BootFlags);
|
void Initialize(int SystemType, int BootFlags, uint32_t blocks_reserved[384]);
|
||||||
// retrieves memory statistics
|
// retrieves memory statistics
|
||||||
void MemoryStatistics(xboxkrnl::PMM_STATISTICS memory_statistics);
|
void MemoryStatistics(xboxkrnl::PMM_STATISTICS memory_statistics);
|
||||||
// allocates memory in the user region
|
// allocates memory in the user region
|
||||||
|
@ -119,13 +119,13 @@ class VMManager : public PhysicalMemory
|
||||||
// allocates memory in the system region
|
// allocates memory in the system region
|
||||||
VAddr AllocateSystemMemory(PageType BusyType, DWORD Perms, size_t Size, bool bAddGuardPage);
|
VAddr AllocateSystemMemory(PageType BusyType, DWORD Perms, size_t Size, bool bAddGuardPage);
|
||||||
// allocates memory in the contiguous region
|
// allocates memory in the contiguous region
|
||||||
VAddr AllocateContiguous(size_t Size, PAddr LowestAddress, PAddr HighestAddress, ULONG Alignment, DWORD Perms);
|
VAddr AllocateContiguousMemory(size_t Size, PAddr LowestAddress, PAddr HighestAddress, ULONG Alignment, DWORD Perms);
|
||||||
// maps device memory in the system region
|
// maps device memory in the system region
|
||||||
VAddr MapDeviceMemory(PAddr Paddr, size_t Size, DWORD Perms);
|
VAddr MapDeviceMemory(PAddr Paddr, size_t Size, DWORD Perms);
|
||||||
// deallocates memory in the system region
|
// deallocates memory in the system region
|
||||||
PFN_COUNT DeallocateSystemMemory(PageType BusyType, VAddr addr, size_t Size);
|
PFN_COUNT DeallocateSystemMemory(PageType BusyType, VAddr addr, size_t Size);
|
||||||
// deallocates memory in the contiguous region
|
// deallocates memory in the contiguous region
|
||||||
void DeallocateContiguous(VAddr addr);
|
void DeallocateContiguousMemory(VAddr addr);
|
||||||
// unmaps device memory in the system region
|
// unmaps device memory in the system region
|
||||||
void UnmapDeviceMemory(VAddr addr, size_t Size);
|
void UnmapDeviceMemory(VAddr addr, size_t Size);
|
||||||
// deallocates memory in the user region
|
// deallocates memory in the user region
|
||||||
|
@ -158,43 +158,36 @@ class VMManager : public PhysicalMemory
|
||||||
xboxkrnl::NTSTATUS XbVirtualProtect(VAddr* addr, size_t* Size, DWORD* Protect);
|
xboxkrnl::NTSTATUS XbVirtualProtect(VAddr* addr, size_t* Size, DWORD* Protect);
|
||||||
// xbox implementation of NtQueryVirtualMemory
|
// xbox implementation of NtQueryVirtualMemory
|
||||||
xboxkrnl::NTSTATUS XbVirtualMemoryStatistics(VAddr addr, xboxkrnl::PMEMORY_BASIC_INFORMATION memory_statistics);
|
xboxkrnl::NTSTATUS XbVirtualMemoryStatistics(VAddr addr, xboxkrnl::PMEMORY_BASIC_INFORMATION memory_statistics);
|
||||||
|
// saves all persisted memory just before a quick reboot
|
||||||
|
void SavePersistentMemory();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// typedef of pointer to a member function mapping a memory block
|
|
||||||
typedef VAddr (VMManager::*MappingFn) (VAddr, size_t, size_t, DWORD, PFN);
|
|
||||||
// an array of structs used to track the free/allocated vma's in the various memory regions
|
// an array of structs used to track the free/allocated vma's in the various memory regions
|
||||||
MemoryRegion m_MemoryRegionArray[COUNTRegion];
|
MemoryRegion m_MemoryRegionArray[COUNTRegion];
|
||||||
// handle of the contiguous file mapping
|
|
||||||
HANDLE m_hContiguousFile = NULL;
|
|
||||||
// handle of the PT file mapping
|
|
||||||
HANDLE m_hPTFile = NULL;
|
|
||||||
// critical section lock to synchronize accesses
|
// critical section lock to synchronize accesses
|
||||||
CRITICAL_SECTION m_CriticalSection;
|
CRITICAL_SECTION m_CriticalSection;
|
||||||
// the allocation granularity of the host. Needed by MapViewOfFileEx and VirtualAlloc
|
// the allocation granularity of the host
|
||||||
DWORD m_AllocationGranularity = 0;
|
DWORD m_AllocationGranularity = 0;
|
||||||
// number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory
|
// number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory
|
||||||
size_t m_VirtualMemoryBytesReserved = 0;
|
size_t m_VirtualMemoryBytesReserved = 0;
|
||||||
|
// number of persisted ptes between quick reboots
|
||||||
|
size_t m_NumPersistentPtes = 0;
|
||||||
|
|
||||||
|
// same as AllocateContiguousMemory, but it allows to allocate beyond m_MaxContiguousPfn
|
||||||
// set up the pfn database
|
VAddr AllocateContiguousMemoryInternal(PFN_COUNT NumberOfPages, PFN LowestPfn, PFN HighestPfn, PFN PfnAlignment, DWORD Perms);
|
||||||
void InitializePfnDatabase();
|
// set up the system allocations
|
||||||
// set up the pfn database after a quick reboot
|
void InitializeSystemAllocations();
|
||||||
void ReinitializePfnDatabase();
|
|
||||||
// initializes a memory region struct
|
// initializes a memory region struct
|
||||||
void ConstructMemoryRegion(VAddr Start, size_t Size, MemoryRegionType Type);
|
void ConstructMemoryRegion(VAddr Start, size_t Size, MemoryRegionType Type);
|
||||||
// clears all memory region structs
|
// clears all memory region structs
|
||||||
void DestroyMemoryRegions();
|
void DestroyMemoryRegions();
|
||||||
// map a memory block with the supplied allocation routine
|
// map a memory block with the supplied allocation routine
|
||||||
VAddr MapMemoryBlock(MappingFn MappingRoutine, MemoryRegionType Type, PFN_COUNT PteNumber, PFN pfn, VAddr HighestAddress = 0);
|
VAddr MapMemoryBlock(MemoryRegionType Type, PFN_COUNT PteNumber, DWORD Permissions, bool b64Blocks, VAddr HighestAddress = 0);
|
||||||
// helper function which maps a block with VirtualAlloc
|
// helper function which allocates user memory with VirtualAlloc
|
||||||
VAddr MapBlockWithVirtualAlloc(VAddr StartingAddr, size_t Size, size_t VmaEnd, DWORD Unused, PFN Unused2);
|
VAddr MapHostMemory(VAddr StartingAddr, size_t Size, size_t VmaEnd, DWORD Permissions);
|
||||||
// helper function which reserves a block of virtual memory with VirtualAlloc
|
|
||||||
VAddr ReserveBlockWithVirtualAlloc(VAddr StartingAddr, size_t Size, size_t VmaEnd, DWORD Unused, PFN Unused2);
|
|
||||||
// helper function which maps a block with MapViewOfFileEx
|
|
||||||
VAddr MapBlockWithMapViewOfFileEx(VAddr StartingAddr, size_t ViewSize, size_t VmaEnd, DWORD OffsetLow, PFN pfn);
|
|
||||||
// constructs a vma
|
// constructs a vma
|
||||||
void ConstructVMA(VAddr Start, size_t Size, MemoryRegionType Type, VMAType VmaType, bool bFragFlag, DWORD Perms = XBOX_PAGE_NOACCESS);
|
void ConstructVMA(VAddr Start, size_t Size, MemoryRegionType Type, VMAType VmaType, DWORD Perms = XBOX_PAGE_NOACCESS);
|
||||||
// destructs a vma
|
// destructs a vma
|
||||||
void DestructVMA(VAddr addr, MemoryRegionType Type, size_t Size);
|
void DestructVMA(VAddr addr, MemoryRegionType Type, size_t Size);
|
||||||
// removes a vma block from the mapped memory
|
// removes a vma block from the mapped memory
|
||||||
|
@ -215,8 +208,6 @@ class VMManager : public PhysicalMemory
|
||||||
void UpdateMemoryPermissions(VAddr addr, size_t Size, DWORD Perms);
|
void UpdateMemoryPermissions(VAddr addr, size_t Size, DWORD Perms);
|
||||||
// restores persistent memory
|
// restores persistent memory
|
||||||
void RestorePersistentMemory();
|
void RestorePersistentMemory();
|
||||||
// restores a persistent allocation
|
|
||||||
void RestorePersistentAllocation(VAddr addr, PFN StartingPfn, PFN EndingPfn, PageType Type);
|
|
||||||
// acquires the critical section
|
// acquires the critical section
|
||||||
void Lock();
|
void Lock();
|
||||||
// releases the critical section
|
// releases the critical section
|
||||||
|
|
|
@ -120,7 +120,7 @@ CommandLineToArgvA(
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI Emulate(int system)
|
DWORD WINAPI Emulate(int system, uint32_t blocks_reserved[384])
|
||||||
{
|
{
|
||||||
FUNC_EXPORTS
|
FUNC_EXPORTS
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ DWORD WINAPI Emulate(int system)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CxbxKrnlMain(argc, argv);
|
CxbxKrnlMain(argc, argv, blocks_reserved);
|
||||||
|
|
||||||
LocalFree(argv);
|
LocalFree(argv);
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CXBX_LOADER
|
||||||
/*! verify Cxbx.exe is loaded to base address 0x00010000 */
|
/*! verify Cxbx.exe is loaded to base address 0x00010000 */
|
||||||
if (!VerifyBaseAddr()) {
|
if (!VerifyBaseAddr()) {
|
||||||
CxbxShowError("Cxbx.exe is not loaded to base address 0x00010000 (which is a requirement for Xbox emulation)");
|
CxbxShowError("Cxbx.exe is not loaded to base address 0x00010000 (which is a requirement for Xbox emulation)");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DWORD guiProcessID = 0;
|
DWORD guiProcessID = 0;
|
||||||
// TODO: Convert ALL __argc & __argv to use main(int argc, char** argv) method.
|
// TODO: Convert ALL __argc & __argv to use main(int argc, char** argv) method.
|
||||||
|
@ -74,9 +76,22 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bHasLoadArgument) {
|
if (bHasLoadArgument) {
|
||||||
|
#ifndef CXBX_LOADER
|
||||||
CxbxKrnlMain(__argc, __argv);
|
CxbxKrnlMain(__argc, __argv);
|
||||||
EmuShared::Cleanup();
|
EmuShared::Cleanup();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
#else
|
||||||
|
std::string szProcArgsBuffer;
|
||||||
|
for (int i = 0; i < __argc; i++) {
|
||||||
|
szProcArgsBuffer.append(__argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CxbxExec(szProcArgsBuffer, nullptr, false)) {
|
||||||
|
CxbxShowError("Could not launch Cxbx-R loader!");
|
||||||
|
EmuShared::Cleanup();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// If 2nd GUI executable is launched, load settings file for GUI for editable support.
|
// If 2nd GUI executable is launched, load settings file for GUI for editable support.
|
||||||
|
|
|
@ -65,6 +65,8 @@
|
||||||
|
|
||||||
static int gameLogoWidth, gameLogoHeight;
|
static int gameLogoWidth, gameLogoHeight;
|
||||||
static int splashLogoWidth, splashLogoHeight;
|
static int splashLogoWidth, splashLogoHeight;
|
||||||
|
static HANDLE hPersistedMemory = NULL;
|
||||||
|
static LPVOID PersistedMemoryAddr = nullptr;
|
||||||
|
|
||||||
bool g_SaveOnExit = true;
|
bool g_SaveOnExit = true;
|
||||||
|
|
||||||
|
@ -345,10 +347,27 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
pCMD->dwChildProcID = lParam; // lParam is process ID.
|
pCMD->dwChildProcID = lParam; // lParam is process ID.
|
||||||
std::thread(CrashMonitorWrapper, pCMD).detach();
|
std::thread(CrashMonitorWrapper, pCMD).detach();
|
||||||
|
|
||||||
|
|
||||||
g_EmuShared->SetIsEmulating(true); // NOTE: Putting in here raise to low or medium risk due to debugger will launch itself. (Current workaround)
|
g_EmuShared->SetIsEmulating(true); // NOTE: Putting in here raise to low or medium risk due to debugger will launch itself. (Current workaround)
|
||||||
g_EmuShared->SetIsReady(true);
|
g_EmuShared->SetIsReady(true);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ID_GUI_VM_PERSIST_MEM: {
|
||||||
|
if (lParam) {
|
||||||
|
hPersistedMemory = OpenFileMapping(FILE_MAP_READ, FALSE, "PersistentMemory");
|
||||||
|
assert(hPersistedMemory != NULL);
|
||||||
|
PersistedMemoryAddr = MapViewOfFile(hPersistedMemory, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
assert(PersistedMemoryAddr != nullptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UnmapViewOfFile(PersistedMemoryAddr);
|
||||||
|
CloseHandle(hPersistedMemory);
|
||||||
|
PersistedMemoryAddr = nullptr;
|
||||||
|
hPersistedMemory = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2224,6 +2243,8 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState /
|
||||||
|
|
||||||
char szExeFileName[MAX_PATH];
|
char szExeFileName[MAX_PATH];
|
||||||
GetModuleFileName(GetModuleHandle(nullptr), szExeFileName, MAX_PATH);
|
GetModuleFileName(GetModuleHandle(nullptr), szExeFileName, MAX_PATH);
|
||||||
|
PathRemoveFileSpec(szExeFileName);
|
||||||
|
PathAppend(szExeFileName, "\\cxbxr-ldr.exe");
|
||||||
|
|
||||||
bool AttachLocalDebugger = (LocalDebuggerState == debuggerOn);
|
bool AttachLocalDebugger = (LocalDebuggerState == debuggerOn);
|
||||||
g_EmuShared->SetDebuggingFlag(&AttachLocalDebugger);
|
g_EmuShared->SetDebuggingFlag(&AttachLocalDebugger);
|
||||||
|
@ -2320,6 +2341,12 @@ void WndMain::CrashMonitor(DWORD dwChildProcID)
|
||||||
g_EmuShared->GetBootFlags(&iBootFlags);
|
g_EmuShared->GetBootFlags(&iBootFlags);
|
||||||
|
|
||||||
if (!iBootFlags) {
|
if (!iBootFlags) {
|
||||||
|
if (hPersistedMemory != NULL) {
|
||||||
|
UnmapViewOfFile(PersistedMemoryAddr);
|
||||||
|
CloseHandle(hPersistedMemory);
|
||||||
|
PersistedMemoryAddr = nullptr;
|
||||||
|
hPersistedMemory = NULL;
|
||||||
|
}
|
||||||
if (dwExitCode == EXIT_SUCCESS) {// StopEmulation
|
if (dwExitCode == EXIT_SUCCESS) {// StopEmulation
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,8 @@
|
||||||
#define ID_GUI_STATUS_LLE_FLAGS 1097
|
#define ID_GUI_STATUS_LLE_FLAGS 1097
|
||||||
#define ID_GUI_STATUS_XBOX_LED_COLOUR 1098
|
#define ID_GUI_STATUS_XBOX_LED_COLOUR 1098
|
||||||
#define ID_GUI_STATUS_LOG_ENABLED 1099
|
#define ID_GUI_STATUS_LOG_ENABLED 1099
|
||||||
#define IDC_AC_MUTE_ON_UNFOCUS_DISABLE 1100
|
#define ID_GUI_VM_PERSIST_MEM 1100
|
||||||
|
#define IDC_AC_MUTE_ON_UNFOCUS_DISABLE 1101
|
||||||
#define IDC_XBOX_PORT_0 1158
|
#define IDC_XBOX_PORT_0 1158
|
||||||
#define IDC_XBOX_PORT_1 1166
|
#define IDC_XBOX_PORT_1 1166
|
||||||
#define IDC_XBOX_PORT_2 1174
|
#define IDC_XBOX_PORT_2 1174
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||||
// *
|
// *
|
||||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||||
|
// * (c) 2019 ego720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -79,24 +80,27 @@ unsigned char virtual_memory_placeholder[VM_PLACEHOLDER_SIZE] = { 0 }; // = { OP
|
||||||
// /ENTRY:"rawMain"
|
// /ENTRY:"rawMain"
|
||||||
|
|
||||||
|
|
||||||
void OutputMessage(const char *msg)
|
void OutputMessage(const char* msg)
|
||||||
{
|
{
|
||||||
OutputDebugStringA(msg); // Send message to debugger output too
|
if (msg != nullptr) {
|
||||||
|
OutputDebugStringA(msg); // Send message to debugger output too
|
||||||
|
|
||||||
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
DWORD nNumberOfCharsToWrite = 0;
|
DWORD nNumberOfCharsToWrite = 0;
|
||||||
while (msg[nNumberOfCharsToWrite]) nNumberOfCharsToWrite++; // poor-man's strlen()
|
while (msg[nNumberOfCharsToWrite]) nNumberOfCharsToWrite++; // poor-man's strlen()
|
||||||
|
|
||||||
// Detect output-redirection to a file
|
// Detect output-redirection to a file
|
||||||
DWORD ConsoleMode;
|
DWORD ConsoleMode;
|
||||||
if (!GetConsoleMode(hConsoleOutput, &ConsoleMode)) {
|
if (!GetConsoleMode(hConsoleOutput, &ConsoleMode)) {
|
||||||
// Note : assume the output file accepts ANSI encoded characters
|
// Note : assume the output file accepts ANSI encoded characters
|
||||||
DWORD NumberOfBytesWritten;
|
DWORD NumberOfBytesWritten;
|
||||||
WriteFile(hConsoleOutput, (const void *)msg, nNumberOfCharsToWrite, &NumberOfBytesWritten, /*lpOverlapped=*/NULL);
|
WriteFile(hConsoleOutput, (const void*)msg, nNumberOfCharsToWrite, &NumberOfBytesWritten, /*lpOverlapped=*/NULL);
|
||||||
} else {
|
}
|
||||||
// Write message to console output
|
else {
|
||||||
DWORD NumberOfCharsWritten;
|
// Write message to console output
|
||||||
WriteConsoleA(hConsoleOutput, (const void *)msg, nNumberOfCharsToWrite, &NumberOfCharsWritten, /*lpReserved=*/NULL);
|
DWORD NumberOfCharsWritten;
|
||||||
|
WriteConsoleA(hConsoleOutput, (const void*)msg, nNumberOfCharsToWrite, &NumberOfCharsWritten, /*lpReserved=*/NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +150,10 @@ DWORD CALLBACK rawMain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReserveAddressRanges(system)) {
|
// Marking this as static to avoid an implicit call to memset, which is not availble in the loader
|
||||||
|
static uint32_t SystemDevBlocksReserved[384];
|
||||||
|
|
||||||
|
if (!ReserveAddressRanges(system, SystemDevBlocksReserved)) {
|
||||||
// If we get here, emulation lacks important address ranges; Don't launch
|
// If we get here, emulation lacks important address ranges; Don't launch
|
||||||
OutputMessage("Required address range couldn't be reserved!\n");
|
OutputMessage("Required address range couldn't be reserved!\n");
|
||||||
return ERROR_NOT_ENOUGH_MEMORY;
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
@ -166,7 +173,7 @@ DWORD CALLBACK rawMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the main emulation function in our DLL
|
// Find the main emulation function in our DLL
|
||||||
typedef void (WINAPI *Emulate_t)(int);
|
typedef void (WINAPI *Emulate_t)(int, uint32_t[384]);
|
||||||
Emulate_t pfnEmulate = (Emulate_t)GetProcAddress(hEmulationDLL, "Emulate");
|
Emulate_t pfnEmulate = (Emulate_t)GetProcAddress(hEmulationDLL, "Emulate");
|
||||||
if (!pfnEmulate) {
|
if (!pfnEmulate) {
|
||||||
OutputMessage("Entrypoint not found!\n");
|
OutputMessage("Entrypoint not found!\n");
|
||||||
|
@ -175,7 +182,7 @@ DWORD CALLBACK rawMain()
|
||||||
|
|
||||||
// Call the main emulation function in our DLL, passing in the results
|
// Call the main emulation function in our DLL, passing in the results
|
||||||
// of the address range reservations
|
// of the address range reservations
|
||||||
pfnEmulate(system); // TODO : Pass along all data that we've gathered up until here (or rebuild it over there)
|
pfnEmulate(system, SystemDevBlocksReserved); // TODO : Pass along all data that we've gathered up until here (or rebuild it over there)
|
||||||
|
|
||||||
// Once emulation actually started, execution may never return here
|
// Once emulation actually started, execution may never return here
|
||||||
// because all code and data that have been used up until now are
|
// because all code and data that have been used up until now are
|
||||||
|
|
Loading…
Reference in New Issue