Get maximum reserve memory ranges from host.
Plus more fixup to manage reliable memory design on loader launch and emulator.
This commit is contained in:
parent
37b230fbfe
commit
fb7398d7c9
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "AddressRanges.h"
|
||||
|
||||
bool AddressRangeMatchesFlags(const int index, const int flags)
|
||||
bool AddressRangeMatchesFlags(const int index, const unsigned int flags)
|
||||
{
|
||||
return XboxAddressRanges[index].RangeFlags & flags;
|
||||
}
|
||||
|
@ -37,6 +37,11 @@ bool IsOptionalAddressRange(const int index)
|
|||
return AddressRangeMatchesFlags(index, MAY_FAIL);
|
||||
}
|
||||
|
||||
int AddressRangeGetSystemFlags(const int index)
|
||||
{
|
||||
return XboxAddressRanges[index].RangeFlags & SYSTEM_ALL;
|
||||
}
|
||||
|
||||
bool VerifyWow64()
|
||||
{
|
||||
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
|
||||
|
|
|
@ -56,7 +56,7 @@ const struct {
|
|||
#ifdef DEBUG
|
||||
uint32_t End; // TODO : Add validation that this End corresponds to specified Size
|
||||
#endif
|
||||
int Size;
|
||||
uint32_t Size;
|
||||
DWORD InitialMemoryProtection; // Memory page protection, for use by VirtualAlloc
|
||||
// Shortend symbol aliasses for memory page protection
|
||||
#define PROT_UNH 0 // UNHANDLED
|
||||
|
@ -64,7 +64,7 @@ const struct {
|
|||
#define PROT_XRW PAGE_EXECUTE_READWRITE
|
||||
#define PROT_NAC PAGE_NOACCESS
|
||||
|
||||
int RangeFlags;
|
||||
unsigned int RangeFlags;
|
||||
// Range flags (used for system selection and optional marker)
|
||||
#define MAY_FAIL (1 << 0) // Optional (may fail address range reservation)
|
||||
#define SYSTEM_XBOX (1 << 1)
|
||||
|
@ -85,10 +85,10 @@ const struct {
|
|||
// See http://xboxdevwiki.net/Memory
|
||||
// and http://xboxdevwiki.net/Boot_Process#Paging
|
||||
// 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(0x00010000, 0x03FFFFFF, MB( 64) - KB(64), PROT_XRW, SYSTEM_ALL | MAY_FAIL, "MemLowVirtual (General Xbox type) lower 64 MB Optional (already reserved via virtual_memory_placeholder)"),
|
||||
RANGE_ENTRY(0x04000000, 0x07FFFFFF, MB( 64) , PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit) ^ + upper 64 MB"),
|
||||
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64) , PROT_UNH, SYSTEM_ALL , "MemPhysical (General Xbox type) lower 64 MB"),
|
||||
RANGE_ENTRY(0x84000000, 0x87FFFFFF, MB( 64) , PROT_UNH, SYSTEM_128MB , "MemPhysical (Chihiro / DevKit) ^ + upper 64 MB"),
|
||||
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)
|
||||
|
@ -107,8 +107,14 @@ const struct {
|
|||
#undef RANGE_ENTRY
|
||||
};
|
||||
|
||||
extern bool AddressRangeMatchesFlags(const int index, const int flags);
|
||||
#define BLOCK_REGION_DEVKIT_INDEX_BEGIN 0
|
||||
#define BLOCK_REGION_DEVKIT_INDEX_END 4096
|
||||
#define BLOCK_REGION_SYSTEM_INDEX_BEGIN 4096
|
||||
#define BLOCK_REGION_SYSTEM_INDEX_END 12288
|
||||
|
||||
extern bool AddressRangeMatchesFlags(const int index, const unsigned int flags);
|
||||
extern bool IsOptionalAddressRange(const int index);
|
||||
extern int AddressRangeGetSystemFlags(const int index);
|
||||
|
||||
extern bool VerifyWow64();
|
||||
|
||||
|
|
|
@ -42,8 +42,10 @@ bool ReserveMemoryRange(int index, uint32_t blocks_reserved[384])
|
|||
|
||||
const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection;
|
||||
bool NeedsReservationTracking = false;
|
||||
unsigned int arr_index = BLOCK_REGION_DEVKIT_INDEX_BEGIN;
|
||||
switch (Start) {
|
||||
case 0x80000000:
|
||||
case 0x84000000:
|
||||
case 0xF0000000: {
|
||||
static bool NeedsInitialization = true;
|
||||
static HANDLE hFileMapping;
|
||||
|
@ -63,7 +65,7 @@ bool ReserveMemoryRange(int index, uint32_t blocks_reserved[384])
|
|||
}
|
||||
LPVOID Result = MapViewOfFileEx(
|
||||
hFileMapping,
|
||||
Start == 0x80000000 ?
|
||||
(Start == 0x80000000 || Start == 0x84000000) ?
|
||||
(FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE) : (FILE_MAP_READ | FILE_MAP_WRITE),
|
||||
0,
|
||||
0,
|
||||
|
@ -75,15 +77,21 @@ bool ReserveMemoryRange(int index, uint32_t blocks_reserved[384])
|
|||
}
|
||||
break;
|
||||
|
||||
case 0xB0000000:
|
||||
case 0xD0000000: {
|
||||
case 0xD0000000:
|
||||
// If additional addresses need to be assign in region's block.
|
||||
// Then check for nonzero value.
|
||||
arr_index = BLOCK_REGION_SYSTEM_INDEX_BEGIN;
|
||||
[[fallthrough]];
|
||||
case 0xB0000000: {
|
||||
// arr_index's default is BLOCK_REGION_DEVKIT_INDEX_BEGIN which is zero.
|
||||
// Any block region above zero should be place above this case to override zero value.
|
||||
//arr_index = BLOCK_REGION_DEVKIT_INDEX_BEGIN;
|
||||
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) {
|
||||
|
@ -107,7 +115,53 @@ bool ReserveMemoryRange(int index, uint32_t blocks_reserved[384])
|
|||
return !HadAnyFailure;
|
||||
}
|
||||
|
||||
bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]) {
|
||||
// Free address range from the host.
|
||||
void FreeMemoryRange(int index, uint32_t blocks_reserved[384])
|
||||
{
|
||||
uint32_t Start = XboxAddressRanges[index].Start, _Start;
|
||||
int Size = XboxAddressRanges[index].Size;
|
||||
bool NeedsReservationTracking = false;
|
||||
unsigned int arr_index = BLOCK_REGION_DEVKIT_INDEX_BEGIN;
|
||||
switch (Start) {
|
||||
case 0x80000000:
|
||||
case 0x84000000:
|
||||
case 0xF0000000: {
|
||||
(void)UnmapViewOfFile((LPVOID)Start);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD0000000:
|
||||
// If additional addresses need to be assign in region's block.
|
||||
// Then check for nonzero value.
|
||||
arr_index = BLOCK_REGION_SYSTEM_INDEX_BEGIN;
|
||||
[[fallthrough]];
|
||||
case 0xB0000000: {
|
||||
// arr_index's default is BLOCK_REGION_DEVKIT_INDEX_BEGIN which is zero.
|
||||
// Any block region above zero should be place above this case to override zero value.
|
||||
//arr_index = BLOCK_REGION_DEVKIT_INDEX_BEGIN;
|
||||
NeedsReservationTracking = true;
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
default: {
|
||||
while (Size > 0) {
|
||||
_Start = Start; // Require to silence C6001's warning complaint
|
||||
BOOL Result = VirtualFree((LPVOID)_Start, 0, MEM_RELEASE);
|
||||
// Handle the next block
|
||||
Start += BLOCK_SIZE;
|
||||
Size -= BLOCK_SIZE;
|
||||
if (NeedsReservationTracking) {
|
||||
if (Result != 0) {
|
||||
blocks_reserved[arr_index / 32] &= ~(1 << (arr_index % 32));
|
||||
}
|
||||
arr_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ReserveAddressRanges(const unsigned 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
|
||||
|
@ -126,3 +180,74 @@ bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeAddressRanges(const unsigned int system, unsigned int release_systems, uint32_t blocks_reserved[384]) {
|
||||
// If reserved_systems is empty, then there's nothing to be freed up.
|
||||
if (release_systems == 0) {
|
||||
return;
|
||||
}
|
||||
// Loop over all Xbox address ranges
|
||||
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
|
||||
// Skip address ranges that do match specific flag
|
||||
if (AddressRangeMatchesFlags(i, system))
|
||||
continue;
|
||||
|
||||
// Skip address ranges that doesn't match the reserved flags
|
||||
if (!AddressRangeMatchesFlags(i, release_systems))
|
||||
continue;
|
||||
|
||||
FreeMemoryRange(i, blocks_reserved);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool AttemptReserveAddressRanges(unsigned int* p_reserved_systems, uint32_t blocks_reserved[384]) {
|
||||
|
||||
int iLast = 0;
|
||||
unsigned int reserved_systems = *p_reserved_systems, clear_systems = 0;
|
||||
// Loop over all Xbox address ranges
|
||||
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
|
||||
|
||||
// Once back to original spot, let's resume.
|
||||
if (i == iLast && clear_systems) {
|
||||
reserved_systems &= ~clear_systems;
|
||||
if (reserved_systems == 0) {
|
||||
*p_reserved_systems = 0;
|
||||
return false;
|
||||
}
|
||||
// Resume virtual allocated range.
|
||||
clear_systems = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clear_systems) {
|
||||
// Skip address ranges that doesn't match the given flags
|
||||
if (!AddressRangeMatchesFlags(i, clear_systems))
|
||||
continue;
|
||||
|
||||
// Release incompatible system's memory range
|
||||
FreeMemoryRange(i, blocks_reserved);
|
||||
}
|
||||
else {
|
||||
// Skip address ranges that don't match the given flags
|
||||
if (!AddressRangeMatchesFlags(i, reserved_systems))
|
||||
continue;
|
||||
|
||||
// Try to reserve each address range
|
||||
if (ReserveMemoryRange(i, blocks_reserved))
|
||||
continue;
|
||||
|
||||
// Some ranges are allowed to fail reserving
|
||||
if (!IsOptionalAddressRange(i)) {
|
||||
// If not, then let's free them and downgrade host's limitation.
|
||||
iLast = i;
|
||||
i = -1; // Reset index back to zero after for statement's increment.
|
||||
clear_systems = AddressRangeGetSystemFlags(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*p_reserved_systems = reserved_systems;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,4 +26,8 @@
|
|||
// ******************************************************************
|
||||
#pragma once
|
||||
|
||||
extern bool ReserveAddressRanges(const int system, uint32_t blocks_reserved[384]);
|
||||
extern bool ReserveAddressRanges(const unsigned int system, uint32_t blocks_reserved[384]);
|
||||
|
||||
extern void FreeAddressRanges(const unsigned int system, unsigned int release_systems, uint32_t blocks_reserved[384]);
|
||||
|
||||
extern bool AttemptReserveAddressRanges(unsigned int* p_reserved_systems, uint32_t blocks_reserved[384]);
|
||||
|
|
|
@ -163,4 +163,20 @@ long long GetSessionID()
|
|||
return sessionID;
|
||||
}
|
||||
|
||||
void SetSystemType(const std::string value)
|
||||
{
|
||||
// If system types key exist, then do not replace old one.
|
||||
if (hasKey(cli_config::system_retail)
|
||||
|| hasKey(cli_config::system_devkit)
|
||||
|| hasKey(cli_config::system_chihiro)) {
|
||||
return;
|
||||
}
|
||||
// If one of system types match, then set it.
|
||||
if (value.compare(cli_config::system_retail) == 0
|
||||
|| value.compare(cli_config::system_devkit) == 0
|
||||
|| value.compare(cli_config::system_chihiro) == 0) {
|
||||
SetValue(value, "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ static constexpr char hwnd[] = "hwnd";
|
|||
static constexpr char debug_mode[] = "dm";
|
||||
static constexpr char debug_file[] = "df";
|
||||
static constexpr char sid[] = "sid";
|
||||
static constexpr char system_retail[] = "retail";
|
||||
static constexpr char system_devkit[] = "devkit";
|
||||
static constexpr char system_chihiro[] = "chihiro";
|
||||
|
||||
bool GenConfig(char** argv, int argc);
|
||||
size_t ConfigSize();
|
||||
|
@ -53,4 +56,6 @@ long long GetSessionID();
|
|||
// Change xbe path to launch.
|
||||
void SetLoad(const std::string value);
|
||||
|
||||
void SetSystemType(const std::string value);
|
||||
|
||||
}
|
||||
|
|
|
@ -195,8 +195,8 @@ class EmuShared : public Mutex
|
|||
// ******************************************************************
|
||||
// * Previous Memory Layout value Accessors
|
||||
// ******************************************************************
|
||||
void GetMmLayout(int* value) { Lock(); *value = m_PreviousMmLayout; Unlock(); }
|
||||
void SetMmLayout(int* value) { Lock(); m_PreviousMmLayout = *value; Unlock(); }
|
||||
void GetMmLayout(unsigned int* value) { Lock(); *value = m_PreviousMmLayout; Unlock(); }
|
||||
void SetMmLayout(unsigned int* value) { Lock(); m_PreviousMmLayout = *value; Unlock(); }
|
||||
#endif
|
||||
// ******************************************************************
|
||||
// * Log Level value Accessors
|
||||
|
@ -272,7 +272,7 @@ class EmuShared : public Mutex
|
|||
bool m_bReady_status;
|
||||
bool m_bEmulating_status;
|
||||
#ifndef CXBX_LOADER // Temporary usage for cxbx.exe's emu
|
||||
int m_PreviousMmLayout;
|
||||
unsigned int m_PreviousMmLayout;
|
||||
int m_Reserved7[3];
|
||||
#else
|
||||
int m_Reserved7[4];
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace xboxkrnl
|
|||
#include "CxbxDebugger.h"
|
||||
#include "common/util/cliConfig.hpp"
|
||||
#include "common/util/xxhash.h"
|
||||
#include "common/ReserveAddressRanges.h"
|
||||
|
||||
#include <clocale>
|
||||
#include <process.h>
|
||||
|
@ -134,6 +135,36 @@ XbeType GetXbeType(Xbe::Header *pXbeHeader)
|
|||
return xtRetail;
|
||||
}
|
||||
|
||||
const char* GetSystemTypeToStr(unsigned int system)
|
||||
{
|
||||
if (system == SYSTEM_CHIHIRO) {
|
||||
return cli_config::system_chihiro;
|
||||
}
|
||||
|
||||
if (system == SYSTEM_DEVKIT) {
|
||||
return cli_config::system_devkit;
|
||||
}
|
||||
|
||||
if (system == SYSTEM_XBOX) {
|
||||
return cli_config::system_retail;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* GetXbeTypeToStr(XbeType xbe_type)
|
||||
{
|
||||
if (xbe_type == xtChihiro) {
|
||||
return "chihiro";
|
||||
}
|
||||
|
||||
if (xbe_type == xtDebug) {
|
||||
return "debug";
|
||||
}
|
||||
|
||||
return "retail";
|
||||
}
|
||||
|
||||
void ApplyMediaPatches()
|
||||
{
|
||||
// Patch the XBE Header to allow running from all media types
|
||||
|
@ -724,7 +755,23 @@ bool HandleFirstLaunch()
|
|||
return true;
|
||||
}
|
||||
|
||||
void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
|
||||
// TODO: Need to move isSystemFlagSupport function somewhere other than CxbxKrnl.cpp file.
|
||||
bool isSystemFlagSupport(int reserved_systems, int assign_system)
|
||||
{
|
||||
if (reserved_systems & assign_system) {
|
||||
return true;
|
||||
}
|
||||
// TODO: Once host's standalone emulation is remove from GUI, remove below as well.
|
||||
#ifndef CXBXR_EMU
|
||||
if (reserved_systems == 0) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CxbxKrnlEmulate(unsigned int reserved_systems, uint32_t blocks_reserved[384])
|
||||
{
|
||||
std::string tempStr;
|
||||
|
||||
|
@ -1075,8 +1122,51 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
|
|||
}
|
||||
}
|
||||
|
||||
// Detect XBE type :
|
||||
g_XbeType = GetXbeType(&CxbxKrnl_Xbe->m_Header);
|
||||
// If CLI has given console type, then enforce it.
|
||||
if (cli_config::hasKey(cli_config::system_chihiro)) {
|
||||
EmuLogInit(LOG_LEVEL::INFO, "Auto detect is disabled, running as chihiro.");
|
||||
g_XbeType = xtChihiro;
|
||||
}
|
||||
else if (cli_config::hasKey(cli_config::system_devkit)) {
|
||||
EmuLogInit(LOG_LEVEL::INFO, "Auto detect is disabled, running as devkit.");
|
||||
g_XbeType = xtDebug;
|
||||
}
|
||||
else if (cli_config::hasKey(cli_config::system_retail)) {
|
||||
EmuLogInit(LOG_LEVEL::INFO, "Auto detect is disabled, running as retail.");
|
||||
g_XbeType = xtRetail;
|
||||
}
|
||||
// Otherwise, use auto detect method.
|
||||
else {
|
||||
// Detect XBE type :
|
||||
g_XbeType = GetXbeType(&CxbxKrnl_Xbe->m_Header);
|
||||
EmuLogInit(LOG_LEVEL::INFO, "Auto detect: XbeType = %s", GetXbeTypeToStr(g_XbeType));
|
||||
}
|
||||
|
||||
EmuLogInit(LOG_LEVEL::INFO, "Host's compatible system types: %2X", reserved_systems);
|
||||
unsigned int emulate_system = 0;
|
||||
// Set reserved_systems which system we will about to emulate.
|
||||
if (isSystemFlagSupport(reserved_systems, SYSTEM_CHIHIRO) && g_XbeType == xtChihiro) {
|
||||
emulate_system = SYSTEM_CHIHIRO;
|
||||
}
|
||||
else if (isSystemFlagSupport(reserved_systems, SYSTEM_DEVKIT) && g_XbeType == xtDebug) {
|
||||
emulate_system = SYSTEM_DEVKIT;
|
||||
}
|
||||
else if (isSystemFlagSupport(reserved_systems, SYSTEM_XBOX) && g_XbeType == xtRetail) {
|
||||
emulate_system = SYSTEM_XBOX;
|
||||
}
|
||||
// If none of system type requested to emulate isn't supported on host's end. Then enforce failure.
|
||||
else {
|
||||
CxbxKrnlCleanup("Unable to emulate system type due to host is not able to reserve required memory ranges.");
|
||||
return;
|
||||
}
|
||||
// Clear emulation system from reserved systems to be free.
|
||||
reserved_systems &= ~emulate_system;
|
||||
|
||||
// Once we have determine which system type to run as, enforce it in future reboots.
|
||||
if ((BootFlags & BOOT_QUICK_REBOOT) == 0) {
|
||||
const char* system_str = GetSystemTypeToStr(emulate_system);
|
||||
cli_config::SetSystemType(system_str);
|
||||
}
|
||||
|
||||
// Register if we're running an Chihiro executable or a debug xbe, otherwise it's an Xbox retail executable
|
||||
g_bIsChihiro = (g_XbeType == xtChihiro);
|
||||
|
@ -1106,9 +1196,9 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
|
|||
uint32_t SystemDevBlocksReserved[384] = { 0 };
|
||||
g_VMManager.Initialize(0, BootFlags, SystemDevBlocksReserved);
|
||||
#else
|
||||
// TODO: Retrieve the system type from the loader and be sure that it doesn't change between quick reboots
|
||||
FreeAddressRanges(emulate_system, reserved_systems, blocks_reserved);
|
||||
// Initialize the memory manager
|
||||
g_VMManager.Initialize(SYSTEM_XBOX, BootFlags, blocks_reserved);
|
||||
g_VMManager.Initialize(emulate_system, BootFlags, blocks_reserved);
|
||||
#endif
|
||||
|
||||
// Commit the memory used by the xbe header
|
||||
|
|
|
@ -237,7 +237,7 @@ bool CreateSettings();
|
|||
bool HandleFirstLaunch();
|
||||
|
||||
/*! Cxbx Kernel Entry Point */
|
||||
void CxbxKrnlEmulate(uint32_t blocks_reserved[384]);
|
||||
void CxbxKrnlEmulate(unsigned int system, 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,17 +73,19 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void VMManager::Initialize(int SystemType, int BootFlags, uint32_t blocks_reserved[384])
|
||||
void VMManager::Initialize(unsigned int SystemType, int BootFlags, uint32_t blocks_reserved[384])
|
||||
{
|
||||
#ifndef CXBXR_EMU
|
||||
if ((BootFlags & BOOT_QUICK_REBOOT) == 0) {
|
||||
#ifndef CXBXR_EMU
|
||||
SystemType = g_bIsRetail ? SYSTEM_XBOX : g_bIsChihiro ? SYSTEM_CHIHIRO : SYSTEM_DEVKIT; // TODO: Temporary placeholder until loader is functional.
|
||||
#endif
|
||||
g_EmuShared->SetMmLayout(&SystemType);
|
||||
}
|
||||
else {
|
||||
g_EmuShared->GetMmLayout(&SystemType);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CXBXR_EMU
|
||||
if (!ReserveAddressRanges(SystemType, blocks_reserved)) {
|
||||
CxbxKrnlCleanup("Failed to reserve required memory ranges!", GetLastError());
|
||||
}
|
||||
|
@ -113,26 +115,19 @@ void VMManager::Initialize(int SystemType, int BootFlags, uint32_t blocks_reserv
|
|||
}
|
||||
}
|
||||
|
||||
// Construct VMAs base on reserved bit indexes for devkit and system region blocks.
|
||||
if (SystemType == SYSTEM_DEVKIT) {
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
for (unsigned int i = BLOCK_REGION_DEVKIT_INDEX_BEGIN; i < BLOCK_REGION_DEVKIT_INDEX_END; i++) {
|
||||
if ((blocks_reserved[i / 32] & (1 << (i % 32))) == 0) {
|
||||
// The loader was unable to reserve this block, so discard it from the memory region
|
||||
ConstructVMA(DEVKIT_MEMORY_BASE + i * (64 * ONE_KB), (64 * ONE_KB), DevkitRegion, ReservedVma, false);
|
||||
}
|
||||
}
|
||||
for (int i = 4096; i < 12288; i++) {
|
||||
if ((blocks_reserved[i / 32] & (1 << (i % 32))) == 0) {
|
||||
// The loader was unable to reserve this block, so discard it from the memory region
|
||||
ConstructVMA(SYSTEM_MEMORY_BASE + i * (64 * ONE_KB), (64 * ONE_KB), SystemRegion, ReservedVma, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 8192; i++) {
|
||||
if ((blocks_reserved[i / 32] & (1 << (i % 32))) == 0) {
|
||||
// The loader was unable to reserve this block, so discard it from the memory region
|
||||
ConstructVMA(SYSTEM_MEMORY_BASE + i * (64 * ONE_KB), (64 * ONE_KB), SystemRegion, ReservedVma, false);
|
||||
}
|
||||
}
|
||||
for (unsigned int i = BLOCK_REGION_SYSTEM_INDEX_BEGIN; i < BLOCK_REGION_SYSTEM_INDEX_END; i++) {
|
||||
if ((blocks_reserved[i / 32] & (1 << (i % 32))) == 0) {
|
||||
// The loader was unable to reserve this block, so discard it from the memory region
|
||||
ConstructVMA(SYSTEM_MEMORY_BASE + i * (64 * ONE_KB), (64 * ONE_KB), SystemRegion, ReservedVma, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,16 @@
|
|||
#ifndef VMMANAGER_H
|
||||
#define VMMANAGER_H
|
||||
|
||||
// TODO: Need to move defines below into one header files.
|
||||
#define SYSTEM_XBOX (1 << 1)
|
||||
#define SYSTEM_DEVKIT (1 << 2)
|
||||
#define SYSTEM_CHIHIRO (1 << 3)
|
||||
|
||||
#define BLOCK_REGION_DEVKIT_INDEX_BEGIN 0
|
||||
#define BLOCK_REGION_DEVKIT_INDEX_END 4096
|
||||
#define BLOCK_REGION_SYSTEM_INDEX_BEGIN 4096
|
||||
#define BLOCK_REGION_SYSTEM_INDEX_END 12288
|
||||
|
||||
#include "PhysicalMemory.h"
|
||||
|
||||
|
||||
|
@ -103,7 +109,7 @@ class VMManager : public PhysicalMemory
|
|||
// shutdown routine
|
||||
void Shutdown();
|
||||
// initializes the memory manager to the default configuration
|
||||
void Initialize(int SystemType, int BootFlags, uint32_t blocks_reserved[384]);
|
||||
void Initialize(unsigned 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
|
||||
|
|
|
@ -122,7 +122,7 @@ CommandLineToArgvA(
|
|||
return argv;
|
||||
}
|
||||
|
||||
DWORD WINAPI Emulate(int system, uint32_t blocks_reserved[384])
|
||||
DWORD WINAPI Emulate(unsigned int reserved_systems, uint32_t blocks_reserved[384])
|
||||
{
|
||||
FUNC_EXPORTS
|
||||
|
||||
|
@ -170,7 +170,13 @@ DWORD WINAPI Emulate(int system, uint32_t blocks_reserved[384])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CxbxKrnlEmulate(blocks_reserved);
|
||||
if (!reserved_systems) {
|
||||
CxbxShowError("Unable to preserve any system's memory ranges!");
|
||||
EmuShared::Cleanup();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CxbxKrnlEmulate(reserved_systems, blocks_reserved);
|
||||
|
||||
/*! cleanup shared memory */
|
||||
EmuShared::Cleanup();
|
||||
|
|
|
@ -82,7 +82,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
|
||||
if (cli_config::hasKey("load")) {
|
||||
#ifndef CXBXR_EMU
|
||||
CxbxKrnlEmulate(nullptr);
|
||||
CxbxKrnlEmulate(0, nullptr);
|
||||
EmuShared::Cleanup();
|
||||
return EXIT_SUCCESS;
|
||||
#else
|
||||
|
|
|
@ -137,29 +137,16 @@ DWORD CALLBACK rawMain()
|
|||
return ERROR_BAD_ENVIRONMENT;
|
||||
}
|
||||
|
||||
// TODO: NOTE - Must reserve all memory by default. This is a requirement for standalone emulation support.
|
||||
// It is still possible to release upper 64 MB space after determine the first xbe file.
|
||||
// However, it is not recommended since modded xbox hardware can have 128MB yet still only able to use lower 64MB if xbe is not patched.
|
||||
int system = SYSTEM_XBOX; // By default, we'll emulate a retail Xbox
|
||||
|
||||
// Note : Since we only have kernel32 API's available (not even the standard libary),
|
||||
// we use the (exclusively wide-char) FindStringOrdinal() here instead of strstr():
|
||||
LPWSTR CommandLine = GetCommandLineW();
|
||||
// TODO: Below options must go, see "NOTE -" comment above for the reasons.
|
||||
if (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /chihiro", -1, true) >= 0) {
|
||||
system = SYSTEM_CHIHIRO;
|
||||
} else {
|
||||
if (FindStringOrdinal(FIND_FROMSTART, CommandLine, -1, L" /devkit", -1, true) >= 0) {
|
||||
system = SYSTEM_DEVKIT;
|
||||
}
|
||||
}
|
||||
// Reserve all memory by default. This is a requirement for standalone emulation support.
|
||||
// Emulator's initial process will decide which memory ranges will be free.
|
||||
unsigned int system = SYSTEM_ALL; // Reserve all systems.
|
||||
|
||||
// Marking this as static to avoid an implicit call to memset, which is not available in the loader
|
||||
static uint32_t SystemDevBlocksReserved[384];
|
||||
|
||||
if (!ReserveAddressRanges(system, SystemDevBlocksReserved)) {
|
||||
if (!AttemptReserveAddressRanges(&system, SystemDevBlocksReserved)) {
|
||||
// If we get here, emulation lacks important address ranges; Don't launch
|
||||
OutputMessage("Required address range couldn't be reserved!\n");
|
||||
OutputMessage("None of system types' required address range(s) could be reserved!\n");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -177,7 +164,7 @@ DWORD CALLBACK rawMain()
|
|||
}
|
||||
|
||||
// Find the main emulation function in our DLL
|
||||
typedef void (WINAPI *Emulate_t)(int, uint32_t[384]);
|
||||
typedef void (WINAPI *Emulate_t)(unsigned int, uint32_t[384]);
|
||||
Emulate_t pfnEmulate = (Emulate_t)GetProcAddress(hEmulationDLL, "Emulate");
|
||||
if (!pfnEmulate) {
|
||||
OutputMessage("Entrypoint not found!\n");
|
||||
|
|
Loading…
Reference in New Issue