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.
|
||||
// *
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// * (c) 2019 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -71,7 +72,6 @@ const struct {
|
|||
#define SYSTEM_CHIHIRO (1 << 3)
|
||||
// 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)
|
||||
#ifdef DEBUG
|
||||
const char *Comment;
|
||||
|
@ -84,31 +84,26 @@ const struct {
|
|||
#endif
|
||||
// See http://xboxdevwiki.net/Memory
|
||||
// and http://xboxdevwiki.net/Boot_Process#Paging
|
||||
// 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(0x00000000, 0x07FFFFFF, MB(128), PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit)"),
|
||||
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64), PROT_XRW, SYSTEM_XBOX , "MemPhysical (Retail)"),
|
||||
RANGE_ENTRY(0x80000000, 0x87FFFFFF, MB(128), PROT_XRW, 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(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(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(0xFD000000, 0xFD6FFFFF, MB( 7), PROT_NAC, SYSTEM_ALL , "DeviceNV2A_a (GPU)"),
|
||||
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(0xFE800000, 0xFE87FFFF, KB(512), PROT_NAC, SYSTEM_ALL , "DeviceAPU"),
|
||||
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(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(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(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)"),
|
||||
*/
|
||||
// Entry : Start , End , Size , Protect , RangeFlags , Comment
|
||||
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(0x00010000, 0x07FFFFFF, MB(128) - KB(64), PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit)"),
|
||||
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64) , PROT_UNH, SYSTEM_XBOX , "MemPhysical (Retail)"),
|
||||
RANGE_ENTRY(0x80000000, 0x87FFFFFF, MB(128) , PROT_UNH, SYSTEM_128MB , "MemPhysical (Chihiro / DevKit)"),
|
||||
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(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 , "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(0xFD700000, 0xFD7FFFFF, MB( 1) , PROT_RW, SYSTEM_ALL , "MemNV2APRAMIN"),
|
||||
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(0xFEC00000, 0xFEC00FFF, KB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceAC97 (ACI)"),
|
||||
RANGE_ENTRY(0xFED00000, 0xFED00FFF, KB( 4) , PROT_NAC, SYSTEM_ALL , "DeviceUSB"),
|
||||
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(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(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"),
|
||||
#undef RANGE_ENTRY
|
||||
};
|
||||
|
||||
|
@ -119,3 +114,4 @@ extern bool VerifyWow64();
|
|||
|
||||
extern LPTSTR GetLastErrorString();
|
||||
extern void FreeLastErrorString(LPTSTR Error);
|
||||
extern void OutputMessage(const char* msg);
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef enum class _IPC_UPDATE_GUI {
|
|||
, XBOX_LED_COLOUR
|
||||
, LOG_ENABLED
|
||||
, KRNL_IS_READY
|
||||
, VM_PERSIST_MEM
|
||||
} IPC_UPDATE_GUI;
|
||||
|
||||
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.
|
||||
// *
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// * (c) 2019 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -30,35 +31,75 @@
|
|||
#include "AddressRanges.h"
|
||||
|
||||
// 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;
|
||||
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)
|
||||
Start += BLOCK_SIZE;
|
||||
Size -= BLOCK_SIZE;
|
||||
HadAnyFailure = true;
|
||||
}
|
||||
|
||||
// Reserve this range in 64 Kb block increments, so that during emulation
|
||||
// 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
|
||||
Start += BLOCK_SIZE;
|
||||
Size -= BLOCK_SIZE;
|
||||
const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection;
|
||||
bool NeedsReservationTracking = false;
|
||||
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
|
||||
|
@ -66,7 +107,7 @@ bool ReserveMemoryRange(int index)
|
|||
return !HadAnyFailure;
|
||||
}
|
||||
|
||||
bool ReserveAddressRanges(const int system) {
|
||||
bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]) {
|
||||
// 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
|
||||
|
@ -74,7 +115,7 @@ bool ReserveAddressRanges(const int system) {
|
|||
continue;
|
||||
|
||||
// Try to reserve each address range
|
||||
if (ReserveMemoryRange(i))
|
||||
if (ReserveMemoryRange(i, blocks_reserved))
|
||||
continue;
|
||||
|
||||
// Some ranges are allowed to fail reserving
|
||||
|
|
|
@ -26,4 +26,4 @@
|
|||
// ******************************************************************
|
||||
#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.
|
||||
// *
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// * (c) 2019 ego720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -51,13 +52,6 @@ bool VerifyAddressRange(int index)
|
|||
int Size = XboxAddressRanges[index].Size;
|
||||
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
|
||||
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
|
||||
// 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
|
||||
// to have been reserved like that too:
|
||||
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;
|
||||
bool Okay;
|
||||
while (Size > 0) {
|
||||
// Expected values
|
||||
PVOID AllocationBase = (PVOID)BaseAddress;
|
||||
|
@ -78,9 +73,9 @@ bool VerifyAddressRange(int index)
|
|||
DWORD State = MEM_RESERVE;
|
||||
DWORD Protect = 0;
|
||||
DWORD Type = MEM_PRIVATE;
|
||||
|
||||
#if 0
|
||||
// Allowed deviations
|
||||
if (XboxAddressRanges[index].Start == 0) {
|
||||
if (XboxAddressRanges[index].Start == 0x10000) {
|
||||
AllocationBase = (PVOID)0x10000;
|
||||
State = MEM_COMMIT;
|
||||
Type = MEM_IMAGE;
|
||||
|
@ -110,23 +105,58 @@ bool VerifyAddressRange(int index)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify each block
|
||||
bool 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);
|
||||
#endif
|
||||
if (BaseAddress == 0x80000000 || BaseAddress == 0xF0000000) {
|
||||
RegionSize = Size;
|
||||
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 == (BaseAddress == 0x80000000 ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE));
|
||||
if (Okay)
|
||||
Okay = (mbi.RegionSize == Size);
|
||||
if (Okay)
|
||||
Okay = (mbi.State == MEM_COMMIT);
|
||||
if (Okay)
|
||||
Okay = (mbi.Protect == mbi.AllocationProtect);
|
||||
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) {
|
||||
HadFailure = true;
|
||||
|
@ -154,9 +184,14 @@ bool VerifyAddressRange(int index)
|
|||
}
|
||||
}
|
||||
|
||||
// Handle the next region
|
||||
BaseAddress += RegionSize;
|
||||
Size -= RegionSize;
|
||||
if (BaseAddress == 0x80000000 || BaseAddress == 0xF0000000 || XboxAddressRanges[index].Start == 0x10000) {
|
||||
Size = 0;
|
||||
}
|
||||
else {
|
||||
// Handle the next region
|
||||
BaseAddress += RegionSize;
|
||||
Size -= RegionSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Safeguard against bounds overflow
|
||||
|
|
|
@ -80,7 +80,7 @@ class EmuShared : public Mutex
|
|||
// * Check if parent process is emulating title
|
||||
// ******************************************************************
|
||||
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
|
||||
|
@ -199,8 +199,7 @@ class EmuShared : public Mutex
|
|||
void GetLogModules(unsigned int *value)
|
||||
{
|
||||
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];
|
||||
}
|
||||
Unlock();
|
||||
|
@ -208,12 +207,11 @@ class EmuShared : public Mutex
|
|||
void SetLogModules(unsigned int *value)
|
||||
{
|
||||
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];
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * 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;
|
||||
break;
|
||||
|
||||
case IPC_UPDATE_GUI::VM_PERSIST_MEM:
|
||||
cmdParam = ID_GUI_VM_PERSIST_MEM;
|
||||
break;
|
||||
|
||||
default:
|
||||
cmdParam = 0;
|
||||
break;
|
||||
|
|
|
@ -291,6 +291,7 @@ g_EmuCDPD = {0};
|
|||
/*XB_MACRO(VOID, WINAPI, D3DDevice_LoadVertexShaderProgram, (CONST DWORD*, DWORD) );*/\
|
||||
/*XB_MACRO(VOID, __stdcall, D3DDevice_LoadVertexShader_0, () );*/\
|
||||
/*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(VOID, WINAPI, D3DDevice_SelectVertexShader, (DWORD, DWORD) );*/\
|
||||
/*XB_MACRO(VOID, __stdcall, D3DDevice_SelectVertexShader_0, () );*/\
|
||||
|
@ -8697,9 +8698,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_PersistDisplay)()
|
|||
{
|
||||
LOG_FUNC();
|
||||
|
||||
HRESULT hRet = D3D_OK;
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
LOG_INCOMPLETE();
|
||||
|
||||
// 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
|
||||
|
@ -8711,8 +8710,11 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_PersistDisplay)()
|
|||
// 5. Use MmPersistContigousMemory to persist the surface data across reboot
|
||||
// 6. Call AvSetSavedDataAddress, passing the xbox surface data pointer
|
||||
|
||||
|
||||
return hRet;
|
||||
// Call the native Xbox function so that AvSetSavedDataAddress is called and the VMManager can know its correct address
|
||||
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\SMCDevice.h" // For SMC_COMMAND_SCRATCH
|
||||
#include "common/util/strConverter.hpp" // for utf16_to_ascii
|
||||
#include "core\kernel\memory-manager\VMManager.h"
|
||||
|
||||
#include <algorithm> // for std::replace
|
||||
#include <locale>
|
||||
|
@ -567,6 +568,8 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
|
|||
QuickReboot |= BOOT_QUICK_REBOOT;
|
||||
g_EmuShared->SetBootFlags(&QuickReboot);
|
||||
|
||||
g_VMManager.SavePersistentMemory();
|
||||
|
||||
// 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.
|
||||
|
||||
|
@ -587,11 +590,10 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
|
|||
|
||||
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);
|
||||
|
||||
g_VMManager.SavePersistentMemory();
|
||||
|
||||
std::string szProcArgsBuffer;
|
||||
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();
|
||||
ExitProcess(EXIT_SUCCESS);
|
||||
TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -53,8 +53,6 @@ namespace NtDll
|
|||
// ******************************************************************
|
||||
// * 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 };
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -104,7 +102,7 @@ XBSYSAPI EXPORTNUM(166) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
|
|||
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
|
||||
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);
|
||||
}
|
||||
|
@ -206,7 +204,7 @@ XBSYSAPI EXPORTNUM(171) xboxkrnl::VOID NTAPI xboxkrnl::MmFreeContiguousMemory
|
|||
{
|
||||
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).
|
||||
// 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_END;
|
||||
|
||||
// This should only be called by debug xbe's
|
||||
assert(g_bIsDebug);
|
||||
|
||||
PVOID addr = (PVOID)g_VMManager.AllocateSystemMemory(DebuggerType, Protect, NumberOfBytes, false);
|
||||
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_END;
|
||||
|
||||
// This should only be called by debug xbe's
|
||||
assert(g_bIsDebug);
|
||||
|
||||
ULONG FreedPagesNumber = g_VMManager.DeallocateSystemMemory(DebuggerType, (VAddr)BaseAddress, NumberOfBytes);
|
||||
|
||||
RETURN(FreedPagesNumber);
|
||||
|
@ -524,9 +516,6 @@ XBSYSAPI EXPORTNUM(376) xboxkrnl::ULONG NTAPI xboxkrnl::MmDbgQueryAvailablePages
|
|||
{
|
||||
LOG_FUNC();
|
||||
|
||||
// This should only be called by debug xbe's
|
||||
assert(g_bIsDebug);
|
||||
|
||||
ULONG FreeDebuggerPageNumber = g_VMManager.QueryNumberOfFreeDebuggerPages();
|
||||
|
||||
RETURN(FreeDebuggerPageNumber);
|
||||
|
@ -546,9 +535,6 @@ XBSYSAPI EXPORTNUM(377) xboxkrnl::VOID NTAPI xboxkrnl::MmDbgReleaseAddress
|
|||
LOG_FUNC_ARG(Opaque)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// This should only be called by debug xbe's
|
||||
assert(g_bIsDebug);
|
||||
|
||||
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_END;
|
||||
|
||||
// This should only be called by debug xbe's
|
||||
assert(g_bIsDebug);
|
||||
|
||||
PVOID addr = (PVOID)g_VMManager.DbgTestPte((VAddr)VirtualAddress, (PMMPTE)Opaque, true);
|
||||
|
||||
RETURN(addr);
|
||||
|
|
|
@ -88,8 +88,6 @@ static std::vector<HANDLE> g_hThreads;
|
|||
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
||||
char szFolder_CxbxReloadedData[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
|
||||
|
||||
std::string CxbxBasePath;
|
||||
|
@ -290,209 +288,6 @@ std::string CxbxGetLastErrorString(char * lpszFunction)
|
|||
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)
|
||||
|
||||
int CxbxMessageBox(const char* msg, UINT uType, HWND hWnd)
|
||||
|
@ -954,7 +749,7 @@ bool HandleFirstLaunch()
|
|||
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
|
||||
if (g_Settings != nullptr) {
|
||||
|
@ -1168,13 +963,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
}
|
||||
#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:
|
||||
DWORD ExeHeaderSize = ExeOptionalHeader->SizeOfHeaders; // Should end up as 0x400
|
||||
NewDosHeader = (PIMAGE_DOS_HEADER)VirtualAlloc(nullptr, ExeHeaderSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
|
@ -1223,9 +1011,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
RestoreExeImageHeader();
|
||||
}
|
||||
|
||||
HANDLE hMemoryBin = CxbxRestoreContiguousMemory(szFilePath_memory_bin);
|
||||
HANDLE hPageTables = CxbxRestorePageTablesMemory(szFilePath_page_tables);
|
||||
|
||||
// Load Per-Xbe Keys from the Cxbx-Reloaded AppData directory
|
||||
LoadXboxKeys(szFolder_CxbxReloadedData);
|
||||
|
||||
|
@ -1326,7 +1111,7 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
}
|
||||
#endif
|
||||
// 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
|
||||
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_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);
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ extern "C" {
|
|||
// 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
|
||||
// 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 */
|
||||
#define CXBX_BASE_ADDR XBE_IMAGE_BASE
|
||||
|
@ -235,7 +235,7 @@ bool CreateSettings();
|
|||
bool HandleFirstLaunch();
|
||||
|
||||
/*! Cxbx Kernel Entry Point */
|
||||
void CxbxKrnlMain(int argc, char* argv[]);
|
||||
void CxbxKrnlMain(int argc, char* argv[], uint32_t blocks_reserved[384]);
|
||||
|
||||
/*! 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);
|
||||
|
|
|
@ -73,13 +73,7 @@ void PhysicalMemory::InitializePageDirectory()
|
|||
TempPte.Default += LARGE_PAGE_SIZE; // increase PFN
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// TODO: map memory for the file system cache?
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -437,7 +431,7 @@ bool PhysicalMemory::ConvertXboxToSystemPteProtection(DWORD perms, PMMPTE pPte)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool PhysicalMemory::ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte)
|
||||
bool PhysicalMemory::ConvertXboxToPtePermissions(DWORD perms, PMMPTE pPte)
|
||||
{
|
||||
ULONG Mask = 0;
|
||||
ULONG LowNibble;
|
||||
|
@ -504,7 +498,7 @@ bool PhysicalMemory::ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte)
|
|||
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
|
||||
// access permissions
|
||||
|
@ -528,7 +522,7 @@ DWORD PhysicalMemory::ConvertPteToXboxProtection(ULONG PteMask)
|
|||
|
||||
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
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017-2018 ergo720
|
||||
// * (c) 2017-2018-2019 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -52,13 +52,11 @@ typedef unsigned int PFN_COUNT;
|
|||
typedef struct _FreeBlock
|
||||
{
|
||||
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;
|
||||
}FreeBlock, *PFreeBlock;
|
||||
|
||||
|
||||
// NOTE: all the bit fields below can have endianess issues...
|
||||
|
||||
/* The Xbox PTE, modelled around the Intel 386 PTE specification */
|
||||
typedef struct _XBOX_PTE
|
||||
{
|
||||
|
@ -79,36 +77,31 @@ typedef struct _XBOX_PTE
|
|||
|
||||
|
||||
/* PTE as used by the memory manager */
|
||||
typedef struct _MMPTE
|
||||
typedef union _MMPTE
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG Default;
|
||||
XBOX_PTE Hardware;
|
||||
};
|
||||
} MMPTE, *PMMPTE;
|
||||
ULONG Default;
|
||||
XBOX_PTE Hardware;
|
||||
}MMPTE, *PMMPTE;
|
||||
|
||||
|
||||
/* PFN entry used by the memory manager */
|
||||
typedef struct _XBOX_PFN {
|
||||
union
|
||||
{
|
||||
ULONG Default;
|
||||
struct {
|
||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||
ULONG Busy : 1; // If set, PFN is in use
|
||||
ULONG Unused : 1;
|
||||
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
|
||||
} Busy;
|
||||
struct {
|
||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||
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 BusyType : 4; // What the page is used for (must be VirtualPageTableType or SystemPageTableType)
|
||||
} PTPageFrame;
|
||||
};
|
||||
} XBOX_PFN, *PXBOX_PFN;
|
||||
typedef union _XBOX_PFN
|
||||
{
|
||||
ULONG Default;
|
||||
struct {
|
||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||
ULONG Busy : 1; // If set, PFN is in use
|
||||
ULONG Unused : 1;
|
||||
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
|
||||
} Busy;
|
||||
struct {
|
||||
ULONG LockCount : 16; // Set to prevent page relocation. Used by MmLockUnlockPhysicalPage and others
|
||||
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 BusyType : 4; // What the page is used for (must be VirtualPageTableType or SystemPageTableType)
|
||||
} PTPageFrame;
|
||||
}XBOX_PFN, *PXBOX_PFN;
|
||||
|
||||
|
||||
/* enum describing the usage type of the memory pages */
|
||||
|
@ -129,7 +122,7 @@ typedef enum _PageType
|
|||
}PageType;
|
||||
|
||||
|
||||
/* enum describing the memory layouts available on the Xbox */
|
||||
/* enum describing the memory layouts the memory manager can use */
|
||||
typedef enum _MmLayout
|
||||
{
|
||||
MmChihiro = 1,
|
||||
|
@ -173,17 +166,12 @@ typedef enum _MmLayout
|
|||
#define IsPteOnPdeBoundary(Pte) (((ULONG_PTR)(Pte) & (PAGE_SIZE - 1)) == 0)
|
||||
#define WRITE_ZERO_PTE(pPte) ((pPte)->Default = 0)
|
||||
#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 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 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))
|
||||
// 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)
|
||||
// This returns the address of the PFN entry for Xbox/Chihiro
|
||||
#define XBOX_PFN_ELEMENT(pfn) (&((PXBOX_PFN)XBOX_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
|
||||
void InsertFree(PFN start, PFN end);
|
||||
// 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
|
||||
bool ConvertXboxToPteProtection(DWORD perms, PMMPTE pPte);
|
||||
bool ConvertXboxToPtePermissions(DWORD perms, PMMPTE pPte);
|
||||
// convert from pte permissions to the corresponding Xbox protection code
|
||||
DWORD ConvertPteToXboxProtection(ULONG PteMask);
|
||||
DWORD ConvertPteToXboxPermissions(ULONG PteMask);
|
||||
// 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
|
||||
DWORD PatchXboxPermissions(DWORD Perms);
|
||||
// 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.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017-2018 ergo720
|
||||
// * (c) 2017-2018-2019 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -28,6 +28,9 @@
|
|||
#ifndef VMMANAGER_H
|
||||
#define VMMANAGER_H
|
||||
|
||||
#define SYSTEM_XBOX (1 << 1)
|
||||
#define SYSTEM_DEVKIT (1 << 2)
|
||||
#define SYSTEM_CHIHIRO (1 << 3)
|
||||
|
||||
#include "PhysicalMemory.h"
|
||||
|
||||
|
@ -55,8 +58,6 @@ struct VirtualMemoryArea
|
|||
VMAType type = FreeVma;
|
||||
// initial vma permissions of the allocation, only used by XbVirtualMemoryStatistics
|
||||
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'
|
||||
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
|
||||
};
|
||||
|
@ -84,6 +85,15 @@ typedef enum _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 */
|
||||
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...
|
||||
//DestroyMemoryRegions();
|
||||
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
|
||||
void Initialize(HANDLE memory_view, HANDLE pagetables_view, int BootFlags);
|
||||
void Initialize(int SystemType, int BootFlags, uint32_t blocks_reserved[384]);
|
||||
// retrieves memory statistics
|
||||
void MemoryStatistics(xboxkrnl::PMM_STATISTICS memory_statistics);
|
||||
// allocates memory in the user region
|
||||
|
@ -119,13 +119,13 @@ class VMManager : public PhysicalMemory
|
|||
// allocates memory in the system region
|
||||
VAddr AllocateSystemMemory(PageType BusyType, DWORD Perms, size_t Size, bool bAddGuardPage);
|
||||
// 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
|
||||
VAddr MapDeviceMemory(PAddr Paddr, size_t Size, DWORD Perms);
|
||||
// deallocates memory in the system region
|
||||
PFN_COUNT DeallocateSystemMemory(PageType BusyType, VAddr addr, size_t Size);
|
||||
// deallocates memory in the contiguous region
|
||||
void DeallocateContiguous(VAddr addr);
|
||||
void DeallocateContiguousMemory(VAddr addr);
|
||||
// unmaps device memory in the system region
|
||||
void UnmapDeviceMemory(VAddr addr, size_t Size);
|
||||
// deallocates memory in the user region
|
||||
|
@ -158,43 +158,36 @@ class VMManager : public PhysicalMemory
|
|||
xboxkrnl::NTSTATUS XbVirtualProtect(VAddr* addr, size_t* Size, DWORD* Protect);
|
||||
// xbox implementation of NtQueryVirtualMemory
|
||||
xboxkrnl::NTSTATUS XbVirtualMemoryStatistics(VAddr addr, xboxkrnl::PMEMORY_BASIC_INFORMATION memory_statistics);
|
||||
// saves all persisted memory just before a quick reboot
|
||||
void SavePersistentMemory();
|
||||
|
||||
|
||||
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
|
||||
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 m_CriticalSection;
|
||||
// the allocation granularity of the host. Needed by MapViewOfFileEx and VirtualAlloc
|
||||
// the allocation granularity of the host
|
||||
DWORD m_AllocationGranularity = 0;
|
||||
// number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory
|
||||
size_t m_VirtualMemoryBytesReserved = 0;
|
||||
// number of persisted ptes between quick reboots
|
||||
size_t m_NumPersistentPtes = 0;
|
||||
|
||||
|
||||
// set up the pfn database
|
||||
void InitializePfnDatabase();
|
||||
// set up the pfn database after a quick reboot
|
||||
void ReinitializePfnDatabase();
|
||||
// same as AllocateContiguousMemory, but it allows to allocate beyond m_MaxContiguousPfn
|
||||
VAddr AllocateContiguousMemoryInternal(PFN_COUNT NumberOfPages, PFN LowestPfn, PFN HighestPfn, PFN PfnAlignment, DWORD Perms);
|
||||
// set up the system allocations
|
||||
void InitializeSystemAllocations();
|
||||
// initializes a memory region struct
|
||||
void ConstructMemoryRegion(VAddr Start, size_t Size, MemoryRegionType Type);
|
||||
// clears all memory region structs
|
||||
void DestroyMemoryRegions();
|
||||
// map a memory block with the supplied allocation routine
|
||||
VAddr MapMemoryBlock(MappingFn MappingRoutine, MemoryRegionType Type, PFN_COUNT PteNumber, PFN pfn, VAddr HighestAddress = 0);
|
||||
// helper function which maps a block with VirtualAlloc
|
||||
VAddr MapBlockWithVirtualAlloc(VAddr StartingAddr, size_t Size, size_t VmaEnd, DWORD Unused, PFN Unused2);
|
||||
// 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);
|
||||
VAddr MapMemoryBlock(MemoryRegionType Type, PFN_COUNT PteNumber, DWORD Permissions, bool b64Blocks, VAddr HighestAddress = 0);
|
||||
// helper function which allocates user memory with VirtualAlloc
|
||||
VAddr MapHostMemory(VAddr StartingAddr, size_t Size, size_t VmaEnd, DWORD Permissions);
|
||||
// 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
|
||||
void DestructVMA(VAddr addr, MemoryRegionType Type, size_t Size);
|
||||
// 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);
|
||||
// restores persistent memory
|
||||
void RestorePersistentMemory();
|
||||
// restores a persistent allocation
|
||||
void RestorePersistentAllocation(VAddr addr, PFN StartingPfn, PFN EndingPfn, PageType Type);
|
||||
// acquires the critical section
|
||||
void Lock();
|
||||
// releases the critical section
|
||||
|
|
|
@ -120,7 +120,7 @@ CommandLineToArgvA(
|
|||
return argv;
|
||||
}
|
||||
|
||||
DWORD WINAPI Emulate(int system)
|
||||
DWORD WINAPI Emulate(int system, uint32_t blocks_reserved[384])
|
||||
{
|
||||
FUNC_EXPORTS
|
||||
|
||||
|
@ -170,7 +170,7 @@ DWORD WINAPI Emulate(int system)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CxbxKrnlMain(argc, argv);
|
||||
CxbxKrnlMain(argc, argv, blocks_reserved);
|
||||
|
||||
LocalFree(argv);
|
||||
|
||||
|
|
|
@ -52,11 +52,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifndef CXBX_LOADER
|
||||
/*! verify Cxbx.exe is loaded to base address 0x00010000 */
|
||||
if (!VerifyBaseAddr()) {
|
||||
CxbxShowError("Cxbx.exe is not loaded to base address 0x00010000 (which is a requirement for Xbox emulation)");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
DWORD guiProcessID = 0;
|
||||
// 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) {
|
||||
#ifndef CXBX_LOADER
|
||||
CxbxKrnlMain(__argc, __argv);
|
||||
EmuShared::Cleanup();
|
||||
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.
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
|
||||
static int gameLogoWidth, gameLogoHeight;
|
||||
static int splashLogoWidth, splashLogoHeight;
|
||||
static HANDLE hPersistedMemory = NULL;
|
||||
static LPVOID PersistedMemoryAddr = nullptr;
|
||||
|
||||
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.
|
||||
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->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;
|
||||
|
@ -2224,6 +2243,8 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState /
|
|||
|
||||
char szExeFileName[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(nullptr), szExeFileName, MAX_PATH);
|
||||
PathRemoveFileSpec(szExeFileName);
|
||||
PathAppend(szExeFileName, "\\cxbxr-ldr.exe");
|
||||
|
||||
bool AttachLocalDebugger = (LocalDebuggerState == debuggerOn);
|
||||
g_EmuShared->SetDebuggingFlag(&AttachLocalDebugger);
|
||||
|
@ -2320,6 +2341,12 @@ void WndMain::CrashMonitor(DWORD dwChildProcID)
|
|||
g_EmuShared->GetBootFlags(&iBootFlags);
|
||||
|
||||
if (!iBootFlags) {
|
||||
if (hPersistedMemory != NULL) {
|
||||
UnmapViewOfFile(PersistedMemoryAddr);
|
||||
CloseHandle(hPersistedMemory);
|
||||
PersistedMemoryAddr = nullptr;
|
||||
hPersistedMemory = NULL;
|
||||
}
|
||||
if (dwExitCode == EXIT_SUCCESS) {// StopEmulation
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,8 @@
|
|||
#define ID_GUI_STATUS_LLE_FLAGS 1097
|
||||
#define ID_GUI_STATUS_XBOX_LED_COLOUR 1098
|
||||
#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_1 1166
|
||||
#define IDC_XBOX_PORT_2 1174
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// * (c) 2019 ego720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -79,24 +80,27 @@ unsigned char virtual_memory_placeholder[VM_PLACEHOLDER_SIZE] = { 0 }; // = { OP
|
|||
// /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);
|
||||
DWORD nNumberOfCharsToWrite = 0;
|
||||
while (msg[nNumberOfCharsToWrite]) nNumberOfCharsToWrite++; // poor-man's strlen()
|
||||
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD nNumberOfCharsToWrite = 0;
|
||||
while (msg[nNumberOfCharsToWrite]) nNumberOfCharsToWrite++; // poor-man's strlen()
|
||||
|
||||
// Detect output-redirection to a file
|
||||
DWORD ConsoleMode;
|
||||
if (!GetConsoleMode(hConsoleOutput, &ConsoleMode)) {
|
||||
// Note : assume the output file accepts ANSI encoded characters
|
||||
DWORD NumberOfBytesWritten;
|
||||
WriteFile(hConsoleOutput, (const void *)msg, nNumberOfCharsToWrite, &NumberOfBytesWritten, /*lpOverlapped=*/NULL);
|
||||
} else {
|
||||
// Write message to console output
|
||||
DWORD NumberOfCharsWritten;
|
||||
WriteConsoleA(hConsoleOutput, (const void *)msg, nNumberOfCharsToWrite, &NumberOfCharsWritten, /*lpReserved=*/NULL);
|
||||
// Detect output-redirection to a file
|
||||
DWORD ConsoleMode;
|
||||
if (!GetConsoleMode(hConsoleOutput, &ConsoleMode)) {
|
||||
// Note : assume the output file accepts ANSI encoded characters
|
||||
DWORD NumberOfBytesWritten;
|
||||
WriteFile(hConsoleOutput, (const void*)msg, nNumberOfCharsToWrite, &NumberOfBytesWritten, /*lpOverlapped=*/NULL);
|
||||
}
|
||||
else {
|
||||
// Write message to console output
|
||||
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
|
||||
OutputMessage("Required address range couldn't be reserved!\n");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
@ -166,7 +173,7 @@ DWORD CALLBACK rawMain()
|
|||
}
|
||||
|
||||
// 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");
|
||||
if (!pfnEmulate) {
|
||||
OutputMessage("Entrypoint not found!\n");
|
||||
|
@ -175,7 +182,7 @@ DWORD CALLBACK rawMain()
|
|||
|
||||
// Call the main emulation function in our DLL, passing in the results
|
||||
// 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
|
||||
// because all code and data that have been used up until now are
|
||||
|
|
Loading…
Reference in New Issue