Merge pull request #821 from ergo720/memory
Virtual memory manager + Kernel memory functions implementation
This commit is contained in:
commit
984e2bd510
|
@ -231,11 +231,12 @@
|
|||
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\nv2a_int.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\OOVPA.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\PhysicalMemory.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\ReservedMemory.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\ResourceTracker.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\VMManager.h" />
|
||||
<ClInclude Include="..\..\src\CxbxVersion.h" />
|
||||
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h" />
|
||||
<ClInclude Include="..\..\src\Cxbx\DlgAudioConfig.h" />
|
||||
|
@ -514,13 +515,14 @@
|
|||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\LibRc4.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\MemoryManager.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\PhysicalMemory.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\ResourceTracker.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\VMManager.cpp" />
|
||||
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp" />
|
||||
<ClCompile Include="..\..\src\Cxbx\DlgAudioConfig.cpp" />
|
||||
<ClCompile Include="..\..\src\Cxbx\DlgControllerConfig.cpp">
|
||||
|
|
|
@ -187,9 +187,6 @@
|
|||
<ClCompile Include="..\..\src\Common\EmuEEPROM.cpp">
|
||||
<Filter>Shared</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\MemoryManager.cpp">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp">
|
||||
<Filter>GUI</Filter>
|
||||
</ClCompile>
|
||||
|
@ -205,6 +202,12 @@
|
|||
<ClCompile Include="..\..\src\Common\Win32\XBAudio.cpp">
|
||||
<Filter>Shared</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\PhysicalMemory.cpp">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\VMManager.cpp">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\Cxbx\DlgControllerConfig.h">
|
||||
|
@ -369,9 +372,6 @@
|
|||
<ClInclude Include="..\..\src\CxbxVersion.h">
|
||||
<Filter>Shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h">
|
||||
<Filter>GUI</Filter>
|
||||
</ClInclude>
|
||||
|
@ -396,6 +396,12 @@
|
|||
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h">
|
||||
<Filter>HLEDatabase\D3D8</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\PhysicalMemory.h">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\VMManager.h">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\resource\Splash.jpg">
|
||||
|
|
|
@ -71,8 +71,8 @@ XBSYSAPI EXPORTNUM(169) PVOID NTAPI MmCreateKernelStack
|
|||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(170) VOID NTAPI MmDeleteKernelStack
|
||||
(
|
||||
IN PVOID EndAddress,
|
||||
IN PVOID BaseAddress
|
||||
IN PVOID StackBase,
|
||||
IN PVOID StackLimit
|
||||
);
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -229,6 +229,11 @@ typedef long NTSTATUS;
|
|||
// Xbox pages are (1 << 12) = 0x00001000 = 4096 bytes in size.
|
||||
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||
#define PAGE_MASK (PAGE_SIZE - 1)
|
||||
#define MAX_NUM_OF_PAGES 1 << (32 - PAGE_SHIFT) // 1048576 (1024^2) max virtual pages possible, = 4GiB / 4096
|
||||
#define XBOX_CONTIGUOUS_MEMORY_LIMIT XBOX_MEMORY_SIZE - 32 * PAGE_SIZE // upper limit available for contiguous allocations (xbox)
|
||||
#define CHIHIRO_CONTIGUOUS_MEMORY_LIMIT CHIHIRO_MEMORY_SIZE - 48 * PAGE_SIZE // upper limit available for contiguous allocations (chihiro)
|
||||
#define ZERO_PAGE_ADDR 0
|
||||
#define FIRST_PAGE_ADDR PAGE_SIZE
|
||||
|
||||
// Convert a physical frame number to its corresponding physical address.
|
||||
#define MI_CONVERT_PFN_TO_PHYSICAL(Pfn) \
|
||||
|
@ -2484,8 +2489,8 @@ typedef struct _XBE_SECTION // Was _XBE_SECTIONHEADER
|
|||
ULONG FileSize; // File size (size of the section in the XBE file)
|
||||
PCSZ SectionName; // Pointer to section name
|
||||
ULONG SectionReferenceCount; // Section reference count - when >= 1, section is loaded
|
||||
ULONG HeadReferenceCount; // Pointer to head shared page reference count
|
||||
ULONG TailReferenceCount; // Pointer to tail shared page reference count
|
||||
PUSHORT HeadReferenceCount; // Pointer to head shared page reference counter
|
||||
PUSHORT TailReferenceCount; // Pointer to tail shared page reference counter
|
||||
BYTE ShaHash[20]; // SHA hash. Hash DWORD containing FileSize, then hash section.
|
||||
}
|
||||
XBEIMAGE_SECTION, *PXBEIMAGE_SECTION;
|
||||
|
|
|
@ -138,6 +138,7 @@ EmuShared::EmuShared()
|
|||
{
|
||||
Load();
|
||||
m_bMultiXbe = false;
|
||||
m_LaunchDataPAddress = NULL;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -1005,7 +1005,7 @@ void *Xbe::FindSection(char *zsSectionName)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void Xbe::PurgeBadChar(std::string &s, const std::string &illegalChars)
|
||||
void Xbe::PurgeBadChar(std::string& s, const std::string& illegalChars)
|
||||
{
|
||||
for (auto it = s.begin(); it < s.end(); ++it)
|
||||
{
|
||||
|
|
|
@ -72,7 +72,7 @@ class Xbe : public Error
|
|||
void ExportLogoBitmap(uint08 x_Gray[100*17]);
|
||||
|
||||
// purge illegal characters in Windows filenames or other OS's
|
||||
void PurgeBadChar(std::string &s, const std::string &illegalChars = "\\/:?\"<>|");
|
||||
void PurgeBadChar(std::string& s, const std::string& illegalChars = "\\/:?\"<>|");
|
||||
|
||||
// Xbe header
|
||||
#include "AlignPrefix1.h"
|
||||
|
|
|
@ -119,6 +119,9 @@ extern XbeType g_XbeType;
|
|||
/*! indicates emulation of an Chihiro (arcade, instead of Xbox console) executable */
|
||||
extern bool g_bIsChihiro;
|
||||
|
||||
/*! indicates emulation of a Debug xbe executable */
|
||||
extern bool g_bIsDebug;
|
||||
|
||||
/*! maximum number of threads cxbx can handle */
|
||||
#define MAXIMUM_XBOX_THREADS 256
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace xboxkrnl
|
|||
#include "EmuNV2A.h" // For InitOpenGLContext
|
||||
#include "HLEIntercept.h"
|
||||
#include "ReservedMemory.h" // For virtual_memory_placeholder
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <clocale>
|
||||
|
@ -89,7 +89,6 @@ static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = { 0 };
|
|||
|
||||
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
||||
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
|
||||
char szFilePath_LaunchDataPage_bin[MAX_PATH] = { 0 };
|
||||
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
||||
char szFilePath_memory_bin[MAX_PATH] = { 0 };
|
||||
|
||||
|
@ -98,6 +97,7 @@ HANDLE CxbxBasePathHandle;
|
|||
Xbe* CxbxKrnl_Xbe = NULL;
|
||||
XbeType g_XbeType = xtRetail;
|
||||
bool g_bIsChihiro = false;
|
||||
bool g_bIsDebug = false;
|
||||
DWORD_PTR g_CPUXbox = 0;
|
||||
DWORD_PTR g_CPUOthers = 0;
|
||||
|
||||
|
@ -303,14 +303,12 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO : Make sure memory.bin is at least 64 MB in size - FileSeek(hFile, CONTIGUOUS_MEMORY_SIZE, soFromBeginning);
|
||||
|
||||
HANDLE hFileMapping = CreateFileMapping(
|
||||
hFile,
|
||||
/* lpFileMappingAttributes */nullptr,
|
||||
PAGE_EXECUTE_READWRITE,
|
||||
/* dwMaximumSizeHigh */0,
|
||||
/* dwMaximumSizeLow */CONTIGUOUS_MEMORY_SIZE,
|
||||
/* dwMaximumSizeLow */CHIHIRO_MEMORY_SIZE,
|
||||
/**/nullptr);
|
||||
if (hFileMapping == NULL)
|
||||
{
|
||||
|
@ -318,13 +316,22 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LARGE_INTEGER len_li;
|
||||
GetFileSizeEx(hFile, &len_li);
|
||||
unsigned int FileSize = len_li.u.LowPart;
|
||||
if (FileSize != CHIHIRO_MEMORY_SIZE)
|
||||
{
|
||||
CxbxKrnlCleanup("CxbxRestoreContiguousMemory : memory.bin file is not 128 MiB large!\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Map memory.bin contents into memory :
|
||||
void *memory = (void *)MapViewOfFileEx(
|
||||
hFileMapping,
|
||||
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
||||
/* dwFileOffsetHigh */0,
|
||||
/* dwFileOffsetLow */0,
|
||||
CONTIGUOUS_MEMORY_SIZE,
|
||||
CONTIGUOUS_MEMORY_CHIHIRO_SIZE,
|
||||
(void *)CONTIGUOUS_MEMORY_BASE);
|
||||
if (memory != (void *)CONTIGUOUS_MEMORY_BASE)
|
||||
{
|
||||
|
@ -336,11 +343,11 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|||
}
|
||||
|
||||
printf("[0x%.4X] INIT: Mapped %d MiB of Xbox contiguous memory at 0x%.8X to 0x%.8X\n",
|
||||
GetCurrentThreadId(), CONTIGUOUS_MEMORY_SIZE / ONE_MB, CONTIGUOUS_MEMORY_BASE, CONTIGUOUS_MEMORY_BASE + CONTIGUOUS_MEMORY_SIZE - 1);
|
||||
GetCurrentThreadId(), CONTIGUOUS_MEMORY_CHIHIRO_SIZE / ONE_MB, CONTIGUOUS_MEMORY_BASE, CONTIGUOUS_MEMORY_BASE + CONTIGUOUS_MEMORY_CHIHIRO_SIZE - 1);
|
||||
|
||||
if (NeedsInitialization)
|
||||
{
|
||||
memset(memory, 0, CONTIGUOUS_MEMORY_SIZE);
|
||||
memset(memory, 0, CONTIGUOUS_MEMORY_CHIHIRO_SIZE);
|
||||
printf("[0x%.4X] INIT: Initialized contiguous memory\n", GetCurrentThreadId());
|
||||
}
|
||||
else
|
||||
|
@ -352,7 +359,7 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|||
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
||||
/* dwFileOffsetHigh */0,
|
||||
/* dwFileOffsetLow */0,
|
||||
TILED_MEMORY_SIZE,
|
||||
TILED_MEMORY_CHIHIRO_SIZE,
|
||||
(void *)TILED_MEMORY_BASE);
|
||||
if (tiled_memory != (void *)TILED_MEMORY_BASE)
|
||||
{
|
||||
|
@ -362,9 +369,12 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
|||
CxbxKrnlCleanup("CxbxRestoreContiguousMemory: Couldn't map contiguous memory.bin into tiled memory at 0xF0000000!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
printf("[0x%.4X] INIT: Mapped contiguous memory to Xbox tiled memory at 0x%.8X to 0x%.8X\n",
|
||||
GetCurrentThreadId(), TILED_MEMORY_BASE, TILED_MEMORY_BASE + TILED_MEMORY_SIZE - 1);
|
||||
GetCurrentThreadId(), TILED_MEMORY_BASE, TILED_MEMORY_BASE + TILED_MEMORY_CHIHIRO_SIZE - 1);
|
||||
|
||||
// Initialize the virtual manager :
|
||||
g_VMManager.Initialize(hFileMapping);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
@ -575,8 +585,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
|
||||
CxbxRestoreContiguousMemory(szFilePath_memory_bin);
|
||||
|
||||
CxbxRestorePersistentMemoryRegions();
|
||||
|
||||
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
|
||||
if (EEPROM == nullptr)
|
||||
{
|
||||
|
@ -602,11 +610,17 @@ void CxbxKrnlMain(int argc, char* argv[])
|
|||
// Detect XBE type :
|
||||
g_XbeType = GetXbeType(&CxbxKrnl_Xbe->m_Header);
|
||||
|
||||
// Register if we're running an Chihiro executable (otherwise it's an Xbox executable)
|
||||
// Register if we're running an Chihiro executable or a debug xbe (otherwise it's an Xbox retail executable)
|
||||
g_bIsChihiro = (g_XbeType == xtChihiro);
|
||||
g_bIsDebug = (g_XbeType == xtDebug);
|
||||
|
||||
// Determine memory size accordingly :
|
||||
SIZE_T memorySize = (g_bIsChihiro ? CHIHIRO_MEMORY_SIZE : XBOX_MEMORY_SIZE);
|
||||
if (g_bIsChihiro || g_bIsDebug)
|
||||
{
|
||||
// Initialize the Chihiro/Debug - specific memory ranges
|
||||
g_VMManager.InitializeChihiroDebug();
|
||||
}
|
||||
|
||||
CxbxRestorePersistentMemoryRegions();
|
||||
|
||||
// Copy over loaded Xbe Headers to specified base address
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header));
|
||||
|
@ -887,7 +901,7 @@ __declspec(noreturn) void CxbxKrnlInit
|
|||
|
||||
// Assign the running Xbe path, so it can be accessed via the kernel thunk 'XeImageFileName' :
|
||||
xboxkrnl::XeImageFileName.MaximumLength = MAX_PATH;
|
||||
xboxkrnl::XeImageFileName.Buffer = (PCHAR)g_MemoryManager.Allocate(MAX_PATH);
|
||||
xboxkrnl::XeImageFileName.Buffer = (PCHAR)g_VMManager.Allocate(MAX_PATH);
|
||||
sprintf(xboxkrnl::XeImageFileName.Buffer, "%c:\\%s", CxbxDefaultXbeDriveLetter, fileName.c_str());
|
||||
xboxkrnl::XeImageFileName.Length = (USHORT)strlen(xboxkrnl::XeImageFileName.Buffer);
|
||||
printf("[0x%.4X] INIT: XeImageFileName = %s\n", GetCurrentThreadId(), xboxkrnl::XeImageFileName.Buffer);
|
||||
|
@ -1014,15 +1028,14 @@ void CxbxInitFilePaths()
|
|||
CxbxKrnlCleanup("CxbxInitFilePaths : Couldn't create Cxbx-Reloaded EmuDisk folder!");
|
||||
}
|
||||
|
||||
snprintf(szFilePath_LaunchDataPage_bin, MAX_PATH, "%s\\CxbxLaunchDataPage.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);
|
||||
|
||||
GetModuleFileName(GetModuleHandle(NULL), szFilePath_CxbxReloaded_Exe, MAX_PATH);
|
||||
}
|
||||
|
||||
// TODO : Is DefaultLaunchDataPage really necessary? (No-one assigns it yet to LaunchDataPage)
|
||||
xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
||||
// REMARK: the following is useless, but PatrickvL has asked to keep it for documentation purposes
|
||||
/*xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
||||
{
|
||||
{ // header
|
||||
2, // 2: dashboard, 0: title
|
||||
|
@ -1030,27 +1043,20 @@ xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
|||
"D:\\default.xbe",
|
||||
0
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
void CxbxRestoreLaunchDataPage()
|
||||
{
|
||||
// If CxbxLaunchDataPage.bin exist, load it into "persistent" memory
|
||||
FILE* fp = fopen(szFilePath_LaunchDataPage_bin, "rb");
|
||||
if (fp)
|
||||
PAddr LaunchDataPAddr;
|
||||
g_EmuShared->GetLaunchDataPAddress(&LaunchDataPAddr);
|
||||
|
||||
if (LaunchDataPAddr)
|
||||
{
|
||||
// Make sure LaunchDataPage is writeable :
|
||||
if (xboxkrnl::LaunchDataPage == &DefaultLaunchDataPage)
|
||||
xboxkrnl::LaunchDataPage = NULL;
|
||||
|
||||
if (xboxkrnl::LaunchDataPage == NULL)
|
||||
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE *)xboxkrnl::MmAllocateContiguousMemory(sizeof(xboxkrnl::LAUNCH_DATA_PAGE));
|
||||
|
||||
// Read in the contents.
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(xboxkrnl::LaunchDataPage, sizeof(xboxkrnl::LAUNCH_DATA_PAGE), 1, fp);
|
||||
fclose(fp);
|
||||
// Delete the file once we're done.
|
||||
remove(szFilePath_LaunchDataPage_bin);
|
||||
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)CONTIGUOUS_MEMORY_BASE + LaunchDataPAddr;
|
||||
// Mark the launch page as allocated to prevent other allocations from overwriting it
|
||||
xboxkrnl::MmAllocateContiguousMemoryEx(PAGE_SIZE, LaunchDataPAddr, LaunchDataPAddr + PAGE_SIZE - 1, PAGE_SIZE, PAGE_READWRITE);
|
||||
LaunchDataPAddr = NULL;
|
||||
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||
|
||||
DbgPrintf("INIT: Restored LaunchDataPage\n");
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ extern "C" {
|
|||
// Sizes
|
||||
#define ONE_KB 1024
|
||||
#define ONE_MB (1024 * 1024)
|
||||
#define X64KB 64 * ONE_KB
|
||||
|
||||
// Thread Information Block offsets - see https://www.microsoft.com/msj/archive/S2CE.aspx
|
||||
#define TIB_ArbitraryDataSlot 0x14
|
||||
|
@ -67,16 +68,41 @@ extern "C" {
|
|||
|
||||
// Define virtual base addresses for physical memory windows.
|
||||
#define MM_SYSTEM_PHYSICAL_MAP KSEG0_BASE // = 0x80000000
|
||||
#define MM_HIGHEST_PHYSICAL_PAGE 0x07FFF
|
||||
#define KERNEL_SIZE sizeof(DUMMY_KERNEL)
|
||||
#define MM_XBOX_HIGHEST_PHYSICAL_PAGE 0x03FFF
|
||||
#define MM_CHIHIRO_HIGHEST_PHYSICAL_PAGE 0x07FFF
|
||||
#define MM_64M_PHYSICAL_PAGE 0x04000
|
||||
#define MM_INSTANCE_PHYSICAL_PAGE 0x03FE0 // Chihiro arcade should use 0x07FF0
|
||||
#define MM_XBOX_INSTANCE_PHYSICAL_PAGE 0x03FE0
|
||||
#define MM_CHIHIRO_INSTANCE_PHYSICAL_PAGE 0x07FF0
|
||||
#define MM_INSTANCE_PAGE_COUNT 16
|
||||
#define CONTIGUOUS_MEMORY_BASE MM_SYSTEM_PHYSICAL_MAP // = 0x80000000
|
||||
#define CONTIGUOUS_MEMORY_SIZE (64 * ONE_MB)
|
||||
#define CONTIGUOUS_MEMORY_XBOX_SIZE (64 * ONE_MB)
|
||||
#define CONTIGUOUS_MEMORY_CHIHIRO_SIZE (128 * ONE_MB)
|
||||
#define TILED_MEMORY_BASE 0xF0000000 // Tiled memory is a mirror of contiguous memory, residing at 0xF0000000
|
||||
#define TILED_MEMORY_SIZE CONTIGUOUS_MEMORY_SIZE
|
||||
#define TILED_MEMORY_XBOX_SIZE CONTIGUOUS_MEMORY_XBOX_SIZE
|
||||
#define TILED_MEMORY_CHIHIRO_SIZE CONTIGUOUS_MEMORY_CHIHIRO_SIZE
|
||||
#define NV2A_MEMORY_BASE 0xFD000000 // See NV2A_ADDR
|
||||
#define NV2A_MEMORY_SIZE 0x01000000 // See NV2A_SIZE
|
||||
#define NV2A_PRAMIN_ADDR 0xFD700000
|
||||
#define NV2A_PRAMIN_SIZE 0x100000
|
||||
#define NV2A_USER_ADDR 0xFD800000
|
||||
#define NV2A_USER_SIZE 0x800000
|
||||
#define APU_BASE 0xFE800000
|
||||
#define APU_SIZE 0x80000
|
||||
#define AC97_BASE 0xFEC00000
|
||||
#define AC97_SIZE 0x1000
|
||||
#define USB0_BASE 0xFED00000
|
||||
#define USB0_SIZE 0x1000
|
||||
#define USB1_BASE 0xFED08000
|
||||
#define USB1_SIZE 0x1000
|
||||
#define NVNet_BASE 0xFEF00000
|
||||
#define NVNet_SIZE 0x400
|
||||
#define BIOS_BASE 0xFF000000
|
||||
#define BIOS_XBOX_SIZE 0xFFFE00
|
||||
#define BIOS_CHIHIRO_SIZE 0x1000000
|
||||
#define MCPX_BASE 0xFFFFFE00
|
||||
#define MCPX_SIZE 0x200
|
||||
#define MAX_VIRTUAL_ADDRESS 0xFFFFFFFF
|
||||
|
||||
/*! memory size per system */
|
||||
#define XBOX_MEMORY_SIZE (64 * ONE_MB)
|
||||
|
@ -97,6 +123,10 @@ extern "C" {
|
|||
#define XBOX_FLASH_ROM_BASE 0xFFF00000
|
||||
#define XBOX_FLASH_ROM_SIZE 0x00100000 // - 0xFFFFFFF
|
||||
|
||||
#define HIGHEST_USER_ADDRESS 0x7FFEFFFF
|
||||
#define HIGHEST_VAD_ADDRESS HIGHEST_USER_ADDRESS - X64KB // for NtAllocateVirtualMemory
|
||||
|
||||
|
||||
// For now, virtual addresses are somewhat limited, as we use
|
||||
// these soley for loading XBE sections. The largest that we
|
||||
// know of, is "BLiNX: the time sweeper", which has a section
|
||||
|
@ -194,7 +224,6 @@ extern char* CxbxKrnl_DebugFileName;
|
|||
/*! file paths */
|
||||
extern char szFilePath_CxbxReloaded_Exe[MAX_PATH];
|
||||
extern char szFolder_CxbxReloadedData[MAX_PATH];
|
||||
extern char szFilePath_LaunchDataPage_bin[MAX_PATH];
|
||||
extern char szFilePath_EEPROM_bin[MAX_PATH];
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace xboxkrnl
|
|||
#include "EmuShared.h"
|
||||
#include "DbgConsole.h"
|
||||
#include "ResourceTracker.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
#include "EmuXTL.h"
|
||||
#include "HLEDatabase.h"
|
||||
#include "Logging.h"
|
||||
|
@ -862,49 +862,49 @@ int GetD3DResourceRefCount(XTL::IDirect3DResource8 *EmuResource)
|
|||
|
||||
XTL::X_D3DSurface *EmuNewD3DSurface()
|
||||
{
|
||||
XTL::X_D3DSurface *result = (XTL::X_D3DSurface *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DSurface));
|
||||
XTL::X_D3DSurface *result = (XTL::X_D3DSurface *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DSurface));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_SURFACE | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DTexture *EmuNewD3DTexture()
|
||||
{
|
||||
XTL::X_D3DTexture *result = (XTL::X_D3DTexture *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DTexture));
|
||||
XTL::X_D3DTexture *result = (XTL::X_D3DTexture *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DTexture));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DVolumeTexture *EmuNewD3DVolumeTexture()
|
||||
{
|
||||
XTL::X_D3DVolumeTexture *result = (XTL::X_D3DVolumeTexture *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DVolumeTexture));
|
||||
XTL::X_D3DVolumeTexture *result = (XTL::X_D3DVolumeTexture *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DVolumeTexture));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DCubeTexture *EmuNewD3DCubeTexture()
|
||||
{
|
||||
XTL::X_D3DCubeTexture *result = (XTL::X_D3DCubeTexture *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DCubeTexture));
|
||||
XTL::X_D3DCubeTexture *result = (XTL::X_D3DCubeTexture *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DCubeTexture));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DIndexBuffer *EmuNewD3DIndexBuffer()
|
||||
{
|
||||
XTL::X_D3DIndexBuffer *result = (XTL::X_D3DIndexBuffer *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DIndexBuffer));
|
||||
XTL::X_D3DIndexBuffer *result = (XTL::X_D3DIndexBuffer *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DIndexBuffer));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_INDEXBUFFER | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DVertexBuffer *EmuNewD3DVertexBuffer()
|
||||
{
|
||||
XTL::X_D3DVertexBuffer *result = (XTL::X_D3DVertexBuffer *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DVertexBuffer));
|
||||
XTL::X_D3DVertexBuffer *result = (XTL::X_D3DVertexBuffer *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DVertexBuffer));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_VERTEXBUFFER | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
||||
XTL::X_D3DPalette *EmuNewD3DPalette()
|
||||
{
|
||||
XTL::X_D3DPalette *result = (XTL::X_D3DPalette *)g_MemoryManager.AllocateZeroed(1, sizeof(XTL::X_D3DPalette));
|
||||
XTL::X_D3DPalette *result = (XTL::X_D3DPalette *)g_VMManager.AllocateZeroed(sizeof(XTL::X_D3DPalette));
|
||||
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_PALETTE | 1; // Set refcount to 1
|
||||
return result;
|
||||
}
|
||||
|
@ -3398,8 +3398,8 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
|||
LOG_FUNC_END;
|
||||
|
||||
// create emulated shader struct
|
||||
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader*)g_MemoryManager.AllocateZeroed(1, sizeof(X_D3DVertexShader));
|
||||
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER*)g_MemoryManager.AllocateZeroed(1, sizeof(VERTEX_SHADER));
|
||||
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader*)g_VMManager.AllocateZeroed(sizeof(X_D3DVertexShader));
|
||||
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER*)g_VMManager.AllocateZeroed(sizeof(VERTEX_SHADER));
|
||||
|
||||
// TODO: Intelligently fill out these fields as necessary
|
||||
|
||||
|
@ -3501,7 +3501,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
|||
|
||||
free(pRecompiledDeclaration);
|
||||
|
||||
pVertexShader->pDeclaration = (DWORD*)g_MemoryManager.Allocate(DeclarationSize);
|
||||
pVertexShader->pDeclaration = (DWORD*)g_VMManager.Allocate(DeclarationSize);
|
||||
memcpy(pVertexShader->pDeclaration, pDeclaration, DeclarationSize);
|
||||
|
||||
pVertexShader->FunctionSize = 0;
|
||||
|
@ -3514,7 +3514,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
|||
{
|
||||
if(pFunction != NULL)
|
||||
{
|
||||
pVertexShader->pFunction = (DWORD*)g_MemoryManager.Allocate(VertexShaderSize);
|
||||
pVertexShader->pFunction = (DWORD*)g_VMManager.Allocate(VertexShaderSize);
|
||||
memcpy(pVertexShader->pFunction, pFunction, VertexShaderSize);
|
||||
pVertexShader->FunctionSize = VertexShaderSize;
|
||||
}
|
||||
|
@ -4035,7 +4035,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateTexture)
|
|||
|
||||
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture
|
||||
Texture_Data = X_D3DRESOURCE_DATA_YUV_SURFACE;
|
||||
pTexture->Lock = (DWORD)g_MemoryManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
pTexture->Lock = (DWORD)g_VMManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
|
||||
g_pCachedYuvSurface = (X_D3DSurface*)pTexture;
|
||||
|
||||
|
@ -4185,7 +4185,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVolumeTexture)
|
|||
|
||||
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture
|
||||
(*ppVolumeTexture)->Data = X_D3DRESOURCE_DATA_YUV_SURFACE;
|
||||
(*ppVolumeTexture)->Lock = (DWORD)g_MemoryManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
(*ppVolumeTexture)->Lock = (DWORD)g_VMManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
(*ppVolumeTexture)->Format = Format << X_D3DFORMAT_FORMAT_SHIFT;
|
||||
|
||||
(*ppVolumeTexture)->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK)
|
||||
|
@ -4644,7 +4644,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_Begin)
|
|||
|
||||
if(g_IVBTable == nullptr)
|
||||
{
|
||||
g_IVBTable = (struct XTL::_D3DIVB*)g_MemoryManager.Allocate(sizeof(XTL::_D3DIVB)*IVB_TABLE_SIZE);
|
||||
g_IVBTable = (struct XTL::_D3DIVB*)g_VMManager.Allocate(sizeof(XTL::_D3DIVB)*IVB_TABLE_SIZE);
|
||||
}
|
||||
|
||||
g_IVBTblOffs = 0;
|
||||
|
@ -4655,7 +4655,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_Begin)
|
|||
|
||||
if(g_pIVBVertexBuffer == nullptr)
|
||||
{
|
||||
g_pIVBVertexBuffer = (DWORD*)g_MemoryManager.Allocate(IVB_BUFFER_SIZE);
|
||||
g_pIVBVertexBuffer = (DWORD*)g_VMManager.Allocate(IVB_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5209,7 +5209,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
|
||||
// create vertex buffer
|
||||
{
|
||||
DWORD dwSize = g_MemoryManager.QueryAllocationSize(pBase);
|
||||
DWORD dwSize = g_VMManager.QuerySize((VAddr)pBase);
|
||||
|
||||
if(dwSize == -1)
|
||||
{
|
||||
|
@ -5273,7 +5273,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
|
||||
// create push buffer
|
||||
{
|
||||
DWORD dwSize = g_MemoryManager.QueryAllocationSize(pBase);
|
||||
DWORD dwSize = g_VMManager.QuerySize((VAddr)pBase);
|
||||
|
||||
if(dwSize == -1)
|
||||
{
|
||||
|
@ -5425,7 +5425,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture
|
||||
// Note : This is the only change to the pResource argument passed into D3DResource_Register !
|
||||
pPixelContainer->Data = X_D3DRESOURCE_DATA_YUV_SURFACE;
|
||||
pPixelContainer->Lock = (DWORD)g_MemoryManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
pPixelContainer->Lock = (DWORD)g_VMManager.Allocate(g_dwOverlayP * g_dwOverlayH);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5955,7 +5955,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
|||
g_pCachedYuvSurface = NULL;
|
||||
|
||||
// free memory associated with this special resource handle
|
||||
g_MemoryManager.Free((PVOID)pThis->Lock);
|
||||
g_VMManager.Deallocate((VAddr)pThis->Lock);
|
||||
}
|
||||
|
||||
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
||||
|
@ -5970,7 +5970,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
|||
|
||||
if(pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
|
||||
{
|
||||
g_MemoryManager.Free((void*)pThis->Data);
|
||||
g_VMManager.Deallocate((VAddr)pThis->Data);
|
||||
uRet = --pThis->Lock; // TODO : This makes no sense (as it mangles X_D3DRESOURCE_LOCK_PALETTE) but crashes otherwise?!
|
||||
}
|
||||
else if(pHostResource != nullptr)
|
||||
|
@ -8527,7 +8527,7 @@ XTL::X_D3DPalette * WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette2)
|
|||
X_D3DPalette *pPalette = EmuNewD3DPalette();
|
||||
|
||||
pPalette->Common |= (Size << X_D3DPALETTE_COMMON_PALETTESIZE_SHIFT);
|
||||
pPalette->Data = (DWORD)g_MemoryManager.AllocateContiguous(XboxD3DPaletteSizeToBytes(Size), PAGE_SIZE);
|
||||
pPalette->Data = (DWORD)g_VMManager.Allocate(XboxD3DPaletteSizeToBytes(Size), 0, (~((::ULONG_PTR)0)), PAGE_SIZE, PAGE_EXECUTE_READWRITE, false);
|
||||
pPalette->Lock = X_D3DRESOURCE_LOCK_PALETTE; // emulated reference count for palettes
|
||||
|
||||
// TODO: Should't we register the palette with a call to
|
||||
|
@ -8701,17 +8701,17 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DeleteVertexShader)
|
|||
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
|
||||
|
||||
RealHandle = pVertexShader->Handle;
|
||||
g_MemoryManager.Free(pVertexShader->pDeclaration);
|
||||
g_VMManager.Deallocate((VAddr)pVertexShader->pDeclaration);
|
||||
|
||||
if(pVertexShader->pFunction)
|
||||
{
|
||||
g_MemoryManager.Free(pVertexShader->pFunction);
|
||||
g_VMManager.Deallocate((VAddr)pVertexShader->pFunction);
|
||||
}
|
||||
|
||||
FreeVertexDynamicPatch(pVertexShader);
|
||||
|
||||
g_MemoryManager.Free(pVertexShader);
|
||||
g_MemoryManager.Free(pD3DVertexShader);
|
||||
g_VMManager.Deallocate((VAddr)pVertexShader);
|
||||
g_VMManager.Deallocate((VAddr)pD3DVertexShader);
|
||||
}
|
||||
|
||||
HRESULT hRet = g_pD3DDevice8->DeleteVertexShader(RealHandle);
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
#include "CxbxKrnl/Emu.h"
|
||||
#include "CxbxKrnl/EmuFS.h"
|
||||
#include "CxbxKrnl/EmuXTL.h"
|
||||
#include <CxbxKrnl/MemoryManager.h>
|
||||
|
||||
//#include <CxbxKrnl/EmuD3D8Types.h> // X_PSH_COMBINECOUNT
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "CxbxKrnl/EmuXTL.h"
|
||||
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DFORMAT
|
||||
#include "CxbxKrnl/ResourceTracker.h"
|
||||
#include "CxbxKrnl/MemoryManager.h"
|
||||
|
||||
uint32 XTL::g_dwPrimaryPBCount = 0;
|
||||
uint32 *XTL::g_pPrimaryPB = 0;
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
#define _CXBXKRNL_INTERNAL
|
||||
#define _XBOXKRNL_DEFEXTRN_
|
||||
|
||||
#include "CxbxKrnl/VMManager.h"
|
||||
#include "CxbxKrnl/xxhash32.h" // For XXHash32::hash()
|
||||
#include "CxbxKrnl/Emu.h"
|
||||
#include "CxbxKrnl/EmuXTL.h"
|
||||
#include "CxbxKrnl/ResourceTracker.h"
|
||||
#include "CxbxKrnl/MemoryManager.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
|
@ -468,7 +468,7 @@ bool XTL::VertexPatcher::PatchStream(VertexPatchDesc *pPatchDesc,
|
|||
uiVertexCount = pPatchDesc->dwVertexCount;
|
||||
dwNewSize = uiVertexCount * pStreamPatch->ConvertedStride;
|
||||
pNewVertexBuffer = NULL;
|
||||
pNewData = (uint08*)g_MemoryManager.Allocate(dwNewSize);
|
||||
pNewData = (uint08*)g_VMManager.Allocate(dwNewSize);
|
||||
if(!pNewData)
|
||||
{
|
||||
CxbxKrnlCleanup("Couldn't allocate the new stream zero buffer");
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "CxbxKrnl/Emu.h"
|
||||
#include "CxbxKrnl/EmuFS.h"
|
||||
#include "CxbxKrnl/EmuXTL.h"
|
||||
#include "CxbxKrnl/MemoryManager.h"
|
||||
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DVSDE_*
|
||||
|
||||
// ****************************************************************************
|
||||
|
|
|
@ -49,7 +49,6 @@ namespace xboxkrnl {
|
|||
#include "EmuFS.h"
|
||||
#include "EmuShared.h"
|
||||
#include "EmuXTL.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include <mmreg.h>
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace xboxkrnl
|
|||
#include "EmuKrnl.h" // For InitializeListHead(), etc.
|
||||
#include "EmuFS.h"
|
||||
#include "CxbxKrnl.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#undef FIELD_OFFSET // prevent macro redefinition warnings
|
||||
#include <windows.h>
|
||||
|
@ -404,7 +404,9 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
}
|
||||
}
|
||||
|
||||
pNewTLS = g_MemoryManager.AllocateZeroed(1, dwCopySize + dwZeroSize + 0x100 /* + HACK: extra safety padding 0x100*/);
|
||||
/* + HACK: extra safety padding 0x100 */
|
||||
pNewTLS = (void*)g_VMManager.AllocateZeroed(dwCopySize + dwZeroSize + 0x100);
|
||||
|
||||
|
||||
if (dwCopySize > 0) {
|
||||
memcpy(pNewTLS, pTLSData, dwCopySize);
|
||||
|
@ -446,7 +448,7 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
}
|
||||
|
||||
// Allocate the xbox KPCR structure
|
||||
xboxkrnl::KPCR *NewPcr = (xboxkrnl::KPCR*)g_MemoryManager.AllocateZeroed(1, sizeof(xboxkrnl::KPCR));
|
||||
xboxkrnl::KPCR *NewPcr = (xboxkrnl::KPCR*)g_VMManager.AllocateZeroed(sizeof(xboxkrnl::KPCR));
|
||||
xboxkrnl::NT_TIB *XbTib = &(NewPcr->NtTib);
|
||||
xboxkrnl::PKPRCB Prcb = &(NewPcr->PrcbData);
|
||||
// Note : As explained above (at EmuKeSetPcr), Cxbx cannot allocate one NT_TIB and KPRCB
|
||||
|
@ -488,7 +490,7 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
|
||||
// Initialize a fake PrcbData.CurrentThread
|
||||
{
|
||||
xboxkrnl::ETHREAD *EThread = (xboxkrnl::ETHREAD*)g_MemoryManager.AllocateZeroed(1, sizeof(xboxkrnl::ETHREAD)); // Clear, to prevent side-effects on random contents
|
||||
xboxkrnl::ETHREAD *EThread = (xboxkrnl::ETHREAD*)g_VMManager.AllocateZeroed(sizeof(xboxkrnl::ETHREAD)); // Clear, to prevent side-effects on random contents
|
||||
|
||||
EThread->Tcb.TlsData = pNewTLS;
|
||||
EThread->UniqueThread = GetCurrentThreadId();
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include <ntstatus.h>
|
||||
#pragma warning(default:4005)
|
||||
#include "CxbxKrnl.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include <experimental/filesystem>
|
||||
|
||||
|
@ -710,7 +710,7 @@ EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(const HANDLE Handl
|
|||
void _CxbxPVOIDDeleter(PVOID *ptr)
|
||||
{
|
||||
if (*ptr)
|
||||
g_MemoryManager.Free(*ptr);
|
||||
g_VMManager.Deallocate((VAddr)*ptr);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -728,7 +728,7 @@ NtDll::FILE_LINK_INFORMATION * _XboxToNTLinkInfo(xboxkrnl::FILE_LINK_INFORMATION
|
|||
|
||||
// Build the native FILE_LINK_INFORMATION struct
|
||||
*Length = sizeof(NtDll::FILE_LINK_INFORMATION) + convertedFileName.size() * sizeof(wchar_t);
|
||||
NtDll::FILE_LINK_INFORMATION *ntLinkInfo = (NtDll::FILE_LINK_INFORMATION *) g_MemoryManager.AllocateZeroed(1, *Length);
|
||||
NtDll::FILE_LINK_INFORMATION *ntLinkInfo = (NtDll::FILE_LINK_INFORMATION *) g_VMManager.AllocateZeroed(*Length);
|
||||
ntLinkInfo->ReplaceIfExists = xboxLinkInfo->ReplaceIfExists;
|
||||
ntLinkInfo->RootDirectory = RootDirectory;
|
||||
ntLinkInfo->FileNameLength = convertedFileName.size() * sizeof(wchar_t);
|
||||
|
@ -748,7 +748,7 @@ NtDll::FILE_RENAME_INFORMATION * _XboxToNTRenameInfo(xboxkrnl::FILE_RENAME_INFOR
|
|||
|
||||
// Build the native FILE_RENAME_INFORMATION struct
|
||||
*Length = sizeof(NtDll::FILE_RENAME_INFORMATION) + convertedFileName.size() * sizeof(wchar_t);
|
||||
NtDll::FILE_RENAME_INFORMATION *ntRenameInfo = (NtDll::FILE_RENAME_INFORMATION *) g_MemoryManager.AllocateZeroed(1, *Length);
|
||||
NtDll::FILE_RENAME_INFORMATION *ntRenameInfo = (NtDll::FILE_RENAME_INFORMATION *) g_VMManager.AllocateZeroed(*Length);
|
||||
ntRenameInfo->ReplaceIfExists = xboxRenameInfo->ReplaceIfExists;
|
||||
ntRenameInfo->RootDirectory = RootDirectory;
|
||||
ntRenameInfo->FileNameLength = convertedFileName.size() * sizeof(wchar_t);
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace xboxkrnl
|
|||
|
||||
#include "Logging.h" // For LOG_FUNC()
|
||||
#include "EmuKrnlLogging.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace NtDll
|
||||
|
|
|
@ -42,13 +42,13 @@
|
|||
// prevent name collisions
|
||||
namespace xboxkrnl
|
||||
{
|
||||
#include <xboxkrnl/xboxkrnl.h> // For ExAllocatePool, etc.
|
||||
#include <xboxkrnl/xboxkrnl.h> // For ExAllocatePool, etc.
|
||||
};
|
||||
|
||||
#include "Logging.h" // For LOG_FUNC()
|
||||
#include "EmuEEPROM.h" // For EmuFindEEPROMInfo, EEPROM, XboxFactoryGameRegion
|
||||
#include "EmuKrnlLogging.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace NtDll
|
||||
|
@ -128,7 +128,7 @@ XBSYSAPI EXPORTNUM(15) xboxkrnl::PVOID NTAPI xboxkrnl::ExAllocatePoolWithTag
|
|||
LOG_FUNC_ARG(Tag)
|
||||
LOG_FUNC_END;
|
||||
|
||||
PVOID pRet = g_MemoryManager.AllocateZeroed(1, NumberOfBytes); // Clear, to prevent side-effects on random contents
|
||||
PVOID pRet = (xboxkrnl::PVOID)g_VMManager.AllocateZeroed(NumberOfBytes); // Clear, to prevent side-effects on random contents
|
||||
|
||||
LOG_INCOMPLETE(); // TODO : Actually implement ExAllocatePoolWithTag
|
||||
|
||||
|
@ -159,7 +159,7 @@ XBSYSAPI EXPORTNUM(17) xboxkrnl::VOID NTAPI xboxkrnl::ExFreePool
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(P);
|
||||
|
||||
g_MemoryManager.Free(P);
|
||||
g_VMManager.Deallocate((VAddr)P);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
// *
|
||||
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
||||
// * (c) 2016 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||
// * (c) 2017 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
|
@ -50,7 +51,8 @@ namespace xboxkrnl
|
|||
#include "EmuKrnlLogging.h"
|
||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
#include "EmuShared.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace NtDll
|
||||
|
@ -70,7 +72,7 @@ XBSYSAPI EXPORTNUM(102) xboxkrnl::PVOID xboxkrnl::MmGlobalData[8] = { NULL, NULL
|
|||
// the xbox kernel. Kernel code accessses this as a normal variable.
|
||||
// XAPI code however, reference to the address of this kernel variable,
|
||||
// thus use indirection (*LaunchDataPage) to get to the same contents.
|
||||
XBSYSAPI EXPORTNUM(164) xboxkrnl::PLAUNCH_DATA_PAGE xboxkrnl::LaunchDataPage = NULL;
|
||||
XBSYSAPI EXPORTNUM(164) xboxkrnl::PLAUNCH_DATA_PAGE xboxkrnl::LaunchDataPage = xbnull;
|
||||
|
||||
// ******************************************************************
|
||||
// * 0x00A5 - MmAllocateContiguousMemory()
|
||||
|
@ -110,30 +112,34 @@ XBSYSAPI EXPORTNUM(166) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
|
|||
LOG_FUNC_ARG(HighestAcceptableAddress)
|
||||
LOG_FUNC_ARG(Alignment)
|
||||
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
PVOID pRet = (PVOID)1; // Marker, never returned, overwritten with NULL on input error
|
||||
|
||||
// size must be > 0
|
||||
if (NumberOfBytes == 0)
|
||||
pRet = xbnull;
|
||||
|
||||
if (Alignment < PAGE_SIZE)
|
||||
Alignment = PAGE_SIZE; // page boundary at least
|
||||
|
||||
// Only known flags are allowed
|
||||
if ((ProtectionType & ~PAGE_KNOWN_FLAGS) != 0)
|
||||
pRet = NULL;
|
||||
pRet = xbnull;
|
||||
|
||||
// Either PAGE_READONLY or PAGE_READWRITE must be set (not both, nor none)
|
||||
if (((ProtectionType & PAGE_READONLY) > 0) == ((ProtectionType & PAGE_READWRITE) > 0))
|
||||
pRet = NULL;
|
||||
pRet = xbnull;
|
||||
|
||||
// Combining PAGE_NOCACHE and PAGE_WRITECOMBINE isn't allowed
|
||||
if ((ProtectionType & (PAGE_NOCACHE | PAGE_WRITECOMBINE)) == (PAGE_NOCACHE | PAGE_WRITECOMBINE))
|
||||
pRet = NULL;
|
||||
pRet = xbnull;
|
||||
|
||||
// Allocate when input arguments are valid
|
||||
if (pRet != NULL)
|
||||
if (pRet != xbnull)
|
||||
{
|
||||
// TODO : Allocate differently if(ProtectionType & PAGE_WRITECOMBINE)
|
||||
pRet = g_MemoryManager.AllocateContiguous(NumberOfBytes, Alignment);
|
||||
pRet = (PVOID)g_VMManager.Allocate(NumberOfBytes, LowestAcceptableAddress, HighestAcceptableAddress, Alignment, ProtectionType, false);
|
||||
}
|
||||
|
||||
RETURN(pRet);
|
||||
|
@ -151,10 +157,10 @@ XBSYSAPI EXPORTNUM(167) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateSystemMemory
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(Protect)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
// TODO: should this be aligned?
|
||||
PVOID pRet = g_MemoryManager.Allocate(NumberOfBytes);
|
||||
// TODO: this should probably allocate the memory at a specific system virtual address region...
|
||||
PVOID pRet = (PVOID)g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, Protect);
|
||||
|
||||
RETURN(pRet);
|
||||
}
|
||||
|
@ -171,13 +177,18 @@ XBSYSAPI EXPORTNUM(168) xboxkrnl::PVOID NTAPI xboxkrnl::MmClaimGpuInstanceMemory
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG_OUT(NumberOfPaddingBytes)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
if (g_bIsChihiro)
|
||||
unsigned int highest_physical_page = MM_XBOX_HIGHEST_PHYSICAL_PAGE;
|
||||
unsigned int instance_physical_page = MM_XBOX_INSTANCE_PHYSICAL_PAGE;
|
||||
if (g_bIsChihiro || g_bIsDebug)
|
||||
{
|
||||
*NumberOfPaddingBytes = 0;
|
||||
highest_physical_page = MM_CHIHIRO_HIGHEST_PHYSICAL_PAGE;
|
||||
}
|
||||
else
|
||||
*NumberOfPaddingBytes = MI_CONVERT_PFN_TO_PHYSICAL(MM_64M_PHYSICAL_PAGE) -
|
||||
MI_CONVERT_PFN_TO_PHYSICAL(MM_INSTANCE_PHYSICAL_PAGE + MM_INSTANCE_PAGE_COUNT);
|
||||
MI_CONVERT_PFN_TO_PHYSICAL(instance_physical_page + MM_INSTANCE_PAGE_COUNT);
|
||||
|
||||
DbgPrintf("KNRL: MmClaimGpuInstanceMemory : *NumberOfPaddingBytes = 0x%.8X\n", *NumberOfPaddingBytes);
|
||||
|
||||
|
@ -189,7 +200,7 @@ XBSYSAPI EXPORTNUM(168) xboxkrnl::PVOID NTAPI xboxkrnl::MmClaimGpuInstanceMemory
|
|||
}
|
||||
#endif
|
||||
|
||||
PVOID Result = (PUCHAR)MI_CONVERT_PFN_TO_PHYSICAL(MM_HIGHEST_PHYSICAL_PAGE + 1)
|
||||
PVOID Result = (PUCHAR)MI_CONVERT_PFN_TO_PHYSICAL(highest_physical_page + 1)
|
||||
- *NumberOfPaddingBytes;
|
||||
|
||||
RETURN(Result);
|
||||
|
@ -209,41 +220,21 @@ XBSYSAPI EXPORTNUM(169) xboxkrnl::PVOID NTAPI xboxkrnl::MmCreateKernelStack
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(DebuggerThread)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
NtDll::PVOID BaseAddress = NULL;
|
||||
|
||||
if (!NumberOfBytes) {
|
||||
// NumberOfBytes cannot be zero when passed to NtAllocateVirtualMemory() below
|
||||
CxbxKrnlCleanup("Assertion: 'NumberOfBytes != 0' in MmCreateKernelStack()");
|
||||
}
|
||||
|
||||
if (NumberOfBytes & 0xFF) {
|
||||
// Validate NumberOfBytes for alignment with the page size
|
||||
CxbxKrnlCleanup("Assertion: '(NumberOfBytes & (PAGE_SIZE -1)) == 0' in MmCreateKernelStack()");
|
||||
}
|
||||
VAddr addr = xbnull;
|
||||
|
||||
/**
|
||||
* Function at present does not:
|
||||
* - Create an additional guard PAGE_SIZE after allocation,
|
||||
* - Fill allocation with any values
|
||||
* - Treat DebuggerThread any differently
|
||||
*/
|
||||
|
||||
NTSTATUS ret = NtDll::NtAllocateVirtualMemory(
|
||||
/*ProcessHandle=*/g_CurrentProcessHandle,
|
||||
/*BaseAddress=*/&BaseAddress,
|
||||
/*ZeroBits=*/0,
|
||||
/*RegionSize=*/&NumberOfBytes,
|
||||
/*AllocationType=*/MEM_COMMIT,
|
||||
/*Protect=*/PAGE_READWRITE);
|
||||
if (NumberOfBytes)
|
||||
{
|
||||
addr = g_VMManager.AllocateStack(NumberOfBytes);
|
||||
}
|
||||
|
||||
if (FAILED(ret))
|
||||
EmuWarning("MmCreateKernelStack failed!");
|
||||
else
|
||||
BaseAddress = (PVOID)((ULONG)BaseAddress + NumberOfBytes);
|
||||
|
||||
RETURN(BaseAddress);
|
||||
RETURN((PVOID)addr);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -251,25 +242,20 @@ XBSYSAPI EXPORTNUM(169) xboxkrnl::PVOID NTAPI xboxkrnl::MmCreateKernelStack
|
|||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(170) xboxkrnl::VOID NTAPI xboxkrnl::MmDeleteKernelStack
|
||||
(
|
||||
PVOID EndAddress,
|
||||
PVOID BaseAddress
|
||||
PVOID StackBase,
|
||||
PVOID StackLimit
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(EndAddress)
|
||||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_ARG(StackBase)
|
||||
LOG_FUNC_ARG(StackLimit)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// TODO : Untested
|
||||
ULONG RegionSize = 0;
|
||||
NTSTATUS ret = NtDll::NtFreeVirtualMemory(
|
||||
/*ProcessHandle=*/g_CurrentProcessHandle,
|
||||
&BaseAddress,
|
||||
&RegionSize,
|
||||
/*FreeType=*/MEM_RELEASE);
|
||||
size_t ActualSize = ((VAddr)StackBase - (VAddr)StackLimit) + PAGE_SIZE;
|
||||
|
||||
if (FAILED(ret))
|
||||
EmuWarning("MmDeleteKernelStack failed!");
|
||||
VAddr StackBottom = (VAddr)StackBase - ActualSize;
|
||||
|
||||
g_VMManager.DeallocateStack(StackBottom);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -285,13 +271,7 @@ XBSYSAPI EXPORTNUM(171) xboxkrnl::VOID NTAPI xboxkrnl::MmFreeContiguousMemory
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(BaseAddress);
|
||||
|
||||
if (BaseAddress == &DefaultLaunchDataPage) {
|
||||
DbgPrintf("KNRL: Ignored MmFreeContiguousMemory(&DefaultLaunchDataPage)\n");
|
||||
LOG_IGNORED();
|
||||
return;
|
||||
}
|
||||
|
||||
g_MemoryManager.Free(BaseAddress);
|
||||
g_VMManager.Deallocate((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
|
||||
|
@ -311,9 +291,9 @@ XBSYSAPI EXPORTNUM(172) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmFreeSystemMemory
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
g_MemoryManager.Free(BaseAddress);
|
||||
g_VMManager.Deallocate((VAddr)BaseAddress);
|
||||
|
||||
RETURN(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -335,8 +315,7 @@ XBSYSAPI EXPORTNUM(173) xboxkrnl::PHYSICAL_ADDRESS NTAPI xboxkrnl::MmGetPhysical
|
|||
// MmLockUnlockBufferPages, emulate this???
|
||||
LOG_INCOMPLETE();
|
||||
|
||||
// We emulate Virtual/Physical memory 1:1
|
||||
return (PHYSICAL_ADDRESS)BaseAddress;
|
||||
return g_VMManager.TranslateVAddr((VAddr)BaseAddress);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -349,9 +328,14 @@ XBSYSAPI EXPORTNUM(174) xboxkrnl::BOOLEAN NTAPI xboxkrnl::MmIsAddressValid
|
|||
{
|
||||
LOG_FUNC_ONE_ARG_OUT(VirtualAddress);
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
BOOLEAN Ret = FALSE;
|
||||
|
||||
RETURN(TRUE);
|
||||
if (g_VMManager.QueryVAddr((VAddr)VirtualAddress))
|
||||
{
|
||||
Ret = TRUE;
|
||||
}
|
||||
|
||||
RETURN(Ret);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -368,8 +352,9 @@ XBSYSAPI EXPORTNUM(175) xboxkrnl::VOID NTAPI xboxkrnl::MmLockUnlockBufferPages
|
|||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(Protect)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
// REMARK: all the pages inside the main memory pool are non-relocatable so, for the moment, this function is pointless
|
||||
LOG_IGNORED();
|
||||
}
|
||||
|
||||
|
@ -385,8 +370,9 @@ XBSYSAPI EXPORTNUM(176) xboxkrnl::VOID NTAPI xboxkrnl::MmLockUnlockPhysicalPage
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(PhysicalAddress)
|
||||
LOG_FUNC_ARG(UnlockPage)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
// REMARK: all the pages inside the main memory pool are non-relocatable so, for the moment, this function is pointless
|
||||
LOG_IGNORED();
|
||||
}
|
||||
|
||||
|
@ -412,7 +398,7 @@ XBSYSAPI EXPORTNUM(177) xboxkrnl::PVOID NTAPI xboxkrnl::MmMapIoSpace
|
|||
LOG_FUNC_ARG(PhysicalAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(ProtectionType)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
PVOID pRet;
|
||||
|
||||
|
@ -422,8 +408,7 @@ XBSYSAPI EXPORTNUM(177) xboxkrnl::PVOID NTAPI xboxkrnl::MmMapIoSpace
|
|||
pRet = (PVOID)PhysicalAddress;
|
||||
}
|
||||
else {
|
||||
// TODO: should this be aligned?
|
||||
pRet = g_MemoryManager.Allocate(NumberOfBytes);
|
||||
g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, ProtectionType);
|
||||
LOG_INCOMPLETE();
|
||||
}
|
||||
|
||||
|
@ -444,27 +429,21 @@ XBSYSAPI EXPORTNUM(178) xboxkrnl::VOID NTAPI xboxkrnl::MmPersistContiguousMemory
|
|||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(Persist)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
if (BaseAddress == LaunchDataPage)
|
||||
{
|
||||
PAddr LaunchDataPAddr = g_VMManager.TranslateVAddr((VAddr)BaseAddress);
|
||||
if (Persist)
|
||||
{
|
||||
FILE* fp = fopen(szFilePath_LaunchDataPage_bin, "wb"); // TODO : Support wide char paths using _wfopen
|
||||
if (fp)
|
||||
{
|
||||
DbgPrintf("KNRL: Persisting LaunchDataPage\n");
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fwrite(LaunchDataPage, sizeof(LAUNCH_DATA_PAGE), 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
DbgPrintf("KNRL: Can't persist LaunchDataPage to %s!\n", szFilePath_LaunchDataPage_bin);
|
||||
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||
DbgPrintf("KNRL: Persisting LaunchDataPage\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LaunchDataPAddr = NULL;
|
||||
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||
DbgPrintf("KNRL: Forgetting LaunchDataPage\n");
|
||||
remove(szFilePath_LaunchDataPage_bin);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -494,12 +473,7 @@ XBSYSAPI EXPORTNUM(179) xboxkrnl::ULONG NTAPI xboxkrnl::MmQueryAddressProtect
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(VirtualAddress);
|
||||
|
||||
// Assume read/write when page is allocated :
|
||||
ULONG Result = PAGE_NOACCESS;
|
||||
|
||||
if (g_MemoryManager.IsAllocated(VirtualAddress)) {
|
||||
Result = PAGE_READWRITE;
|
||||
}
|
||||
ULONG Result = g_VMManager.QueryProtection((VAddr)VirtualAddress);
|
||||
|
||||
LOG_INCOMPLETE(); // TODO : Improve the MmQueryAddressProtect implementation
|
||||
|
||||
|
@ -516,9 +490,7 @@ XBSYSAPI EXPORTNUM(180) xboxkrnl::ULONG NTAPI xboxkrnl::MmQueryAllocationSize
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(BaseAddress);
|
||||
|
||||
LOG_INCOMPLETE(); // TODO : Free PAGE_WRITECOMBINE differently
|
||||
|
||||
ULONG uiSize = g_MemoryManager.QueryAllocationSize(BaseAddress);
|
||||
ULONG uiSize = g_VMManager.QuerySize((VAddr)BaseAddress);
|
||||
|
||||
RETURN(uiSize);
|
||||
}
|
||||
|
@ -533,30 +505,20 @@ XBSYSAPI EXPORTNUM(181) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmQueryStatistics
|
|||
{
|
||||
LOG_FUNC_ONE_ARG_OUT(MemoryStatistics);
|
||||
|
||||
MEMORYSTATUSEX MemoryStatus;
|
||||
SYSTEM_INFO SysInfo;
|
||||
NTSTATUS ret;
|
||||
|
||||
#ifdef _DEBUG_TRACE
|
||||
if (!MemoryStatistics)
|
||||
{
|
||||
DbgPrintf("KNRL: MmQueryStatistics : PMM_STATISTICS MemoryStatistics is nullptr!\n");
|
||||
LOG_IGNORED();
|
||||
RETURN(STATUS_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MemoryStatistics->Length == sizeof(MM_STATISTICS))
|
||||
{
|
||||
GlobalMemoryStatusEx(&MemoryStatus);
|
||||
GetSystemInfo(&SysInfo);
|
||||
|
||||
/**
|
||||
* When each of the PMM_STATISTICS MemoryStatistics elements
|
||||
* are setup correctly below, these two lines become redundant
|
||||
*/
|
||||
ZeroMemory(MemoryStatistics, sizeof(MM_STATISTICS));
|
||||
//MemoryStatistics->Length = sizeof(MM_STATISTICS);
|
||||
|
||||
MemoryStatistics->TotalPhysicalPages = (ULONG)(MemoryStatus.ullTotalPhys / SysInfo.dwPageSize);
|
||||
MemoryStatistics->AvailablePages = (ULONG)(MemoryStatus.ullAvailPhys / SysInfo.dwPageSize);
|
||||
MemoryStatistics->VirtualMemoryBytesCommitted = (ULONG)(MemoryStatus.ullTotalVirtual - MemoryStatus.ullAvailVirtual);
|
||||
MemoryStatistics->VirtualMemoryBytesReserved = (ULONG)(MemoryStatus.ullAvailVirtual);
|
||||
// MemoryStatistics->CachePagesCommitted = [ ];
|
||||
// MemoryStatistics->PoolPagesCommitted = [ ];
|
||||
// MemoryStatistics->StackPagesCommitted = [ ];
|
||||
// MemoryStatistics->ImagePagesCommitted = [ ];
|
||||
g_VMManager.MemoryStatistics(MemoryStatistics);
|
||||
|
||||
DbgPrintf(" MemoryStatistics->Length = 0x%.08X\n", MemoryStatistics->Length);
|
||||
DbgPrintf(" MemoryStatistics->TotalPhysicalPages = 0x%.08X\n", MemoryStatistics->TotalPhysicalPages);
|
||||
|
@ -593,14 +555,9 @@ XBSYSAPI EXPORTNUM(182) xboxkrnl::VOID NTAPI xboxkrnl::MmSetAddressProtect
|
|||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(NewProtect)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
DWORD dwOldProtect;
|
||||
|
||||
if (!VirtualProtect(BaseAddress, NumberOfBytes, NewProtect & (~PAGE_WRITECOMBINE), &dwOldProtect))
|
||||
EmuWarning("VirtualProtect Failed!");
|
||||
|
||||
DbgPrintf("KRNL: VirtualProtect was 0x%.8X -> 0x%.8X\n", dwOldProtect, NewProtect & (~PAGE_WRITECOMBINE));
|
||||
g_VMManager.Protect((VAddr)BaseAddress, NumberOfBytes, NewProtect);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -618,13 +575,13 @@ XBSYSAPI EXPORTNUM(183) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmUnmapIoSpace
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(BaseAddress)
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
if ((xbaddr)BaseAddress >= XBOX_WRITE_COMBINED_BASE) { // 0xF0000000
|
||||
// Don't free hardware devices (flash, NV2A, etc)
|
||||
}
|
||||
else {
|
||||
g_MemoryManager.Free(BaseAddress);
|
||||
g_VMManager.Deallocate((VAddr)BaseAddress);
|
||||
LOG_INCOMPLETE();
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace NtDll
|
|||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
#include "EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#pragma warning(disable:4005) // Ignore redefined status values
|
||||
#include <ntstatus.h>
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace xboxkrnl
|
|||
#include "Logging.h" // For LOG_FUNC()
|
||||
#include "EmuKrnlLogging.h"
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
#include "VMManager.h"
|
||||
|
||||
// ******************************************************************
|
||||
// * 0x0146 - XeImageFileName
|
||||
|
@ -79,7 +80,7 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
|
|||
LOG_FUNC_ARG(Section)
|
||||
LOG_FUNC_END;
|
||||
|
||||
NTSTATUS ret = STATUS_INVALID_HANDLE;
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
|
||||
void* sectionData = CxbxKrnl_Xbe->FindSection((char*)std::string(Section->SectionName, 9).c_str());
|
||||
if (sectionData != nullptr) {
|
||||
|
@ -89,12 +90,46 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
|
|||
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
||||
// Copy the section data
|
||||
memcpy(Section->VirtualAddress, sectionData, Section->FileSize);
|
||||
|
||||
// ergo720: I can't just +/- PAGE_SIZE the VirtualAddress and the VirtualSize of a section because some titles have
|
||||
// sections less than PAGE_SIZE, which will cause again an overlap with the next section since both will have the
|
||||
// same aligned starting address.
|
||||
// Test case: Dead or Alive 3, section XGRPH has a size of 764 bytes
|
||||
// XGRPH DSOUND
|
||||
// 1F18A0 + 2FC -> aligned_start = 1F1000 1F1BA0 -> aligned_start = 1F1000 <- collision
|
||||
|
||||
// The following just increases the amount of physical/virtual memory consumed but doesn't actually allocate anything
|
||||
// inside the manager. This is done so that, because we now have fewer physical allocations, we also get more free contiguous
|
||||
// space that can be used by MmAllocateContiguousMemoryEx, which is problematic to map in the case of fragmentation. Also
|
||||
// note that the manager physical allocation routines check the free memory left before attempting a new allocation and bail out
|
||||
// immediately if not enough is available, this prevents exceeding the max memory on the Xbox
|
||||
|
||||
VAddr BaseAddress = (VAddr)Section->VirtualAddress;
|
||||
VAddr EndingAddress = (VAddr)Section->VirtualAddress + Section->VirtualSize;
|
||||
|
||||
if ((*Section->TailReferenceCount) != 0)
|
||||
{
|
||||
EndingAddress &= ~PAGE_MASK;
|
||||
}
|
||||
|
||||
if ((*Section->HeadReferenceCount) != 0)
|
||||
{
|
||||
BaseAddress = (BaseAddress + PAGE_SIZE) & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
if (EndingAddress > BaseAddress)
|
||||
{
|
||||
size_t RegionSize = EndingAddress - BaseAddress;
|
||||
ret = XbAllocateVirtualMemoryStub(&BaseAddress, 0, &RegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
// Increment the head/tail page reference counters
|
||||
(*Section->HeadReferenceCount)++;
|
||||
(*Section->TailReferenceCount)++;
|
||||
}
|
||||
|
||||
// Increment the reference count
|
||||
Section->SectionReferenceCount++;
|
||||
|
||||
ret = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
RETURN(ret);
|
||||
|
@ -123,9 +158,34 @@ XBSYSAPI EXPORTNUM(328) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeUnloadSection
|
|||
// Decrement the reference count
|
||||
Section->SectionReferenceCount -= 1;
|
||||
|
||||
// Free the section if necessary
|
||||
// Free the section and the physical memory in use if necessary
|
||||
if (Section->SectionReferenceCount == 0) {
|
||||
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
||||
|
||||
// REMARK: the following can be tested with Broken Sword - The Sleeping Dragon, RalliSport Challenge, ...
|
||||
|
||||
VAddr BaseAddress = (VAddr)Section->VirtualAddress;
|
||||
VAddr EndingAddress = (VAddr)Section->VirtualAddress + Section->VirtualSize;
|
||||
|
||||
// Decrement the head/tail page reference counters
|
||||
(*Section->HeadReferenceCount)--;
|
||||
(*Section->TailReferenceCount)--;
|
||||
|
||||
if ((*Section->TailReferenceCount) != 0)
|
||||
{
|
||||
EndingAddress &= ~PAGE_MASK;
|
||||
}
|
||||
|
||||
if ((*Section->HeadReferenceCount) != 0)
|
||||
{
|
||||
BaseAddress = (BaseAddress + PAGE_SIZE) & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
if (EndingAddress > BaseAddress)
|
||||
{
|
||||
size_t RegionSize = EndingAddress - BaseAddress;
|
||||
XbFreeVirtualMemoryStub(&BaseAddress, &RegionSize, MEM_DECOMMIT);
|
||||
}
|
||||
}
|
||||
|
||||
ret = STATUS_SUCCESS;
|
||||
|
|
|
@ -82,6 +82,7 @@ namespace xboxkrnl
|
|||
#include <cassert>
|
||||
//#include <gl\glut.h>
|
||||
|
||||
|
||||
// Public Domain ffs Implementation
|
||||
// See: http://snipplr.com/view/22147/stringsh-implementation/
|
||||
int ffs(int v)
|
||||
|
@ -2764,8 +2765,11 @@ DEVICE_READ32(PFB)
|
|||
result = 3; // = NV_PFB_CFG0_PART_4
|
||||
break;
|
||||
case NV_PFB_CSTATUS:
|
||||
result = CONTIGUOUS_MEMORY_SIZE;
|
||||
break;
|
||||
{
|
||||
if (g_bIsChihiro || g_bIsDebug) { result = CONTIGUOUS_MEMORY_CHIHIRO_SIZE; break; }
|
||||
result = CONTIGUOUS_MEMORY_XBOX_SIZE;
|
||||
}
|
||||
break;
|
||||
case NV_PFB_WBC:
|
||||
result = 0; // = !NV_PFB_WBC_FLUSH
|
||||
break;
|
||||
|
|
|
@ -47,6 +47,8 @@ enum {
|
|||
LLE_JIT = 1 << 2,
|
||||
};
|
||||
|
||||
typedef UINT_PTR PAddr;
|
||||
|
||||
// ******************************************************************
|
||||
// * EmuShared : Shared memory
|
||||
// ******************************************************************
|
||||
|
@ -122,6 +124,12 @@ class EmuShared : public Mutex
|
|||
void GetMultiXbeFlag(bool *value) { Lock(); *value = m_bMultiXbe; Unlock(); }
|
||||
void SetMultiXbeFlag(bool *value) { Lock(); m_bMultiXbe = *value; Unlock(); }
|
||||
|
||||
// ******************************************************************
|
||||
// * Launch data physical address Accessors
|
||||
// ******************************************************************
|
||||
void GetLaunchDataPAddress(PAddr *value) { Lock(); *value = m_LaunchDataPAddress; Unlock(); }
|
||||
void SetLaunchDataPAddress(PAddr *value) { Lock(); m_LaunchDataPAddress = *value; Unlock(); }
|
||||
|
||||
|
||||
private:
|
||||
// ******************************************************************
|
||||
|
@ -142,6 +150,7 @@ class EmuShared : public Mutex
|
|||
float m_MSpF;
|
||||
float m_FPS;
|
||||
bool m_bMultiXbe;
|
||||
PAddr m_LaunchDataPAddress;
|
||||
};
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace xboxkrnl
|
|||
#include "EmuFS.h"
|
||||
#include "EmuShared.h"
|
||||
#include "EmuXTL.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include <mmreg.h>
|
||||
#include <msacm.h>
|
||||
|
@ -82,7 +82,7 @@ HRESULT WINAPI XTL::EMUPATCH(XACTEngineCreate)
|
|||
|
||||
// TODO: Any other form of initialization?
|
||||
|
||||
*ppEngine = (X_XACTEngine*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTEngine ) );
|
||||
*ppEngine = (X_XACTEngine*)g_VMManager.AllocateZeroed(sizeof( X_XACTEngine ));
|
||||
|
||||
|
||||
|
||||
|
@ -130,7 +130,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_RegisterWaveBank)
|
|||
|
||||
// TODO: Implement
|
||||
|
||||
*ppWaveBank = (X_XACTWaveBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTWaveBank ) );
|
||||
*ppWaveBank = (X_XACTWaveBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTWaveBank ));
|
||||
|
||||
RETURN(S_OK);
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_RegisterStreamedWaveBank)
|
|||
|
||||
// TODO: Implement
|
||||
|
||||
*ppWaveBank = (X_XACTWaveBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTWaveBank ) );
|
||||
*ppWaveBank = (X_XACTWaveBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTWaveBank ));
|
||||
|
||||
RETURN(S_OK);
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_CreateSoundBank)
|
|||
|
||||
// TODO: Implement
|
||||
|
||||
*ppSoundBank = (X_XACTSoundBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTSoundBank ) );
|
||||
*ppSoundBank = (X_XACTSoundBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTSoundBank ));
|
||||
|
||||
RETURN(S_OK);
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_CreateSoundSource)
|
|||
LOG_FUNC_ARG(ppSoundSource)
|
||||
LOG_FUNC_END;
|
||||
|
||||
*ppSoundSource = (X_XACTSoundSource*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTSoundSource ) );
|
||||
*ppSoundSource = (X_XACTSoundSource*)g_VMManager.AllocateZeroed(sizeof( X_XACTSoundSource ));
|
||||
|
||||
RETURN(S_OK);
|
||||
}
|
||||
|
|
|
@ -1042,21 +1042,27 @@ DWORD WINAPI XTL::EMUPATCH(XLaunchNewImageA)
|
|||
|
||||
// Update the kernel's LaunchDataPage :
|
||||
{
|
||||
if (xboxkrnl::LaunchDataPage == &DefaultLaunchDataPage)
|
||||
xboxkrnl::LaunchDataPage = NULL;
|
||||
|
||||
if (xboxkrnl::LaunchDataPage == NULL)
|
||||
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE *)xboxkrnl::MmAllocateContiguousMemory(sizeof(xboxkrnl::LAUNCH_DATA_PAGE));
|
||||
if (xboxkrnl::LaunchDataPage == xbnull)
|
||||
{
|
||||
PVOID LaunchDataVAddr = xboxkrnl::MmAllocateContiguousMemory(sizeof(xboxkrnl::LAUNCH_DATA_PAGE));
|
||||
if (!LaunchDataVAddr)
|
||||
{
|
||||
RETURN(STATUS_NO_MEMORY);
|
||||
}
|
||||
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)LaunchDataVAddr;
|
||||
}
|
||||
|
||||
xboxkrnl::LaunchDataPage->Header.dwTitleId = g_pCertificate->dwTitleId;
|
||||
xboxkrnl::LaunchDataPage->Header.dwFlags = 0; // TODO : What to put in here?
|
||||
xboxkrnl::LaunchDataPage->Header.dwLaunchDataType = LDT_TITLE;
|
||||
|
||||
if (pLaunchData != NULL)
|
||||
xboxkrnl::MmPersistContiguousMemory((PVOID)xboxkrnl::LaunchDataPage, PAGE_SIZE, TRUE);
|
||||
|
||||
if (pLaunchData != xbnull)
|
||||
// Save the launch data
|
||||
memcpy(&(xboxkrnl::LaunchDataPage->LaunchData[0]), pLaunchData, sizeof(LAUNCH_DATA));
|
||||
|
||||
if (lpTitlePath == NULL)
|
||||
if (lpTitlePath == xbnull)
|
||||
{
|
||||
// If no path is specified, then the xbe is rebooting to dashboard
|
||||
char szDashboardPath[MAX_PATH] = { 0 };
|
||||
|
@ -1089,8 +1095,6 @@ DWORD WINAPI XTL::EMUPATCH(XLaunchNewImageA)
|
|||
RETURN(ERROR_GEN_FAILURE);
|
||||
}
|
||||
|
||||
DWORD g_XGetLaunchInfo_Status = -1;
|
||||
|
||||
#if 0 // patch disabled
|
||||
// ******************************************************************
|
||||
// * patch: XGetLaunchInfo
|
||||
|
|
|
@ -1,286 +0,0 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * .,-::::: .,:: .::::::::. .,:: .:
|
||||
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
||||
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
||||
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
||||
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
||||
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
||||
// *
|
||||
// * Cxbx->Win32->CxbxKrnl->MemoryManager.cpp
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
||||
#define LOG_PREFIX "XMEM"
|
||||
|
||||
#include <assert.h> // For assert()
|
||||
#include <malloc.h> // For _aligned_malloc()
|
||||
|
||||
#include "CxbxKrnl.h"
|
||||
#include "Emu.h"
|
||||
#include "Logging.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
MemoryManager g_MemoryManager;
|
||||
|
||||
MemoryManager::MemoryManager()
|
||||
{
|
||||
InitializeCriticalSectionAndSpinCount(&m_CriticalSection, 0x400);
|
||||
}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
DeleteCriticalSection(&m_CriticalSection);
|
||||
}
|
||||
|
||||
// Acquire m_CriticalSection before calling FindContainingTypedMemoryBlock!
|
||||
TypedMemoryBlock *MemoryManager::FindContainingTypedMemoryBlock(void* addr)
|
||||
{
|
||||
// Find the first block whose key (upper_bound) is not less than the requested address (thus: upper_bound >= addr)
|
||||
auto low = m_MemoryBlockInfo.lower_bound(addr);
|
||||
if (low == m_MemoryBlockInfo.end())
|
||||
return nullptr;
|
||||
|
||||
// Check if the requested address lies inside this block
|
||||
TypedMemoryBlock *info = &(low->second);
|
||||
if (addr < info->block.addr)
|
||||
return nullptr;
|
||||
|
||||
assert((uintptr_t)addr <= ((uintptr_t)info->block.upper_bound));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void* MemoryManager::Allocate(size_t size)
|
||||
{
|
||||
LOG_FUNC_ONE_ARG(size);
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
void * addr = malloc(size);
|
||||
|
||||
if (addr != NULL) {
|
||||
TypedMemoryBlock info;
|
||||
|
||||
info.type = MemoryType::STANDARD;
|
||||
info.block.init(addr, size);
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
m_MemoryBlockInfo[info.block.upper_bound] = info;
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
} else {
|
||||
#if 1 // TODO : Only log this in DEBUG builds (as a failure is already indicated by a null result)
|
||||
EmuWarning("MemoryManager::Allocate Failed!");
|
||||
#endif
|
||||
}
|
||||
|
||||
RETURN((void*)addr);
|
||||
}
|
||||
|
||||
void* MemoryManager::AllocateAligned(size_t size, size_t alignment)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(size) ;
|
||||
LOG_FUNC_ARG(alignment);
|
||||
LOG_FUNC_END;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
void * addr = _aligned_malloc(size, alignment);
|
||||
|
||||
if (addr != NULL) {
|
||||
TypedMemoryBlock info;
|
||||
|
||||
info.type = MemoryType::ALIGNED;
|
||||
info.block.init(addr, size);
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
m_MemoryBlockInfo[info.block.upper_bound] = info;
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
}
|
||||
|
||||
RETURN((void*)addr);
|
||||
}
|
||||
|
||||
void* MemoryManager::AllocateContiguous(size_t size, size_t alignment)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(size);
|
||||
LOG_FUNC_ARG(alignment);
|
||||
LOG_FUNC_END;
|
||||
|
||||
assert(size > 0);
|
||||
assert(alignment >= 4096); // TODO : Pull PAGE_SIZE in scope for this?
|
||||
assert((alignment & (alignment - 1)) == 0);
|
||||
|
||||
xbaddr alignMask = (xbaddr)(alignment - 1);
|
||||
|
||||
xbaddr addr = NULL;
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
// Is the contiguous allocation table empty?
|
||||
if (m_ContiguousMemoryBlocks.empty()) {
|
||||
// Start allocating Contiguous Memory after the Kernel image header to prevent overwriting our dummy Kernel
|
||||
addr = XBOX_KERNEL_BASE + sizeof(DUMMY_KERNEL);
|
||||
addr = (addr + alignMask) & ~alignMask;
|
||||
} else {
|
||||
// Locate the first available Memory Region with enough space for the requested buffer
|
||||
// TODO : This could be improved later on by always locating the smallest block with enough space
|
||||
// in order to reduce memory fragmentation.
|
||||
for (auto it = m_ContiguousMemoryBlocks.begin(); it != m_ContiguousMemoryBlocks.end(); ++it) {
|
||||
MemoryBlock current = it->second;
|
||||
xbaddr after_current = (xbaddr)current.upper_bound + 1;
|
||||
after_current = (after_current + alignMask) & ~alignMask;
|
||||
|
||||
// Is this the last entry?
|
||||
if (std::next(it) == m_ContiguousMemoryBlocks.end()) {
|
||||
// Continue allocating after the last block :
|
||||
addr = after_current;
|
||||
break;
|
||||
}
|
||||
|
||||
// Is there an empty gap after the current entry?
|
||||
MemoryBlock next = std::next(it)->second;
|
||||
if (after_current < (xbaddr)next.addr) {
|
||||
// does this allocation fit inside the gap?
|
||||
if (after_current + size < (xbaddr)next.addr) {
|
||||
addr = after_current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addr + size > CONTIGUOUS_MEMORY_BASE + CONTIGUOUS_MEMORY_SIZE) {
|
||||
EmuWarning("MemoryManager::AllocateContiguous exhausted it's allowed memory buffer");
|
||||
addr = NULL;
|
||||
}
|
||||
|
||||
if (addr != NULL) {
|
||||
MemoryBlock block;
|
||||
|
||||
block.init((void *)addr, size);
|
||||
m_ContiguousMemoryBlocks[(void *)addr] = block;
|
||||
|
||||
TypedMemoryBlock info;
|
||||
|
||||
info.type = MemoryType::CONTIGUOUS;
|
||||
info.block = block;
|
||||
|
||||
m_MemoryBlockInfo[info.block.upper_bound] = info;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
|
||||
RETURN((void*)addr);
|
||||
}
|
||||
|
||||
void* MemoryManager::AllocateZeroed(size_t num, size_t size)
|
||||
{
|
||||
LOG_FORWARD(Allocate); // Log AllocateZeroed as the origin of the following RETURN log message
|
||||
|
||||
void* addr = Allocate(num * size);
|
||||
|
||||
if (addr != nullptr) {
|
||||
memset(addr, 0, num * size);
|
||||
}
|
||||
|
||||
return addr; // Dont use RETURN, as Allocate already logs the result with that
|
||||
}
|
||||
|
||||
bool MemoryManager::IsAllocated(void* addr)
|
||||
{
|
||||
bool result;
|
||||
|
||||
LOG_FUNC_ONE_ARG(addr);
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
result = (FindContainingTypedMemoryBlock(addr) != nullptr);
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
void MemoryManager::Free(void* addr)
|
||||
{
|
||||
LOG_FUNC_ONE_ARG(addr);
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
|
||||
TypedMemoryBlock *info = FindContainingTypedMemoryBlock(addr);
|
||||
if (info != nullptr) {
|
||||
if (info->block.addr == addr) {
|
||||
switch (info->type) {
|
||||
case MemoryType::ALIGNED:
|
||||
_aligned_free((void*)info->block.addr);
|
||||
break;
|
||||
case MemoryType::STANDARD:
|
||||
free((void*)info->block.addr);
|
||||
break;
|
||||
case MemoryType::CONTIGUOUS:
|
||||
m_ContiguousMemoryBlocks.erase(info->block.addr);
|
||||
break;
|
||||
default:
|
||||
CxbxKrnlCleanup("Fatal: MemoryManager attempted to free memory of an unknown type");
|
||||
break;
|
||||
}
|
||||
|
||||
m_MemoryBlockInfo.erase(info->block.upper_bound);
|
||||
}
|
||||
else {
|
||||
__debugbreak();
|
||||
CxbxKrnlCleanup("Fatal: MemoryManager attempted to free only a part of a block");
|
||||
}
|
||||
} else {
|
||||
__debugbreak();
|
||||
CxbxKrnlCleanup("Fatal: Attempted to free memory that was not allocated via MemoryManager");
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
}
|
||||
|
||||
size_t MemoryManager::QueryAllocationSize(void* addr)
|
||||
{
|
||||
LOG_FUNC_ONE_ARG(addr);
|
||||
|
||||
size_t ret = 0;
|
||||
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
TypedMemoryBlock *info = FindContainingTypedMemoryBlock(addr);
|
||||
if (info != nullptr) {
|
||||
// Return the available size in this block
|
||||
ret = (uintptr_t)info->block.upper_bound - (uintptr_t)addr + 1;
|
||||
}
|
||||
else {
|
||||
#if 1 // TODO : Only log this in DEBUG builds (as a failure is already indicated by a null result)?
|
||||
EmuWarning("MemoryManager: Attempted to query memory that was not allocated via MemoryManager");
|
||||
#endif
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_CriticalSection);
|
||||
|
||||
RETURN(ret);
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * .,-::::: .,:: .::::::::. .,:: .:
|
||||
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
||||
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
||||
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
||||
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
||||
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
||||
// *
|
||||
// * Cxbx->Win32->CxbxKrnl->MemoryManager.h
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
||||
#ifndef MEMORY_MANAGER_H
|
||||
#define MEMORY_MANAGER_H
|
||||
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
typedef struct {
|
||||
void *addr;
|
||||
void *upper_bound;
|
||||
void init(void * base, size_t size) { addr = base; upper_bound = (void *)((uintptr_t)base + size - 1); }
|
||||
} MemoryBlock;
|
||||
|
||||
enum struct MemoryType {
|
||||
STANDARD = 0,
|
||||
ALIGNED,
|
||||
CONTIGUOUS
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
MemoryType type;
|
||||
MemoryBlock block;
|
||||
} TypedMemoryBlock;
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
public:
|
||||
MemoryManager();
|
||||
~MemoryManager();
|
||||
void* Allocate(size_t size);
|
||||
void* AllocateAligned(size_t size, size_t alignment);
|
||||
void* AllocateContiguous(size_t size, size_t alignment);
|
||||
void* AllocateZeroed(size_t num, size_t size);
|
||||
bool IsAllocated(void* addr);
|
||||
void Free(void* addr);
|
||||
size_t QueryAllocationSize(void* addr);
|
||||
private:
|
||||
std::map<void *, TypedMemoryBlock> m_MemoryBlockInfo;
|
||||
std::map<void *, MemoryBlock> m_ContiguousMemoryBlocks;
|
||||
CRITICAL_SECTION m_CriticalSection;
|
||||
TypedMemoryBlock *FindContainingTypedMemoryBlock(void* addr);
|
||||
};
|
||||
|
||||
extern MemoryManager g_MemoryManager;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,340 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * .,-::::: .,:: .::::::::. .,:: .:
|
||||
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
||||
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
||||
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
||||
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
||||
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
||||
// *
|
||||
// * Cxbx->Win32->CxbxKrnl->PhysicalMemory.cpp
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
||||
#include "PhysicalMemory.h"
|
||||
|
||||
|
||||
PMEMORY_STATUS PhysicalMemory::GetError() const
|
||||
{
|
||||
return m_Status;
|
||||
}
|
||||
|
||||
PAddr PhysicalMemory::AllocatePhysicalMemory(size_t size)
|
||||
{
|
||||
PAddr addr = m_MaxContiguousAddress;
|
||||
ClearError();
|
||||
size_t FreeMemory = m_MaxContiguousAddress - m_PhysicalMemoryInUse;
|
||||
if (size > FreeMemory)
|
||||
{
|
||||
EmuWarning("Out of physical memory!");
|
||||
SetError(PMEMORY_INSUFFICIENT_MEMORY);
|
||||
return addr;
|
||||
}
|
||||
|
||||
// Allocate the block wherever possible
|
||||
// This attempts to counter external fragmentation by allocating big blocks top-down and small blocks bottom-up
|
||||
if (size > m_AllocationThreshold)
|
||||
{
|
||||
if (m_Mem_map.empty())
|
||||
{
|
||||
addr = m_MaxContiguousAddress - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate the block starting from the top of memory
|
||||
for (auto rit = m_Mem_map.rbegin(); ; ++rit)
|
||||
{
|
||||
if (std::next(rit) == m_Mem_map.rend())
|
||||
{
|
||||
if (rit->first >= size)
|
||||
{
|
||||
addr = rit->first - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FreeMemory >= size) // fragmentation
|
||||
{
|
||||
addr = AllocateFragmented(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reinstate this if the nv2a instance memory allocation is found to be ever deallocated after being
|
||||
// mapped during initialization. The only one that could do it is MmClaimGpuInstanceMemory, however it doesn't seem
|
||||
// to deallocate the region, just to repurpose it...
|
||||
|
||||
//u32 offset = std::next(rit)->first + std::next(rit)->second;
|
||||
/*if (rit == max_contiguous_it && m_MaxContiguousAddress - offset >= size)
|
||||
{
|
||||
addr = m_MaxContiguousAddress - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}*/
|
||||
|
||||
if (rit->first - (std::next(rit)->first + std::next(rit)->second) >= size)
|
||||
{
|
||||
addr = rit->first - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Mem_map.empty())
|
||||
{
|
||||
addr = 0;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate the block starting from the bottom of memory
|
||||
auto max_contiguous_it = m_Mem_map.lower_bound(m_MaxContiguousAddress); // skip the nv2a/PFN allocation
|
||||
for (auto it = m_Mem_map.begin(); ; ++it)
|
||||
{
|
||||
if (it == m_Mem_map.begin() && it->first >= size)
|
||||
{
|
||||
addr = 0;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 offset = it->first + it->second;
|
||||
if (std::next(it) == max_contiguous_it)
|
||||
{
|
||||
if (m_MaxContiguousAddress - offset >= size)
|
||||
{
|
||||
addr = offset;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FreeMemory >= size) // fragmentation
|
||||
{
|
||||
addr = AllocateFragmented(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::next(it)->first - offset >= size)
|
||||
{
|
||||
addr = offset;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
PAddr PhysicalMemory::AllocatePhysicalMemoryRange(size_t size, PAddr low_addr, PAddr high_addr)
|
||||
{
|
||||
PAddr addr = m_MaxContiguousAddress;
|
||||
ClearError();
|
||||
size_t FreeMemory = m_MaxContiguousAddress - m_PhysicalMemoryInUse;
|
||||
if (size > FreeMemory)
|
||||
{
|
||||
EmuWarning("Out of physical memory!");
|
||||
SetError(PMEMORY_INSUFFICIENT_MEMORY);
|
||||
return addr;
|
||||
}
|
||||
|
||||
// TODO: it's a bit complex to properly allocate the blocks inside the requested range using the iterators,
|
||||
// a better approch would be to implement an actual PFN database and search free blocks with that, but unfortunately
|
||||
// with the current code it's not possible to relocate already allocated blocks
|
||||
|
||||
// Allocate the block inside the specified range if possible, going from the top-down
|
||||
if (m_Mem_map.empty())
|
||||
{
|
||||
addr = low_addr;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t FreeMemoryInRange = 0;
|
||||
|
||||
auto low_pair = m_Mem_map.emplace(low_addr, 0);
|
||||
PAddr lower_bound = low_addr;
|
||||
if (low_pair.first != m_Mem_map.begin())
|
||||
{
|
||||
auto low_it = std::prev(low_pair.first);
|
||||
if (low_it->first + low_it->second > low_addr)
|
||||
{
|
||||
lower_bound = low_it->first + low_it->second;
|
||||
}
|
||||
}
|
||||
if (!low_pair.second)
|
||||
{
|
||||
lower_bound = low_addr + low_pair.first->second;
|
||||
}
|
||||
auto high_pair = m_Mem_map.emplace(high_addr, 0);
|
||||
auto high_it = high_pair.first;
|
||||
{
|
||||
auto prev_it = std::prev(high_pair.first);
|
||||
if (prev_it->first + prev_it->second >= high_pair.first->first)
|
||||
{
|
||||
high_it = prev_it;
|
||||
if (high_it == low_pair.first)
|
||||
{
|
||||
SetError(PMEMORY_INSUFFICIENT_MEMORY);
|
||||
EmuWarning("Not enough memory in range 0x%.8X - 0x%.8X", low_addr, high_addr);
|
||||
if (high_pair.first->second == 0) { m_Mem_map.erase(high_addr); }
|
||||
if (low_pair.first->second == 0) { m_Mem_map.erase(low_addr); }
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = high_it; ; --it)
|
||||
{
|
||||
if (std::prev(it) == low_pair.first)
|
||||
{
|
||||
if (it->first - lower_bound >= size)
|
||||
{
|
||||
addr = it->first - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
FreeMemoryInRange += (it->first - lower_bound);
|
||||
|
||||
if (FreeMemoryInRange >= size) // fragmentation
|
||||
{
|
||||
addr = AllocateFragmented(size);
|
||||
break;
|
||||
}
|
||||
SetError(PMEMORY_INSUFFICIENT_MEMORY);
|
||||
EmuWarning("Not enough memory in range 0x%.8X - 0x%.8X", low_addr, high_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t FreeBetween = it->first - (std::prev(it)->first + std::prev(it)->second);
|
||||
if (FreeBetween >= size)
|
||||
{
|
||||
addr = it->first - size;
|
||||
m_Mem_map[addr] = size;
|
||||
m_PhysicalMemoryInUse += size;
|
||||
break;
|
||||
}
|
||||
FreeMemoryInRange += FreeBetween;
|
||||
}
|
||||
if (high_pair.first->second == 0) { m_Mem_map.erase(high_addr); }
|
||||
if (low_pair.first->second == 0) { m_Mem_map.erase(low_addr); }
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
VAddr PhysicalMemory::AllocateFragmented(size_t size)
|
||||
{
|
||||
PAddr addr_ptr = (PAddr)VirtualAlloc(NULL, size + PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (!addr_ptr)
|
||||
{
|
||||
EmuWarning("AllocateFragmented: VirtualAlloc could not allocate the memory!");
|
||||
SetError(PMEMORY_INSUFFICIENT_MEMORY);
|
||||
return m_MaxContiguousAddress;
|
||||
}
|
||||
VAddr aligned_start = addr_ptr & ~(UINT_PTR)PAGE_MASK;
|
||||
|
||||
m_Fragmented_mem_map[addr_ptr] = size;
|
||||
EmuWarning("Warning: allocated memory via AllocateFragmented.");
|
||||
SetError(PMEMORY_ALLOCATE_FRAGMENTED);
|
||||
m_PhysicalMemoryInUse += size;
|
||||
return aligned_start;
|
||||
}
|
||||
|
||||
void PhysicalMemory::ShrinkPhysicalAllocation(PAddr addr, size_t offset, bool bFragmentedMap, bool bStart)
|
||||
{
|
||||
if (!offset) { return; } // nothing to do
|
||||
|
||||
if (bFragmentedMap)
|
||||
{
|
||||
auto it = std::prev(m_Fragmented_mem_map.upper_bound(addr));
|
||||
PAddr old_base = it->first;
|
||||
size_t old_size = it->second;
|
||||
m_Fragmented_mem_map.erase(old_base);
|
||||
|
||||
if (old_size - offset)
|
||||
{
|
||||
if (bStart) { m_Fragmented_mem_map.emplace(old_base + offset, old_size - offset); }
|
||||
else { m_Fragmented_mem_map.emplace(old_base, old_size - offset); }
|
||||
}
|
||||
|
||||
m_PhysicalMemoryInUse -= offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = m_Mem_map.lower_bound(addr);
|
||||
PAddr old_base = it->first;
|
||||
size_t old_size = it->second;
|
||||
m_Mem_map.erase(old_base);
|
||||
|
||||
if (old_size - offset)
|
||||
{
|
||||
if (bStart) { m_Mem_map.emplace(old_base + offset, old_size - offset); }
|
||||
else { m_Mem_map.emplace(old_base, old_size - offset); }
|
||||
}
|
||||
|
||||
m_PhysicalMemoryInUse -= offset;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalMemory::DeAllocatePhysicalMemory(PAddr addr)
|
||||
{
|
||||
auto it = m_Mem_map.lower_bound(addr);
|
||||
m_PhysicalMemoryInUse -= it->second;
|
||||
m_Mem_map.erase(addr);
|
||||
}
|
||||
|
||||
void PhysicalMemory::DeAllocateFragmented(VAddr addr)
|
||||
{
|
||||
auto it = std::prev(m_Fragmented_mem_map.upper_bound(addr));
|
||||
VirtualFree((void*)it->first, 0, MEM_RELEASE);
|
||||
m_PhysicalMemoryInUse -= it->second;
|
||||
m_Fragmented_mem_map.erase(it->first);
|
||||
}
|
||||
|
||||
void PhysicalMemory::SetError(PMEMORY_STATUS err)
|
||||
{
|
||||
m_Status = err;
|
||||
}
|
||||
|
||||
void PhysicalMemory::ClearError()
|
||||
{
|
||||
m_Status = PMEMORY_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * .,-::::: .,:: .::::::::. .,:: .:
|
||||
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
||||
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
||||
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
||||
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
||||
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
||||
// *
|
||||
// * Cxbx->Win32->CxbxKrnl->PhysicalMemory.h
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
||||
#ifndef PHYSICAL_MEMORY_H
|
||||
#define PHYSICAL_MEMORY_H
|
||||
|
||||
#define _CXBXKRNL_INTERNAL
|
||||
#define _XBOXKRNL_DEFEXTRN_
|
||||
|
||||
namespace xboxkrnl
|
||||
{
|
||||
#include <xboxkrnl/xboxkrnl.h>
|
||||
};
|
||||
|
||||
#include "Emu.h"
|
||||
#include "CxbxKrnl.h"
|
||||
#include <windows.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
/* PhysicalMemory class error codes */
|
||||
|
||||
#define PMEMORY_STATUS unsigned int
|
||||
#define PMEMORY_SUCCESS 0x0
|
||||
#define PMEMORY_INSUFFICIENT_MEMORY 0x1
|
||||
#define PMEMORY_ALLOCATE_FRAGMENTED 0x2
|
||||
|
||||
|
||||
/* Global typedefs */
|
||||
|
||||
typedef UINT_PTR VAddr;
|
||||
typedef UINT_PTR PAddr;
|
||||
typedef std::uint32_t u32;
|
||||
typedef DWORD PTEflags;
|
||||
|
||||
|
||||
/* PhysicalMemory class */
|
||||
|
||||
class PhysicalMemory
|
||||
{
|
||||
protected:
|
||||
// if the block to allocate is smaller than AllocationThreshold, then it will be mapped starting from the bottom of the memory,
|
||||
// otherwise it's mapped from the top. AllocationThreshold is 64KiB, the allocation granularity of the Xbox
|
||||
const unsigned int m_AllocationThreshold = 1024 * 64;
|
||||
// amount of physical memory in use
|
||||
size_t m_PhysicalMemoryInUse = 0;
|
||||
// max physical memory available on the Xbox/Chihiro
|
||||
size_t m_MaxPhysicalMemory = XBOX_MEMORY_SIZE;
|
||||
// map tracking the physical memory currently in use
|
||||
std::map<PAddr, size_t> m_Mem_map;
|
||||
// map tracking the blocks allocated with VirtualAlloc
|
||||
std::map<VAddr, size_t> m_Fragmented_mem_map;
|
||||
// current error status code of the PhysicalMemory class
|
||||
PMEMORY_STATUS m_Status = PMEMORY_SUCCESS;
|
||||
// highest address available for contiguous allocations
|
||||
PAddr m_MaxContiguousAddress = XBOX_CONTIGUOUS_MEMORY_LIMIT;
|
||||
|
||||
// protected constructor so PhysicalMemory can only be inherited from
|
||||
PhysicalMemory() {};
|
||||
// destructor
|
||||
~PhysicalMemory()
|
||||
{
|
||||
for (auto it = m_Fragmented_mem_map.begin(); it != m_Fragmented_mem_map.end(); ++it)
|
||||
{
|
||||
VirtualFree((void*)it->first, 0, MEM_RELEASE);
|
||||
}
|
||||
}
|
||||
// allocates a block of the mapped file, returns m_MaxContiguousAddress and sets an error code if unsuccessful
|
||||
PAddr AllocatePhysicalMemory(size_t size);
|
||||
// allocates a block of the mapped file between the specified range if possible
|
||||
PAddr AllocatePhysicalMemoryRange(size_t size, PAddr low_addr, PAddr high_addr);
|
||||
// allocates a block of memory with VirtualAlloc when the main memory is fragmented and sets an error code
|
||||
VAddr AllocateFragmented(size_t size);
|
||||
// shrinks the size af an allocation
|
||||
void ShrinkPhysicalAllocation(PAddr addr, size_t offset, bool bFragmentedMap, bool bStart);
|
||||
// deallocates a block of the mapped file
|
||||
void DeAllocatePhysicalMemory(PAddr addr);
|
||||
// deallocates a block allocated with VirtualAlloc
|
||||
void DeAllocateFragmented(VAddr addr);
|
||||
// retrieves the current error code of the PhysicalMemory class
|
||||
PMEMORY_STATUS GetError() const;
|
||||
// sets the error code of the PhysicalMemory class
|
||||
void SetError(PMEMORY_STATUS err);
|
||||
// clears the error code of the PhysicalMemory class
|
||||
void ClearError();
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,226 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * .,-::::: .,:: .::::::::. .,:: .:
|
||||
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
||||
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
||||
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
||||
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
||||
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
||||
// *
|
||||
// * Cxbx->Win32->CxbxKrnl->VMManager.h
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017 ergo720
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
||||
#ifndef VMMANAGER_H
|
||||
#define VMMANAGER_H
|
||||
|
||||
|
||||
#include "PhysicalMemory.h"
|
||||
|
||||
#define XbAllocateVirtualMemoryStub(addr, zero_bits, size, allocation_type, protect) \
|
||||
g_VMManager.XbAllocateVirtualMemory(addr, zero_bits, size, allocation_type, protect, true)
|
||||
#define XbAllocateVirtualMemoryReal(addr, zero_bits, size, allocation_type, protect) \
|
||||
g_VMManager.XbAllocateVirtualMemory(addr, zero_bits, size, allocation_type, protect, false)
|
||||
#define XbFreeVirtualMemoryStub(addr, size, free_type) \
|
||||
g_VMManager.XbFreeVirtualMemory(addr, size, free_type, true)
|
||||
#define XbFreeVirtualMemoryReal(addr, size, free_type) \
|
||||
g_VMManager.XbFreeVirtualMemory(addr, size, free_type, false)
|
||||
|
||||
|
||||
/* VMATypes */
|
||||
|
||||
enum class VMAType : u32
|
||||
{
|
||||
// vma represents an unmapped region of the address space
|
||||
Free,
|
||||
// vma represents allocated memory
|
||||
Allocated,
|
||||
// stack allocation
|
||||
Stack,
|
||||
// tiled memory
|
||||
MemTiled,
|
||||
// nv2a
|
||||
IO_DeviceNV2A,
|
||||
// nv2a pramin memory
|
||||
MemNV2A_PRAMIN,
|
||||
// apu
|
||||
IO_DeviceAPU,
|
||||
// ac97
|
||||
IO_DeviceAC97,
|
||||
// usb0
|
||||
IO_DeviceUSB0,
|
||||
// usb1
|
||||
IO_DeviceUSB1,
|
||||
// ethernet controller
|
||||
IO_DeviceNVNet,
|
||||
// bios
|
||||
DeviceBIOS,
|
||||
// mcpx rom (retail xbox only)
|
||||
DeviceMCPX,
|
||||
// mark this vma as non-mergeable
|
||||
Lock,
|
||||
};
|
||||
|
||||
|
||||
/* VirtualMemoryArea struct */
|
||||
|
||||
struct VirtualMemoryArea
|
||||
{
|
||||
// vma starting address
|
||||
VAddr base = 0;
|
||||
// vma size
|
||||
size_t size = 0;
|
||||
// vma kind of memory
|
||||
VMAType type = VMAType::Free;
|
||||
// vma permissions
|
||||
DWORD permissions = PAGE_NOACCESS;
|
||||
// addr of the memory backing this block, if any
|
||||
PAddr backing_block = NULL;
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
/* VMManager class */
|
||||
|
||||
class VMManager : public PhysicalMemory
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
VMManager() { InitializeCriticalSectionAndSpinCount(&m_CriticalSection, 0x400); };
|
||||
// destructor
|
||||
~VMManager()
|
||||
{
|
||||
DeleteCriticalSection(&m_CriticalSection);
|
||||
FlushViewOfFile((void*)CONTIGUOUS_MEMORY_BASE, CHIHIRO_MEMORY_SIZE);
|
||||
FlushFileBuffers(m_hAliasedView);
|
||||
UnmapViewOfFile((void *)m_Base);
|
||||
UnmapViewOfFile((void *)CONTIGUOUS_MEMORY_BASE);
|
||||
UnmapViewOfFile((void*)TILED_MEMORY_BASE);
|
||||
CloseHandle(m_hAliasedView);
|
||||
}
|
||||
// initializes the page table to the default configuration
|
||||
void Initialize(HANDLE file_view);
|
||||
// initialize chihiro/debug - specifc memory ranges
|
||||
void InitializeChihiroDebug();
|
||||
// maps the virtual memory region used by a device
|
||||
void MapHardwareDevice(VAddr base, size_t size, VMAType type);
|
||||
// retrieves memory statistics
|
||||
void MemoryStatistics(xboxkrnl::PMM_STATISTICS memory_statistics);
|
||||
// allocates a block of memory
|
||||
VAddr Allocate(size_t size, PAddr low_addr = 0, PAddr high_addr = MAXULONG_PTR, ULONG Alignment = PAGE_SIZE,
|
||||
DWORD protect = PAGE_EXECUTE_READWRITE, bool bNonContiguous = true);
|
||||
// allocates a block of memory and zeros it
|
||||
VAddr AllocateZeroed(size_t size);
|
||||
// allocates stack memory
|
||||
VAddr AllocateStack(size_t size);
|
||||
// deallocate a block of memory
|
||||
void Deallocate(VAddr addr);
|
||||
// deallocate stack memory
|
||||
void DeallocateStack(VAddr addr);
|
||||
// changes the protections of a memory region
|
||||
void Protect(VAddr target, size_t size, DWORD new_perms);
|
||||
// query if a VAddr is valid
|
||||
bool QueryVAddr(VAddr addr);
|
||||
// translate a VAddr
|
||||
PAddr TranslateVAddr(VAddr addr);
|
||||
// retrieves the protection status of an address
|
||||
DWORD QueryProtection(VAddr addr);
|
||||
// retrieves the size of an allocation
|
||||
size_t QuerySize(VAddr addr);
|
||||
// xbox implementation of NtAllocateVirtualMemory
|
||||
xboxkrnl::NTSTATUS XbAllocateVirtualMemory(VAddr* addr, ULONG zero_bits, size_t* size, DWORD allocation_type,
|
||||
DWORD protect, bool bStub);
|
||||
// xbox implementation of NtFreeVirtualMemory
|
||||
xboxkrnl::NTSTATUS XbFreeVirtualMemory(VAddr* addr, size_t* size, DWORD free_type, bool bStub);
|
||||
|
||||
|
||||
private:
|
||||
// m_Vma_map iterator
|
||||
typedef std::map<VAddr, VirtualMemoryArea>::iterator VMAIter;
|
||||
// map covering the entire 32 bit virtual address space as seen by the guest
|
||||
std::map<VAddr, VirtualMemoryArea> m_Vma_map;
|
||||
// handle of the second file view region
|
||||
HANDLE m_hAliasedView = NULL;
|
||||
// start address of the memory region to which map non-contiguous allocations in the virtual space
|
||||
VAddr m_Base = 0;
|
||||
// critical section lock to synchronize accesses
|
||||
CRITICAL_SECTION m_CriticalSection;
|
||||
// amount of image virtual memory in use
|
||||
size_t m_ImageMemoryInUse = 0;
|
||||
// amount of non - image virtual memory in use
|
||||
size_t m_NonImageMemoryInUse = 0;
|
||||
// amount of stack virtual memory in use
|
||||
size_t m_StackMemoryInUse = 0;
|
||||
|
||||
// creates a vma block to be mapped in memory at the specified VAddr, if requested
|
||||
VAddr MapMemoryBlock(size_t* size, PAddr low_addr, PAddr high_addr, ULONG Alignment = PAGE_SIZE, bool bNonContiguous = true);
|
||||
// creates a vma representing the memory block to remove
|
||||
void UnmapRange(VAddr target);
|
||||
// changes access permissions for a range of vma's, splitting them if necessary
|
||||
void ReprotectVMARange(VAddr target, size_t size, DWORD new_perms);
|
||||
// checks if a VAddr is valid; returns false if not
|
||||
bool IsValidVirtualAddress(const VAddr addr);
|
||||
// translates a VAddr to its corresponding PAddr; it must be valid
|
||||
PAddr TranslateVAddrToPAddr(const VAddr addr);
|
||||
// maps a new allocation in the virtual address space
|
||||
void MapMemoryRegion(VAddr base, size_t size, PAddr target);
|
||||
// removes an allocation from the virtual address space
|
||||
void UnmapRegion(VAddr base, size_t size);
|
||||
// removes a vma block from the mapped memory
|
||||
VMAIter Unmap(VMAIter vma_handle);
|
||||
// updates the page table with a new vma entry
|
||||
void MapPages(u32 page_num, u32 page_count, PAddr memory, PTEflags type);
|
||||
// carves a vma of a specific size at the specified address by splitting free vma's
|
||||
VMAIter CarveVMA(VAddr base, size_t size);
|
||||
// splits the edges of the given range of non-free vma's so that there is a vma split at each end of the range
|
||||
VMAIter CarveVMARange(VAddr base, size_t size);
|
||||
// gets the iterator of a vma in m_Vma_map
|
||||
VMAIter GetVMAIterator(VAddr target);
|
||||
// splits a parent vma into two children
|
||||
VMAIter SplitVMA(VMAIter vma_handle, u32 offset_in_vma);
|
||||
// merges the specified vma with adjacent ones if possible
|
||||
VMAIter MergeAdjacentVMA(VMAIter vma_handle);
|
||||
// changes access permissions for a vma
|
||||
VMAIter ReprotectVMA(VMAIter vma_handle, DWORD new_perms);
|
||||
// updates the page table
|
||||
void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
|
||||
// acquires the critical section
|
||||
void Lock();
|
||||
// releases the critical section
|
||||
void Unlock();
|
||||
// destructs a vma if not free already
|
||||
VMAIter DestructVMA(VMAIter vma_handle, VAddr addr, size_t size);
|
||||
// changes the size/base of a vma
|
||||
void ResizeVMA(VMAIter vma_handle, size_t offset, bool bStart);
|
||||
};
|
||||
|
||||
|
||||
extern VMManager g_VMManager;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue