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\HLEDataBase\D3D8.OOVPA.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h" />
|
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\nv2a_int.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\nv2a_int.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\OOVPA.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\OOVPA.h" />
|
||||||
|
<ClInclude Include="..\..\src\CxbxKrnl\PhysicalMemory.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\ReservedMemory.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\ReservedMemory.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\ResourceTracker.h" />
|
<ClInclude Include="..\..\src\CxbxKrnl\ResourceTracker.h" />
|
||||||
|
<ClInclude Include="..\..\src\CxbxKrnl\VMManager.h" />
|
||||||
<ClInclude Include="..\..\src\CxbxVersion.h" />
|
<ClInclude Include="..\..\src\CxbxVersion.h" />
|
||||||
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h" />
|
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h" />
|
||||||
<ClInclude Include="..\..\src\Cxbx\DlgAudioConfig.h" />
|
<ClInclude Include="..\..\src\Cxbx\DlgAudioConfig.h" />
|
||||||
|
@ -514,13 +515,14 @@
|
||||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\CxbxKrnl\LibRc4.cpp" />
|
<ClCompile Include="..\..\src\CxbxKrnl\LibRc4.cpp" />
|
||||||
<ClCompile Include="..\..\src\CxbxKrnl\MemoryManager.cpp" />
|
<ClCompile Include="..\..\src\CxbxKrnl\PhysicalMemory.cpp" />
|
||||||
<ClCompile Include="..\..\src\CxbxKrnl\ResourceTracker.cpp">
|
<ClCompile Include="..\..\src\CxbxKrnl\ResourceTracker.cpp">
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\CxbxKrnl\VMManager.cpp" />
|
||||||
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp" />
|
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp" />
|
||||||
<ClCompile Include="..\..\src\Cxbx\DlgAudioConfig.cpp" />
|
<ClCompile Include="..\..\src\Cxbx\DlgAudioConfig.cpp" />
|
||||||
<ClCompile Include="..\..\src\Cxbx\DlgControllerConfig.cpp">
|
<ClCompile Include="..\..\src\Cxbx\DlgControllerConfig.cpp">
|
||||||
|
|
|
@ -187,9 +187,6 @@
|
||||||
<ClCompile Include="..\..\src\Common\EmuEEPROM.cpp">
|
<ClCompile Include="..\..\src\Common\EmuEEPROM.cpp">
|
||||||
<Filter>Shared</Filter>
|
<Filter>Shared</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\CxbxKrnl\MemoryManager.cpp">
|
|
||||||
<Filter>Emulator</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp">
|
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -205,6 +202,12 @@
|
||||||
<ClCompile Include="..\..\src\Common\Win32\XBAudio.cpp">
|
<ClCompile Include="..\..\src\Common\Win32\XBAudio.cpp">
|
||||||
<Filter>Shared</Filter>
|
<Filter>Shared</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\CxbxKrnl\PhysicalMemory.cpp">
|
||||||
|
<Filter>Emulator</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\CxbxKrnl\VMManager.cpp">
|
||||||
|
<Filter>Emulator</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\Cxbx\DlgControllerConfig.h">
|
<ClInclude Include="..\..\src\Cxbx\DlgControllerConfig.h">
|
||||||
|
@ -369,9 +372,6 @@
|
||||||
<ClInclude Include="..\..\src\CxbxVersion.h">
|
<ClInclude Include="..\..\src\CxbxVersion.h">
|
||||||
<Filter>Shared</Filter>
|
<Filter>Shared</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h">
|
|
||||||
<Filter>Emulator</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h">
|
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -396,6 +396,12 @@
|
||||||
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h">
|
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h">
|
||||||
<Filter>HLEDatabase\D3D8</Filter>
|
<Filter>HLEDatabase\D3D8</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\CxbxKrnl\PhysicalMemory.h">
|
||||||
|
<Filter>Emulator</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\CxbxKrnl\VMManager.h">
|
||||||
|
<Filter>Emulator</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\resource\Splash.jpg">
|
<None Include="..\..\resource\Splash.jpg">
|
||||||
|
|
|
@ -71,8 +71,8 @@ XBSYSAPI EXPORTNUM(169) PVOID NTAPI MmCreateKernelStack
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
XBSYSAPI EXPORTNUM(170) VOID NTAPI MmDeleteKernelStack
|
XBSYSAPI EXPORTNUM(170) VOID NTAPI MmDeleteKernelStack
|
||||||
(
|
(
|
||||||
IN PVOID EndAddress,
|
IN PVOID StackBase,
|
||||||
IN PVOID BaseAddress
|
IN PVOID StackLimit
|
||||||
);
|
);
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -229,6 +229,11 @@ typedef long NTSTATUS;
|
||||||
// Xbox pages are (1 << 12) = 0x00001000 = 4096 bytes in size.
|
// Xbox pages are (1 << 12) = 0x00001000 = 4096 bytes in size.
|
||||||
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||||
#define PAGE_MASK (PAGE_SIZE - 1)
|
#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.
|
// Convert a physical frame number to its corresponding physical address.
|
||||||
#define MI_CONVERT_PFN_TO_PHYSICAL(Pfn) \
|
#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)
|
ULONG FileSize; // File size (size of the section in the XBE file)
|
||||||
PCSZ SectionName; // Pointer to section name
|
PCSZ SectionName; // Pointer to section name
|
||||||
ULONG SectionReferenceCount; // Section reference count - when >= 1, section is loaded
|
ULONG SectionReferenceCount; // Section reference count - when >= 1, section is loaded
|
||||||
ULONG HeadReferenceCount; // Pointer to head shared page reference count
|
PUSHORT HeadReferenceCount; // Pointer to head shared page reference counter
|
||||||
ULONG TailReferenceCount; // Pointer to tail shared page reference count
|
PUSHORT TailReferenceCount; // Pointer to tail shared page reference counter
|
||||||
BYTE ShaHash[20]; // SHA hash. Hash DWORD containing FileSize, then hash section.
|
BYTE ShaHash[20]; // SHA hash. Hash DWORD containing FileSize, then hash section.
|
||||||
}
|
}
|
||||||
XBEIMAGE_SECTION, *PXBEIMAGE_SECTION;
|
XBEIMAGE_SECTION, *PXBEIMAGE_SECTION;
|
||||||
|
|
|
@ -138,6 +138,7 @@ EmuShared::EmuShared()
|
||||||
{
|
{
|
||||||
Load();
|
Load();
|
||||||
m_bMultiXbe = false;
|
m_bMultiXbe = false;
|
||||||
|
m_LaunchDataPAddress = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ void *Xbe::FindSection(char *zsSectionName)
|
||||||
return NULL;
|
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)
|
for (auto it = s.begin(); it < s.end(); ++it)
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,7 +72,7 @@ class Xbe : public Error
|
||||||
void ExportLogoBitmap(uint08 x_Gray[100*17]);
|
void ExportLogoBitmap(uint08 x_Gray[100*17]);
|
||||||
|
|
||||||
// purge illegal characters in Windows filenames or other OS's
|
// 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
|
// Xbe header
|
||||||
#include "AlignPrefix1.h"
|
#include "AlignPrefix1.h"
|
||||||
|
|
|
@ -119,6 +119,9 @@ extern XbeType g_XbeType;
|
||||||
/*! indicates emulation of an Chihiro (arcade, instead of Xbox console) executable */
|
/*! indicates emulation of an Chihiro (arcade, instead of Xbox console) executable */
|
||||||
extern bool g_bIsChihiro;
|
extern bool g_bIsChihiro;
|
||||||
|
|
||||||
|
/*! indicates emulation of a Debug xbe executable */
|
||||||
|
extern bool g_bIsDebug;
|
||||||
|
|
||||||
/*! maximum number of threads cxbx can handle */
|
/*! maximum number of threads cxbx can handle */
|
||||||
#define MAXIMUM_XBOX_THREADS 256
|
#define MAXIMUM_XBOX_THREADS 256
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace xboxkrnl
|
||||||
#include "EmuNV2A.h" // For InitOpenGLContext
|
#include "EmuNV2A.h" // For InitOpenGLContext
|
||||||
#include "HLEIntercept.h"
|
#include "HLEIntercept.h"
|
||||||
#include "ReservedMemory.h" // For virtual_memory_placeholder
|
#include "ReservedMemory.h" // For virtual_memory_placeholder
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
|
@ -89,7 +89,6 @@ static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = { 0 };
|
||||||
|
|
||||||
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
||||||
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
|
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
|
||||||
char szFilePath_LaunchDataPage_bin[MAX_PATH] = { 0 };
|
|
||||||
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
||||||
char szFilePath_memory_bin[MAX_PATH] = { 0 };
|
char szFilePath_memory_bin[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
|
@ -98,6 +97,7 @@ HANDLE CxbxBasePathHandle;
|
||||||
Xbe* CxbxKrnl_Xbe = NULL;
|
Xbe* CxbxKrnl_Xbe = NULL;
|
||||||
XbeType g_XbeType = xtRetail;
|
XbeType g_XbeType = xtRetail;
|
||||||
bool g_bIsChihiro = false;
|
bool g_bIsChihiro = false;
|
||||||
|
bool g_bIsDebug = false;
|
||||||
DWORD_PTR g_CPUXbox = 0;
|
DWORD_PTR g_CPUXbox = 0;
|
||||||
DWORD_PTR g_CPUOthers = 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(
|
HANDLE hFileMapping = CreateFileMapping(
|
||||||
hFile,
|
hFile,
|
||||||
/* lpFileMappingAttributes */nullptr,
|
/* lpFileMappingAttributes */nullptr,
|
||||||
PAGE_EXECUTE_READWRITE,
|
PAGE_EXECUTE_READWRITE,
|
||||||
/* dwMaximumSizeHigh */0,
|
/* dwMaximumSizeHigh */0,
|
||||||
/* dwMaximumSizeLow */CONTIGUOUS_MEMORY_SIZE,
|
/* dwMaximumSizeLow */CHIHIRO_MEMORY_SIZE,
|
||||||
/**/nullptr);
|
/**/nullptr);
|
||||||
if (hFileMapping == NULL)
|
if (hFileMapping == NULL)
|
||||||
{
|
{
|
||||||
|
@ -318,13 +316,22 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
||||||
return nullptr;
|
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 :
|
// Map memory.bin contents into memory :
|
||||||
void *memory = (void *)MapViewOfFileEx(
|
void *memory = (void *)MapViewOfFileEx(
|
||||||
hFileMapping,
|
hFileMapping,
|
||||||
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
||||||
/* dwFileOffsetHigh */0,
|
/* dwFileOffsetHigh */0,
|
||||||
/* dwFileOffsetLow */0,
|
/* dwFileOffsetLow */0,
|
||||||
CONTIGUOUS_MEMORY_SIZE,
|
CONTIGUOUS_MEMORY_CHIHIRO_SIZE,
|
||||||
(void *)CONTIGUOUS_MEMORY_BASE);
|
(void *)CONTIGUOUS_MEMORY_BASE);
|
||||||
if (memory != (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",
|
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)
|
if (NeedsInitialization)
|
||||||
{
|
{
|
||||||
memset(memory, 0, CONTIGUOUS_MEMORY_SIZE);
|
memset(memory, 0, CONTIGUOUS_MEMORY_CHIHIRO_SIZE);
|
||||||
printf("[0x%.4X] INIT: Initialized contiguous memory\n", GetCurrentThreadId());
|
printf("[0x%.4X] INIT: Initialized contiguous memory\n", GetCurrentThreadId());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -352,7 +359,7 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
||||||
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
||||||
/* dwFileOffsetHigh */0,
|
/* dwFileOffsetHigh */0,
|
||||||
/* dwFileOffsetLow */0,
|
/* dwFileOffsetLow */0,
|
||||||
TILED_MEMORY_SIZE,
|
TILED_MEMORY_CHIHIRO_SIZE,
|
||||||
(void *)TILED_MEMORY_BASE);
|
(void *)TILED_MEMORY_BASE);
|
||||||
if (tiled_memory != (void *)TILED_MEMORY_BASE)
|
if (tiled_memory != (void *)TILED_MEMORY_BASE)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +371,10 @@ void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[0x%.4X] INIT: Mapped contiguous memory to Xbox tiled memory at 0x%.8X to 0x%.8X\n",
|
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;
|
return memory;
|
||||||
}
|
}
|
||||||
|
@ -575,8 +585,6 @@ void CxbxKrnlMain(int argc, char* argv[])
|
||||||
|
|
||||||
CxbxRestoreContiguousMemory(szFilePath_memory_bin);
|
CxbxRestoreContiguousMemory(szFilePath_memory_bin);
|
||||||
|
|
||||||
CxbxRestorePersistentMemoryRegions();
|
|
||||||
|
|
||||||
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
|
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
|
||||||
if (EEPROM == nullptr)
|
if (EEPROM == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -602,11 +610,17 @@ void CxbxKrnlMain(int argc, char* argv[])
|
||||||
// Detect XBE type :
|
// Detect XBE type :
|
||||||
g_XbeType = GetXbeType(&CxbxKrnl_Xbe->m_Header);
|
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_bIsChihiro = (g_XbeType == xtChihiro);
|
||||||
|
g_bIsDebug = (g_XbeType == xtDebug);
|
||||||
|
|
||||||
// Determine memory size accordingly :
|
if (g_bIsChihiro || g_bIsDebug)
|
||||||
SIZE_T memorySize = (g_bIsChihiro ? CHIHIRO_MEMORY_SIZE : XBOX_MEMORY_SIZE);
|
{
|
||||||
|
// Initialize the Chihiro/Debug - specific memory ranges
|
||||||
|
g_VMManager.InitializeChihiroDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
CxbxRestorePersistentMemoryRegions();
|
||||||
|
|
||||||
// Copy over loaded Xbe Headers to specified base address
|
// Copy over loaded Xbe Headers to specified base address
|
||||||
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header));
|
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' :
|
// Assign the running Xbe path, so it can be accessed via the kernel thunk 'XeImageFileName' :
|
||||||
xboxkrnl::XeImageFileName.MaximumLength = MAX_PATH;
|
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());
|
sprintf(xboxkrnl::XeImageFileName.Buffer, "%c:\\%s", CxbxDefaultXbeDriveLetter, fileName.c_str());
|
||||||
xboxkrnl::XeImageFileName.Length = (USHORT)strlen(xboxkrnl::XeImageFileName.Buffer);
|
xboxkrnl::XeImageFileName.Length = (USHORT)strlen(xboxkrnl::XeImageFileName.Buffer);
|
||||||
printf("[0x%.4X] INIT: XeImageFileName = %s\n", GetCurrentThreadId(), 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!");
|
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_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData);
|
||||||
snprintf(szFilePath_memory_bin, MAX_PATH, "%s\\memory.bin", szFolder_CxbxReloadedData);
|
snprintf(szFilePath_memory_bin, MAX_PATH, "%s\\memory.bin", szFolder_CxbxReloadedData);
|
||||||
|
|
||||||
GetModuleFileName(GetModuleHandle(NULL), szFilePath_CxbxReloaded_Exe, MAX_PATH);
|
GetModuleFileName(GetModuleHandle(NULL), szFilePath_CxbxReloaded_Exe, MAX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Is DefaultLaunchDataPage really necessary? (No-one assigns it yet to LaunchDataPage)
|
// REMARK: the following is useless, but PatrickvL has asked to keep it for documentation purposes
|
||||||
xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
/*xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
||||||
{
|
{
|
||||||
{ // header
|
{ // header
|
||||||
2, // 2: dashboard, 0: title
|
2, // 2: dashboard, 0: title
|
||||||
|
@ -1030,27 +1043,20 @@ xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
|
||||||
"D:\\default.xbe",
|
"D:\\default.xbe",
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
|
|
||||||
void CxbxRestoreLaunchDataPage()
|
void CxbxRestoreLaunchDataPage()
|
||||||
{
|
{
|
||||||
// If CxbxLaunchDataPage.bin exist, load it into "persistent" memory
|
PAddr LaunchDataPAddr;
|
||||||
FILE* fp = fopen(szFilePath_LaunchDataPage_bin, "rb");
|
g_EmuShared->GetLaunchDataPAddress(&LaunchDataPAddr);
|
||||||
if (fp)
|
|
||||||
|
if (LaunchDataPAddr)
|
||||||
{
|
{
|
||||||
// Make sure LaunchDataPage is writeable :
|
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)CONTIGUOUS_MEMORY_BASE + LaunchDataPAddr;
|
||||||
if (xboxkrnl::LaunchDataPage == &DefaultLaunchDataPage)
|
// Mark the launch page as allocated to prevent other allocations from overwriting it
|
||||||
xboxkrnl::LaunchDataPage = NULL;
|
xboxkrnl::MmAllocateContiguousMemoryEx(PAGE_SIZE, LaunchDataPAddr, LaunchDataPAddr + PAGE_SIZE - 1, PAGE_SIZE, PAGE_READWRITE);
|
||||||
|
LaunchDataPAddr = NULL;
|
||||||
if (xboxkrnl::LaunchDataPage == NULL)
|
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||||
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);
|
|
||||||
|
|
||||||
DbgPrintf("INIT: Restored LaunchDataPage\n");
|
DbgPrintf("INIT: Restored LaunchDataPage\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ extern "C" {
|
||||||
// Sizes
|
// Sizes
|
||||||
#define ONE_KB 1024
|
#define ONE_KB 1024
|
||||||
#define ONE_MB (1024 * 1024)
|
#define ONE_MB (1024 * 1024)
|
||||||
|
#define X64KB 64 * ONE_KB
|
||||||
|
|
||||||
// Thread Information Block offsets - see https://www.microsoft.com/msj/archive/S2CE.aspx
|
// Thread Information Block offsets - see https://www.microsoft.com/msj/archive/S2CE.aspx
|
||||||
#define TIB_ArbitraryDataSlot 0x14
|
#define TIB_ArbitraryDataSlot 0x14
|
||||||
|
@ -67,16 +68,41 @@ extern "C" {
|
||||||
|
|
||||||
// Define virtual base addresses for physical memory windows.
|
// Define virtual base addresses for physical memory windows.
|
||||||
#define MM_SYSTEM_PHYSICAL_MAP KSEG0_BASE // = 0x80000000
|
#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_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 MM_INSTANCE_PAGE_COUNT 16
|
||||||
#define CONTIGUOUS_MEMORY_BASE MM_SYSTEM_PHYSICAL_MAP // = 0x80000000
|
#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_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_BASE 0xFD000000 // See NV2A_ADDR
|
||||||
#define NV2A_MEMORY_SIZE 0x01000000 // See NV2A_SIZE
|
#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 */
|
/*! memory size per system */
|
||||||
#define XBOX_MEMORY_SIZE (64 * ONE_MB)
|
#define XBOX_MEMORY_SIZE (64 * ONE_MB)
|
||||||
|
@ -97,6 +123,10 @@ extern "C" {
|
||||||
#define XBOX_FLASH_ROM_BASE 0xFFF00000
|
#define XBOX_FLASH_ROM_BASE 0xFFF00000
|
||||||
#define XBOX_FLASH_ROM_SIZE 0x00100000 // - 0xFFFFFFF
|
#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
|
// For now, virtual addresses are somewhat limited, as we use
|
||||||
// these soley for loading XBE sections. The largest that we
|
// these soley for loading XBE sections. The largest that we
|
||||||
// know of, is "BLiNX: the time sweeper", which has a section
|
// know of, is "BLiNX: the time sweeper", which has a section
|
||||||
|
@ -194,7 +224,6 @@ extern char* CxbxKrnl_DebugFileName;
|
||||||
/*! file paths */
|
/*! file paths */
|
||||||
extern char szFilePath_CxbxReloaded_Exe[MAX_PATH];
|
extern char szFilePath_CxbxReloaded_Exe[MAX_PATH];
|
||||||
extern char szFolder_CxbxReloadedData[MAX_PATH];
|
extern char szFolder_CxbxReloadedData[MAX_PATH];
|
||||||
extern char szFilePath_LaunchDataPage_bin[MAX_PATH];
|
|
||||||
extern char szFilePath_EEPROM_bin[MAX_PATH];
|
extern char szFilePath_EEPROM_bin[MAX_PATH];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace xboxkrnl
|
||||||
#include "EmuShared.h"
|
#include "EmuShared.h"
|
||||||
#include "DbgConsole.h"
|
#include "DbgConsole.h"
|
||||||
#include "ResourceTracker.h"
|
#include "ResourceTracker.h"
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
#include "EmuXTL.h"
|
#include "EmuXTL.h"
|
||||||
#include "HLEDatabase.h"
|
#include "HLEDatabase.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
@ -862,49 +862,49 @@ int GetD3DResourceRefCount(XTL::IDirect3DResource8 *EmuResource)
|
||||||
|
|
||||||
XTL::X_D3DSurface *EmuNewD3DSurface()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_SURFACE | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DTexture *EmuNewD3DTexture()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DVolumeTexture *EmuNewD3DVolumeTexture()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DCubeTexture *EmuNewD3DCubeTexture()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_TEXTURE | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DIndexBuffer *EmuNewD3DIndexBuffer()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_INDEXBUFFER | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DVertexBuffer *EmuNewD3DVertexBuffer()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_VERTEXBUFFER | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DPalette *EmuNewD3DPalette()
|
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
|
result->Common = X_D3DCOMMON_D3DCREATED | X_D3DCOMMON_TYPE_PALETTE | 1; // Set refcount to 1
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3398,8 +3398,8 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// create emulated shader struct
|
// create emulated shader struct
|
||||||
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader*)g_MemoryManager.AllocateZeroed(1, sizeof(X_D3DVertexShader));
|
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader*)g_VMManager.AllocateZeroed(sizeof(X_D3DVertexShader));
|
||||||
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER*)g_MemoryManager.AllocateZeroed(1, sizeof(VERTEX_SHADER));
|
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER*)g_VMManager.AllocateZeroed(sizeof(VERTEX_SHADER));
|
||||||
|
|
||||||
// TODO: Intelligently fill out these fields as necessary
|
// TODO: Intelligently fill out these fields as necessary
|
||||||
|
|
||||||
|
@ -3501,7 +3501,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
||||||
|
|
||||||
free(pRecompiledDeclaration);
|
free(pRecompiledDeclaration);
|
||||||
|
|
||||||
pVertexShader->pDeclaration = (DWORD*)g_MemoryManager.Allocate(DeclarationSize);
|
pVertexShader->pDeclaration = (DWORD*)g_VMManager.Allocate(DeclarationSize);
|
||||||
memcpy(pVertexShader->pDeclaration, pDeclaration, DeclarationSize);
|
memcpy(pVertexShader->pDeclaration, pDeclaration, DeclarationSize);
|
||||||
|
|
||||||
pVertexShader->FunctionSize = 0;
|
pVertexShader->FunctionSize = 0;
|
||||||
|
@ -3514,7 +3514,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
||||||
{
|
{
|
||||||
if(pFunction != NULL)
|
if(pFunction != NULL)
|
||||||
{
|
{
|
||||||
pVertexShader->pFunction = (DWORD*)g_MemoryManager.Allocate(VertexShaderSize);
|
pVertexShader->pFunction = (DWORD*)g_VMManager.Allocate(VertexShaderSize);
|
||||||
memcpy(pVertexShader->pFunction, pFunction, VertexShaderSize);
|
memcpy(pVertexShader->pFunction, pFunction, VertexShaderSize);
|
||||||
pVertexShader->FunctionSize = 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
|
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture
|
||||||
Texture_Data = X_D3DRESOURCE_DATA_YUV_SURFACE;
|
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;
|
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
|
// 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)->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)->Format = Format << X_D3DFORMAT_FORMAT_SHIFT;
|
||||||
|
|
||||||
(*ppVolumeTexture)->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK)
|
(*ppVolumeTexture)->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK)
|
||||||
|
@ -4644,7 +4644,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_Begin)
|
||||||
|
|
||||||
if(g_IVBTable == nullptr)
|
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;
|
g_IVBTblOffs = 0;
|
||||||
|
@ -4655,7 +4655,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_Begin)
|
||||||
|
|
||||||
if(g_pIVBVertexBuffer == nullptr)
|
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
|
// create vertex buffer
|
||||||
{
|
{
|
||||||
DWORD dwSize = g_MemoryManager.QueryAllocationSize(pBase);
|
DWORD dwSize = g_VMManager.QuerySize((VAddr)pBase);
|
||||||
|
|
||||||
if(dwSize == -1)
|
if(dwSize == -1)
|
||||||
{
|
{
|
||||||
|
@ -5273,7 +5273,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register)
|
||||||
|
|
||||||
// create push buffer
|
// create push buffer
|
||||||
{
|
{
|
||||||
DWORD dwSize = g_MemoryManager.QueryAllocationSize(pBase);
|
DWORD dwSize = g_VMManager.QuerySize((VAddr)pBase);
|
||||||
|
|
||||||
if(dwSize == -1)
|
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
|
// 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 !
|
// Note : This is the only change to the pResource argument passed into D3DResource_Register !
|
||||||
pPixelContainer->Data = X_D3DRESOURCE_DATA_YUV_SURFACE;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -5955,7 +5955,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
||||||
g_pCachedYuvSurface = NULL;
|
g_pCachedYuvSurface = NULL;
|
||||||
|
|
||||||
// free memory associated with this special resource handle
|
// free memory associated with this special resource handle
|
||||||
g_MemoryManager.Free((PVOID)pThis->Lock);
|
g_VMManager.Deallocate((VAddr)pThis->Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
||||||
|
@ -5970,7 +5970,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
||||||
|
|
||||||
if(pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
|
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?!
|
uRet = --pThis->Lock; // TODO : This makes no sense (as it mangles X_D3DRESOURCE_LOCK_PALETTE) but crashes otherwise?!
|
||||||
}
|
}
|
||||||
else if(pHostResource != nullptr)
|
else if(pHostResource != nullptr)
|
||||||
|
@ -8527,7 +8527,7 @@ XTL::X_D3DPalette * WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette2)
|
||||||
X_D3DPalette *pPalette = EmuNewD3DPalette();
|
X_D3DPalette *pPalette = EmuNewD3DPalette();
|
||||||
|
|
||||||
pPalette->Common |= (Size << X_D3DPALETTE_COMMON_PALETTESIZE_SHIFT);
|
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
|
pPalette->Lock = X_D3DRESOURCE_LOCK_PALETTE; // emulated reference count for palettes
|
||||||
|
|
||||||
// TODO: Should't we register the palette with a call to
|
// 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;
|
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
|
||||||
|
|
||||||
RealHandle = pVertexShader->Handle;
|
RealHandle = pVertexShader->Handle;
|
||||||
g_MemoryManager.Free(pVertexShader->pDeclaration);
|
g_VMManager.Deallocate((VAddr)pVertexShader->pDeclaration);
|
||||||
|
|
||||||
if(pVertexShader->pFunction)
|
if(pVertexShader->pFunction)
|
||||||
{
|
{
|
||||||
g_MemoryManager.Free(pVertexShader->pFunction);
|
g_VMManager.Deallocate((VAddr)pVertexShader->pFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeVertexDynamicPatch(pVertexShader);
|
FreeVertexDynamicPatch(pVertexShader);
|
||||||
|
|
||||||
g_MemoryManager.Free(pVertexShader);
|
g_VMManager.Deallocate((VAddr)pVertexShader);
|
||||||
g_MemoryManager.Free(pD3DVertexShader);
|
g_VMManager.Deallocate((VAddr)pD3DVertexShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hRet = g_pD3DDevice8->DeleteVertexShader(RealHandle);
|
HRESULT hRet = g_pD3DDevice8->DeleteVertexShader(RealHandle);
|
||||||
|
|
|
@ -72,7 +72,6 @@
|
||||||
#include "CxbxKrnl/Emu.h"
|
#include "CxbxKrnl/Emu.h"
|
||||||
#include "CxbxKrnl/EmuFS.h"
|
#include "CxbxKrnl/EmuFS.h"
|
||||||
#include "CxbxKrnl/EmuXTL.h"
|
#include "CxbxKrnl/EmuXTL.h"
|
||||||
#include <CxbxKrnl/MemoryManager.h>
|
|
||||||
|
|
||||||
//#include <CxbxKrnl/EmuD3D8Types.h> // X_PSH_COMBINECOUNT
|
//#include <CxbxKrnl/EmuD3D8Types.h> // X_PSH_COMBINECOUNT
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "CxbxKrnl/EmuXTL.h"
|
#include "CxbxKrnl/EmuXTL.h"
|
||||||
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DFORMAT
|
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DFORMAT
|
||||||
#include "CxbxKrnl/ResourceTracker.h"
|
#include "CxbxKrnl/ResourceTracker.h"
|
||||||
#include "CxbxKrnl/MemoryManager.h"
|
|
||||||
|
|
||||||
uint32 XTL::g_dwPrimaryPBCount = 0;
|
uint32 XTL::g_dwPrimaryPBCount = 0;
|
||||||
uint32 *XTL::g_pPrimaryPB = 0;
|
uint32 *XTL::g_pPrimaryPB = 0;
|
||||||
|
|
|
@ -37,11 +37,11 @@
|
||||||
#define _CXBXKRNL_INTERNAL
|
#define _CXBXKRNL_INTERNAL
|
||||||
#define _XBOXKRNL_DEFEXTRN_
|
#define _XBOXKRNL_DEFEXTRN_
|
||||||
|
|
||||||
|
#include "CxbxKrnl/VMManager.h"
|
||||||
#include "CxbxKrnl/xxhash32.h" // For XXHash32::hash()
|
#include "CxbxKrnl/xxhash32.h" // For XXHash32::hash()
|
||||||
#include "CxbxKrnl/Emu.h"
|
#include "CxbxKrnl/Emu.h"
|
||||||
#include "CxbxKrnl/EmuXTL.h"
|
#include "CxbxKrnl/EmuXTL.h"
|
||||||
#include "CxbxKrnl/ResourceTracker.h"
|
#include "CxbxKrnl/ResourceTracker.h"
|
||||||
#include "CxbxKrnl/MemoryManager.h"
|
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ bool XTL::VertexPatcher::PatchStream(VertexPatchDesc *pPatchDesc,
|
||||||
uiVertexCount = pPatchDesc->dwVertexCount;
|
uiVertexCount = pPatchDesc->dwVertexCount;
|
||||||
dwNewSize = uiVertexCount * pStreamPatch->ConvertedStride;
|
dwNewSize = uiVertexCount * pStreamPatch->ConvertedStride;
|
||||||
pNewVertexBuffer = NULL;
|
pNewVertexBuffer = NULL;
|
||||||
pNewData = (uint08*)g_MemoryManager.Allocate(dwNewSize);
|
pNewData = (uint08*)g_VMManager.Allocate(dwNewSize);
|
||||||
if(!pNewData)
|
if(!pNewData)
|
||||||
{
|
{
|
||||||
CxbxKrnlCleanup("Couldn't allocate the new stream zero buffer");
|
CxbxKrnlCleanup("Couldn't allocate the new stream zero buffer");
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "CxbxKrnl/Emu.h"
|
#include "CxbxKrnl/Emu.h"
|
||||||
#include "CxbxKrnl/EmuFS.h"
|
#include "CxbxKrnl/EmuFS.h"
|
||||||
#include "CxbxKrnl/EmuXTL.h"
|
#include "CxbxKrnl/EmuXTL.h"
|
||||||
#include "CxbxKrnl/MemoryManager.h"
|
|
||||||
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DVSDE_*
|
#include "CxbxKrnl/EmuD3D8Types.h" // For X_D3DVSDE_*
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
|
|
|
@ -49,7 +49,6 @@ namespace xboxkrnl {
|
||||||
#include "EmuFS.h"
|
#include "EmuFS.h"
|
||||||
#include "EmuShared.h"
|
#include "EmuShared.h"
|
||||||
#include "EmuXTL.h"
|
#include "EmuXTL.h"
|
||||||
#include "MemoryManager.h"
|
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
#include <mmreg.h>
|
#include <mmreg.h>
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace xboxkrnl
|
||||||
#include "EmuKrnl.h" // For InitializeListHead(), etc.
|
#include "EmuKrnl.h" // For InitializeListHead(), etc.
|
||||||
#include "EmuFS.h"
|
#include "EmuFS.h"
|
||||||
#include "CxbxKrnl.h"
|
#include "CxbxKrnl.h"
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
|
||||||
#undef FIELD_OFFSET // prevent macro redefinition warnings
|
#undef FIELD_OFFSET // prevent macro redefinition warnings
|
||||||
#include <windows.h>
|
#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) {
|
if (dwCopySize > 0) {
|
||||||
memcpy(pNewTLS, pTLSData, dwCopySize);
|
memcpy(pNewTLS, pTLSData, dwCopySize);
|
||||||
|
@ -446,7 +448,7 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the xbox KPCR structure
|
// 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::NT_TIB *XbTib = &(NewPcr->NtTib);
|
||||||
xboxkrnl::PKPRCB Prcb = &(NewPcr->PrcbData);
|
xboxkrnl::PKPRCB Prcb = &(NewPcr->PrcbData);
|
||||||
// Note : As explained above (at EmuKeSetPcr), Cxbx cannot allocate one NT_TIB and KPRCB
|
// 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
|
// 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->Tcb.TlsData = pNewTLS;
|
||||||
EThread->UniqueThread = GetCurrentThreadId();
|
EThread->UniqueThread = GetCurrentThreadId();
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
#pragma warning(default:4005)
|
#pragma warning(default:4005)
|
||||||
#include "CxbxKrnl.h"
|
#include "CxbxKrnl.h"
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(const HANDLE Handl
|
||||||
void _CxbxPVOIDDeleter(PVOID *ptr)
|
void _CxbxPVOIDDeleter(PVOID *ptr)
|
||||||
{
|
{
|
||||||
if (*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
|
// Build the native FILE_LINK_INFORMATION struct
|
||||||
*Length = sizeof(NtDll::FILE_LINK_INFORMATION) + convertedFileName.size() * sizeof(wchar_t);
|
*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->ReplaceIfExists = xboxLinkInfo->ReplaceIfExists;
|
||||||
ntLinkInfo->RootDirectory = RootDirectory;
|
ntLinkInfo->RootDirectory = RootDirectory;
|
||||||
ntLinkInfo->FileNameLength = convertedFileName.size() * sizeof(wchar_t);
|
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
|
// Build the native FILE_RENAME_INFORMATION struct
|
||||||
*Length = sizeof(NtDll::FILE_RENAME_INFORMATION) + convertedFileName.size() * sizeof(wchar_t);
|
*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->ReplaceIfExists = xboxRenameInfo->ReplaceIfExists;
|
||||||
ntRenameInfo->RootDirectory = RootDirectory;
|
ntRenameInfo->RootDirectory = RootDirectory;
|
||||||
ntRenameInfo->FileNameLength = convertedFileName.size() * sizeof(wchar_t);
|
ntRenameInfo->FileNameLength = convertedFileName.size() * sizeof(wchar_t);
|
||||||
|
|
|
@ -47,7 +47,6 @@ namespace xboxkrnl
|
||||||
|
|
||||||
#include "Logging.h" // For LOG_FUNC()
|
#include "Logging.h" // For LOG_FUNC()
|
||||||
#include "EmuKrnlLogging.h"
|
#include "EmuKrnlLogging.h"
|
||||||
#include "MemoryManager.h"
|
|
||||||
|
|
||||||
// prevent name collisions
|
// prevent name collisions
|
||||||
namespace NtDll
|
namespace NtDll
|
||||||
|
|
|
@ -42,13 +42,13 @@
|
||||||
// prevent name collisions
|
// prevent name collisions
|
||||||
namespace xboxkrnl
|
namespace xboxkrnl
|
||||||
{
|
{
|
||||||
#include <xboxkrnl/xboxkrnl.h> // For ExAllocatePool, etc.
|
#include <xboxkrnl/xboxkrnl.h> // For ExAllocatePool, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "Logging.h" // For LOG_FUNC()
|
#include "Logging.h" // For LOG_FUNC()
|
||||||
#include "EmuEEPROM.h" // For EmuFindEEPROMInfo, EEPROM, XboxFactoryGameRegion
|
#include "EmuEEPROM.h" // For EmuFindEEPROMInfo, EEPROM, XboxFactoryGameRegion
|
||||||
#include "EmuKrnlLogging.h"
|
#include "EmuKrnlLogging.h"
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
|
||||||
// prevent name collisions
|
// prevent name collisions
|
||||||
namespace NtDll
|
namespace NtDll
|
||||||
|
@ -128,7 +128,7 @@ XBSYSAPI EXPORTNUM(15) xboxkrnl::PVOID NTAPI xboxkrnl::ExAllocatePoolWithTag
|
||||||
LOG_FUNC_ARG(Tag)
|
LOG_FUNC_ARG(Tag)
|
||||||
LOG_FUNC_END;
|
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
|
LOG_INCOMPLETE(); // TODO : Actually implement ExAllocatePoolWithTag
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ XBSYSAPI EXPORTNUM(17) xboxkrnl::VOID NTAPI xboxkrnl::ExFreePool
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG(P);
|
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) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
||||||
// * (c) 2016 Patrick van Logchem <pvanlogchem@gmail.com>
|
// * (c) 2016 Patrick van Logchem <pvanlogchem@gmail.com>
|
||||||
|
// * (c) 2017 ergo720
|
||||||
// *
|
// *
|
||||||
// * All rights reserved
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -50,7 +51,8 @@ namespace xboxkrnl
|
||||||
#include "EmuKrnlLogging.h"
|
#include "EmuKrnlLogging.h"
|
||||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||||
#include "Emu.h" // For EmuWarning()
|
#include "Emu.h" // For EmuWarning()
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
#include "EmuShared.h"
|
||||||
|
|
||||||
// prevent name collisions
|
// prevent name collisions
|
||||||
namespace NtDll
|
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.
|
// the xbox kernel. Kernel code accessses this as a normal variable.
|
||||||
// XAPI code however, reference to the address of this kernel variable,
|
// XAPI code however, reference to the address of this kernel variable,
|
||||||
// thus use indirection (*LaunchDataPage) to get to the same contents.
|
// 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()
|
// * 0x00A5 - MmAllocateContiguousMemory()
|
||||||
|
@ -110,30 +112,34 @@ XBSYSAPI EXPORTNUM(166) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
|
||||||
LOG_FUNC_ARG(HighestAcceptableAddress)
|
LOG_FUNC_ARG(HighestAcceptableAddress)
|
||||||
LOG_FUNC_ARG(Alignment)
|
LOG_FUNC_ARG(Alignment)
|
||||||
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
|
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
|
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)
|
if (Alignment < PAGE_SIZE)
|
||||||
Alignment = PAGE_SIZE; // page boundary at least
|
Alignment = PAGE_SIZE; // page boundary at least
|
||||||
|
|
||||||
// Only known flags are allowed
|
// Only known flags are allowed
|
||||||
if ((ProtectionType & ~PAGE_KNOWN_FLAGS) != 0)
|
if ((ProtectionType & ~PAGE_KNOWN_FLAGS) != 0)
|
||||||
pRet = NULL;
|
pRet = xbnull;
|
||||||
|
|
||||||
// Either PAGE_READONLY or PAGE_READWRITE must be set (not both, nor none)
|
// Either PAGE_READONLY or PAGE_READWRITE must be set (not both, nor none)
|
||||||
if (((ProtectionType & PAGE_READONLY) > 0) == ((ProtectionType & PAGE_READWRITE) > 0))
|
if (((ProtectionType & PAGE_READONLY) > 0) == ((ProtectionType & PAGE_READWRITE) > 0))
|
||||||
pRet = NULL;
|
pRet = xbnull;
|
||||||
|
|
||||||
// Combining PAGE_NOCACHE and PAGE_WRITECOMBINE isn't allowed
|
// Combining PAGE_NOCACHE and PAGE_WRITECOMBINE isn't allowed
|
||||||
if ((ProtectionType & (PAGE_NOCACHE | PAGE_WRITECOMBINE)) == (PAGE_NOCACHE | PAGE_WRITECOMBINE))
|
if ((ProtectionType & (PAGE_NOCACHE | PAGE_WRITECOMBINE)) == (PAGE_NOCACHE | PAGE_WRITECOMBINE))
|
||||||
pRet = NULL;
|
pRet = xbnull;
|
||||||
|
|
||||||
// Allocate when input arguments are valid
|
// Allocate when input arguments are valid
|
||||||
if (pRet != NULL)
|
if (pRet != xbnull)
|
||||||
{
|
{
|
||||||
// TODO : Allocate differently if(ProtectionType & PAGE_WRITECOMBINE)
|
// 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);
|
RETURN(pRet);
|
||||||
|
@ -151,10 +157,10 @@ XBSYSAPI EXPORTNUM(167) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateSystemMemory
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(Protect)
|
LOG_FUNC_ARG(Protect)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// TODO: should this be aligned?
|
// TODO: this should probably allocate the memory at a specific system virtual address region...
|
||||||
PVOID pRet = g_MemoryManager.Allocate(NumberOfBytes);
|
PVOID pRet = (PVOID)g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, Protect);
|
||||||
|
|
||||||
RETURN(pRet);
|
RETURN(pRet);
|
||||||
}
|
}
|
||||||
|
@ -171,13 +177,18 @@ XBSYSAPI EXPORTNUM(168) xboxkrnl::PVOID NTAPI xboxkrnl::MmClaimGpuInstanceMemory
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG_OUT(NumberOfPaddingBytes)
|
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;
|
*NumberOfPaddingBytes = 0;
|
||||||
|
highest_physical_page = MM_CHIHIRO_HIGHEST_PHYSICAL_PAGE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*NumberOfPaddingBytes = MI_CONVERT_PFN_TO_PHYSICAL(MM_64M_PHYSICAL_PAGE) -
|
*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);
|
DbgPrintf("KNRL: MmClaimGpuInstanceMemory : *NumberOfPaddingBytes = 0x%.8X\n", *NumberOfPaddingBytes);
|
||||||
|
|
||||||
|
@ -189,7 +200,7 @@ XBSYSAPI EXPORTNUM(168) xboxkrnl::PVOID NTAPI xboxkrnl::MmClaimGpuInstanceMemory
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
- *NumberOfPaddingBytes;
|
||||||
|
|
||||||
RETURN(Result);
|
RETURN(Result);
|
||||||
|
@ -209,41 +220,21 @@ XBSYSAPI EXPORTNUM(169) xboxkrnl::PVOID NTAPI xboxkrnl::MmCreateKernelStack
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(DebuggerThread)
|
LOG_FUNC_ARG(DebuggerThread)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
NtDll::PVOID BaseAddress = NULL;
|
VAddr addr = xbnull;
|
||||||
|
|
||||||
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()");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function at present does not:
|
* Function at present does not:
|
||||||
* - Create an additional guard PAGE_SIZE after allocation,
|
|
||||||
* - Fill allocation with any values
|
|
||||||
* - Treat DebuggerThread any differently
|
* - Treat DebuggerThread any differently
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NTSTATUS ret = NtDll::NtAllocateVirtualMemory(
|
if (NumberOfBytes)
|
||||||
/*ProcessHandle=*/g_CurrentProcessHandle,
|
{
|
||||||
/*BaseAddress=*/&BaseAddress,
|
addr = g_VMManager.AllocateStack(NumberOfBytes);
|
||||||
/*ZeroBits=*/0,
|
}
|
||||||
/*RegionSize=*/&NumberOfBytes,
|
|
||||||
/*AllocationType=*/MEM_COMMIT,
|
|
||||||
/*Protect=*/PAGE_READWRITE);
|
|
||||||
|
|
||||||
if (FAILED(ret))
|
RETURN((PVOID)addr);
|
||||||
EmuWarning("MmCreateKernelStack failed!");
|
|
||||||
else
|
|
||||||
BaseAddress = (PVOID)((ULONG)BaseAddress + NumberOfBytes);
|
|
||||||
|
|
||||||
RETURN(BaseAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -251,25 +242,20 @@ XBSYSAPI EXPORTNUM(169) xboxkrnl::PVOID NTAPI xboxkrnl::MmCreateKernelStack
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
XBSYSAPI EXPORTNUM(170) xboxkrnl::VOID NTAPI xboxkrnl::MmDeleteKernelStack
|
XBSYSAPI EXPORTNUM(170) xboxkrnl::VOID NTAPI xboxkrnl::MmDeleteKernelStack
|
||||||
(
|
(
|
||||||
PVOID EndAddress,
|
PVOID StackBase,
|
||||||
PVOID BaseAddress
|
PVOID StackLimit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(EndAddress)
|
LOG_FUNC_ARG(StackBase)
|
||||||
LOG_FUNC_ARG(BaseAddress)
|
LOG_FUNC_ARG(StackLimit)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// TODO : Untested
|
size_t ActualSize = ((VAddr)StackBase - (VAddr)StackLimit) + PAGE_SIZE;
|
||||||
ULONG RegionSize = 0;
|
|
||||||
NTSTATUS ret = NtDll::NtFreeVirtualMemory(
|
|
||||||
/*ProcessHandle=*/g_CurrentProcessHandle,
|
|
||||||
&BaseAddress,
|
|
||||||
&RegionSize,
|
|
||||||
/*FreeType=*/MEM_RELEASE);
|
|
||||||
|
|
||||||
if (FAILED(ret))
|
VAddr StackBottom = (VAddr)StackBase - ActualSize;
|
||||||
EmuWarning("MmDeleteKernelStack failed!");
|
|
||||||
|
g_VMManager.DeallocateStack(StackBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -285,13 +271,7 @@ XBSYSAPI EXPORTNUM(171) xboxkrnl::VOID NTAPI xboxkrnl::MmFreeContiguousMemory
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG(BaseAddress);
|
LOG_FUNC_ONE_ARG(BaseAddress);
|
||||||
|
|
||||||
if (BaseAddress == &DefaultLaunchDataPage) {
|
g_VMManager.Deallocate((VAddr)BaseAddress);
|
||||||
DbgPrintf("KNRL: Ignored MmFreeContiguousMemory(&DefaultLaunchDataPage)\n");
|
|
||||||
LOG_IGNORED();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_MemoryManager.Free(BaseAddress);
|
|
||||||
|
|
||||||
// TODO -oDxbx: Sokoban crashes after this, at reset time (press Black + White to hit this).
|
// TODO -oDxbx: Sokoban crashes after this, at reset time (press Black + White to hit this).
|
||||||
// Tracing in assembly shows the crash takes place quite a while further, so it's probably
|
// Tracing in assembly shows the crash takes place quite a while further, so it's probably
|
||||||
|
@ -311,9 +291,9 @@ XBSYSAPI EXPORTNUM(172) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmFreeSystemMemory
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(BaseAddress)
|
LOG_FUNC_ARG(BaseAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
g_MemoryManager.Free(BaseAddress);
|
g_VMManager.Deallocate((VAddr)BaseAddress);
|
||||||
|
|
||||||
RETURN(STATUS_SUCCESS);
|
RETURN(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -335,8 +315,7 @@ XBSYSAPI EXPORTNUM(173) xboxkrnl::PHYSICAL_ADDRESS NTAPI xboxkrnl::MmGetPhysical
|
||||||
// MmLockUnlockBufferPages, emulate this???
|
// MmLockUnlockBufferPages, emulate this???
|
||||||
LOG_INCOMPLETE();
|
LOG_INCOMPLETE();
|
||||||
|
|
||||||
// We emulate Virtual/Physical memory 1:1
|
return g_VMManager.TranslateVAddr((VAddr)BaseAddress);
|
||||||
return (PHYSICAL_ADDRESS)BaseAddress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -349,9 +328,14 @@ XBSYSAPI EXPORTNUM(174) xboxkrnl::BOOLEAN NTAPI xboxkrnl::MmIsAddressValid
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG_OUT(VirtualAddress);
|
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(BaseAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(Protect)
|
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();
|
LOG_IGNORED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,8 +370,9 @@ XBSYSAPI EXPORTNUM(176) xboxkrnl::VOID NTAPI xboxkrnl::MmLockUnlockPhysicalPage
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(PhysicalAddress)
|
LOG_FUNC_ARG(PhysicalAddress)
|
||||||
LOG_FUNC_ARG(UnlockPage)
|
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();
|
LOG_IGNORED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +398,7 @@ XBSYSAPI EXPORTNUM(177) xboxkrnl::PVOID NTAPI xboxkrnl::MmMapIoSpace
|
||||||
LOG_FUNC_ARG(PhysicalAddress)
|
LOG_FUNC_ARG(PhysicalAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(ProtectionType)
|
LOG_FUNC_ARG(ProtectionType)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
PVOID pRet;
|
PVOID pRet;
|
||||||
|
|
||||||
|
@ -422,8 +408,7 @@ XBSYSAPI EXPORTNUM(177) xboxkrnl::PVOID NTAPI xboxkrnl::MmMapIoSpace
|
||||||
pRet = (PVOID)PhysicalAddress;
|
pRet = (PVOID)PhysicalAddress;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: should this be aligned?
|
g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, ProtectionType);
|
||||||
pRet = g_MemoryManager.Allocate(NumberOfBytes);
|
|
||||||
LOG_INCOMPLETE();
|
LOG_INCOMPLETE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,27 +429,21 @@ XBSYSAPI EXPORTNUM(178) xboxkrnl::VOID NTAPI xboxkrnl::MmPersistContiguousMemory
|
||||||
LOG_FUNC_ARG(BaseAddress)
|
LOG_FUNC_ARG(BaseAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(Persist)
|
LOG_FUNC_ARG(Persist)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
if (BaseAddress == LaunchDataPage)
|
if (BaseAddress == LaunchDataPage)
|
||||||
{
|
{
|
||||||
|
PAddr LaunchDataPAddr = g_VMManager.TranslateVAddr((VAddr)BaseAddress);
|
||||||
if (Persist)
|
if (Persist)
|
||||||
{
|
{
|
||||||
FILE* fp = fopen(szFilePath_LaunchDataPage_bin, "wb"); // TODO : Support wide char paths using _wfopen
|
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||||
if (fp)
|
DbgPrintf("KNRL: Persisting LaunchDataPage\n");
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LaunchDataPAddr = NULL;
|
||||||
|
g_EmuShared->SetLaunchDataPAddress(&LaunchDataPAddr);
|
||||||
DbgPrintf("KNRL: Forgetting LaunchDataPage\n");
|
DbgPrintf("KNRL: Forgetting LaunchDataPage\n");
|
||||||
remove(szFilePath_LaunchDataPage_bin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -494,12 +473,7 @@ XBSYSAPI EXPORTNUM(179) xboxkrnl::ULONG NTAPI xboxkrnl::MmQueryAddressProtect
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG(VirtualAddress);
|
LOG_FUNC_ONE_ARG(VirtualAddress);
|
||||||
|
|
||||||
// Assume read/write when page is allocated :
|
ULONG Result = g_VMManager.QueryProtection((VAddr)VirtualAddress);
|
||||||
ULONG Result = PAGE_NOACCESS;
|
|
||||||
|
|
||||||
if (g_MemoryManager.IsAllocated(VirtualAddress)) {
|
|
||||||
Result = PAGE_READWRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INCOMPLETE(); // TODO : Improve the MmQueryAddressProtect implementation
|
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_FUNC_ONE_ARG(BaseAddress);
|
||||||
|
|
||||||
LOG_INCOMPLETE(); // TODO : Free PAGE_WRITECOMBINE differently
|
ULONG uiSize = g_VMManager.QuerySize((VAddr)BaseAddress);
|
||||||
|
|
||||||
ULONG uiSize = g_MemoryManager.QueryAllocationSize(BaseAddress);
|
|
||||||
|
|
||||||
RETURN(uiSize);
|
RETURN(uiSize);
|
||||||
}
|
}
|
||||||
|
@ -533,30 +505,20 @@ XBSYSAPI EXPORTNUM(181) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmQueryStatistics
|
||||||
{
|
{
|
||||||
LOG_FUNC_ONE_ARG_OUT(MemoryStatistics);
|
LOG_FUNC_ONE_ARG_OUT(MemoryStatistics);
|
||||||
|
|
||||||
MEMORYSTATUSEX MemoryStatus;
|
|
||||||
SYSTEM_INFO SysInfo;
|
|
||||||
NTSTATUS ret;
|
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))
|
if (MemoryStatistics->Length == sizeof(MM_STATISTICS))
|
||||||
{
|
{
|
||||||
GlobalMemoryStatusEx(&MemoryStatus);
|
g_VMManager.MemoryStatistics(MemoryStatistics);
|
||||||
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 = [ ];
|
|
||||||
|
|
||||||
DbgPrintf(" MemoryStatistics->Length = 0x%.08X\n", MemoryStatistics->Length);
|
DbgPrintf(" MemoryStatistics->Length = 0x%.08X\n", MemoryStatistics->Length);
|
||||||
DbgPrintf(" MemoryStatistics->TotalPhysicalPages = 0x%.08X\n", MemoryStatistics->TotalPhysicalPages);
|
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(BaseAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_ARG(NewProtect)
|
LOG_FUNC_ARG(NewProtect)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
DWORD dwOldProtect;
|
g_VMManager.Protect((VAddr)BaseAddress, NumberOfBytes, NewProtect);
|
||||||
|
|
||||||
if (!VirtualProtect(BaseAddress, NumberOfBytes, NewProtect & (~PAGE_WRITECOMBINE), &dwOldProtect))
|
|
||||||
EmuWarning("VirtualProtect Failed!");
|
|
||||||
|
|
||||||
DbgPrintf("KRNL: VirtualProtect was 0x%.8X -> 0x%.8X\n", dwOldProtect, NewProtect & (~PAGE_WRITECOMBINE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -618,13 +575,13 @@ XBSYSAPI EXPORTNUM(183) xboxkrnl::NTSTATUS NTAPI xboxkrnl::MmUnmapIoSpace
|
||||||
LOG_FUNC_BEGIN
|
LOG_FUNC_BEGIN
|
||||||
LOG_FUNC_ARG(BaseAddress)
|
LOG_FUNC_ARG(BaseAddress)
|
||||||
LOG_FUNC_ARG(NumberOfBytes)
|
LOG_FUNC_ARG(NumberOfBytes)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
if ((xbaddr)BaseAddress >= XBOX_WRITE_COMBINED_BASE) { // 0xF0000000
|
if ((xbaddr)BaseAddress >= XBOX_WRITE_COMBINED_BASE) { // 0xF0000000
|
||||||
// Don't free hardware devices (flash, NV2A, etc)
|
// Don't free hardware devices (flash, NV2A, etc)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g_MemoryManager.Free(BaseAddress);
|
g_VMManager.Deallocate((VAddr)BaseAddress);
|
||||||
LOG_INCOMPLETE();
|
LOG_INCOMPLETE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ namespace NtDll
|
||||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||||
#include "Emu.h" // For EmuWarning()
|
#include "Emu.h" // For EmuWarning()
|
||||||
#include "EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
|
#include "EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
|
||||||
#include "MemoryManager.h"
|
|
||||||
|
|
||||||
#pragma warning(disable:4005) // Ignore redefined status values
|
#pragma warning(disable:4005) // Ignore redefined status values
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace xboxkrnl
|
||||||
#include "Logging.h" // For LOG_FUNC()
|
#include "Logging.h" // For LOG_FUNC()
|
||||||
#include "EmuKrnlLogging.h"
|
#include "EmuKrnlLogging.h"
|
||||||
#include "Emu.h" // For EmuWarning()
|
#include "Emu.h" // For EmuWarning()
|
||||||
|
#include "VMManager.h"
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * 0x0146 - XeImageFileName
|
// * 0x0146 - XeImageFileName
|
||||||
|
@ -79,7 +80,7 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
|
||||||
LOG_FUNC_ARG(Section)
|
LOG_FUNC_ARG(Section)
|
||||||
LOG_FUNC_END;
|
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());
|
void* sectionData = CxbxKrnl_Xbe->FindSection((char*)std::string(Section->SectionName, 9).c_str());
|
||||||
if (sectionData != nullptr) {
|
if (sectionData != nullptr) {
|
||||||
|
@ -89,12 +90,46 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
|
||||||
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
||||||
// Copy the section data
|
// Copy the section data
|
||||||
memcpy(Section->VirtualAddress, sectionData, Section->FileSize);
|
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
|
// Increment the reference count
|
||||||
Section->SectionReferenceCount++;
|
Section->SectionReferenceCount++;
|
||||||
|
|
||||||
ret = STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN(ret);
|
RETURN(ret);
|
||||||
|
@ -123,9 +158,34 @@ XBSYSAPI EXPORTNUM(328) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeUnloadSection
|
||||||
// Decrement the reference count
|
// Decrement the reference count
|
||||||
Section->SectionReferenceCount -= 1;
|
Section->SectionReferenceCount -= 1;
|
||||||
|
|
||||||
// Free the section if necessary
|
// Free the section and the physical memory in use if necessary
|
||||||
if (Section->SectionReferenceCount == 0) {
|
if (Section->SectionReferenceCount == 0) {
|
||||||
memset(Section->VirtualAddress, 0, Section->VirtualSize);
|
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;
|
ret = STATUS_SUCCESS;
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace xboxkrnl
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
//#include <gl\glut.h>
|
//#include <gl\glut.h>
|
||||||
|
|
||||||
|
|
||||||
// Public Domain ffs Implementation
|
// Public Domain ffs Implementation
|
||||||
// See: http://snipplr.com/view/22147/stringsh-implementation/
|
// See: http://snipplr.com/view/22147/stringsh-implementation/
|
||||||
int ffs(int v)
|
int ffs(int v)
|
||||||
|
@ -2764,8 +2765,11 @@ DEVICE_READ32(PFB)
|
||||||
result = 3; // = NV_PFB_CFG0_PART_4
|
result = 3; // = NV_PFB_CFG0_PART_4
|
||||||
break;
|
break;
|
||||||
case NV_PFB_CSTATUS:
|
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:
|
case NV_PFB_WBC:
|
||||||
result = 0; // = !NV_PFB_WBC_FLUSH
|
result = 0; // = !NV_PFB_WBC_FLUSH
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -47,6 +47,8 @@ enum {
|
||||||
LLE_JIT = 1 << 2,
|
LLE_JIT = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef UINT_PTR PAddr;
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * EmuShared : Shared memory
|
// * EmuShared : Shared memory
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -122,6 +124,12 @@ class EmuShared : public Mutex
|
||||||
void GetMultiXbeFlag(bool *value) { Lock(); *value = m_bMultiXbe; Unlock(); }
|
void GetMultiXbeFlag(bool *value) { Lock(); *value = m_bMultiXbe; Unlock(); }
|
||||||
void SetMultiXbeFlag(bool *value) { Lock(); m_bMultiXbe = *value; 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:
|
private:
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -142,6 +150,7 @@ class EmuShared : public Mutex
|
||||||
float m_MSpF;
|
float m_MSpF;
|
||||||
float m_FPS;
|
float m_FPS;
|
||||||
bool m_bMultiXbe;
|
bool m_bMultiXbe;
|
||||||
|
PAddr m_LaunchDataPAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace xboxkrnl
|
||||||
#include "EmuFS.h"
|
#include "EmuFS.h"
|
||||||
#include "EmuShared.h"
|
#include "EmuShared.h"
|
||||||
#include "EmuXTL.h"
|
#include "EmuXTL.h"
|
||||||
#include "MemoryManager.h"
|
#include "VMManager.h"
|
||||||
|
|
||||||
#include <mmreg.h>
|
#include <mmreg.h>
|
||||||
#include <msacm.h>
|
#include <msacm.h>
|
||||||
|
@ -82,7 +82,7 @@ HRESULT WINAPI XTL::EMUPATCH(XACTEngineCreate)
|
||||||
|
|
||||||
// TODO: Any other form of initialization?
|
// 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
|
// TODO: Implement
|
||||||
|
|
||||||
*ppWaveBank = (X_XACTWaveBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTWaveBank ) );
|
*ppWaveBank = (X_XACTWaveBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTWaveBank ));
|
||||||
|
|
||||||
RETURN(S_OK);
|
RETURN(S_OK);
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_RegisterStreamedWaveBank)
|
||||||
|
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
|
|
||||||
*ppWaveBank = (X_XACTWaveBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTWaveBank ) );
|
*ppWaveBank = (X_XACTWaveBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTWaveBank ));
|
||||||
|
|
||||||
RETURN(S_OK);
|
RETURN(S_OK);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_CreateSoundBank)
|
||||||
|
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
|
|
||||||
*ppSoundBank = (X_XACTSoundBank*)g_MemoryManager.AllocateZeroed(1, sizeof( X_XACTSoundBank ) );
|
*ppSoundBank = (X_XACTSoundBank*)g_VMManager.AllocateZeroed(sizeof( X_XACTSoundBank ));
|
||||||
|
|
||||||
RETURN(S_OK);
|
RETURN(S_OK);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ HRESULT WINAPI XTL::EMUPATCH(IXACTEngine_CreateSoundSource)
|
||||||
LOG_FUNC_ARG(ppSoundSource)
|
LOG_FUNC_ARG(ppSoundSource)
|
||||||
LOG_FUNC_END;
|
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);
|
RETURN(S_OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1042,21 +1042,27 @@ DWORD WINAPI XTL::EMUPATCH(XLaunchNewImageA)
|
||||||
|
|
||||||
// Update the kernel's LaunchDataPage :
|
// Update the kernel's LaunchDataPage :
|
||||||
{
|
{
|
||||||
if (xboxkrnl::LaunchDataPage == &DefaultLaunchDataPage)
|
if (xboxkrnl::LaunchDataPage == xbnull)
|
||||||
xboxkrnl::LaunchDataPage = NULL;
|
{
|
||||||
|
PVOID LaunchDataVAddr = xboxkrnl::MmAllocateContiguousMemory(sizeof(xboxkrnl::LAUNCH_DATA_PAGE));
|
||||||
if (xboxkrnl::LaunchDataPage == NULL)
|
if (!LaunchDataVAddr)
|
||||||
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE *)xboxkrnl::MmAllocateContiguousMemory(sizeof(xboxkrnl::LAUNCH_DATA_PAGE));
|
{
|
||||||
|
RETURN(STATUS_NO_MEMORY);
|
||||||
|
}
|
||||||
|
xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)LaunchDataVAddr;
|
||||||
|
}
|
||||||
|
|
||||||
xboxkrnl::LaunchDataPage->Header.dwTitleId = g_pCertificate->dwTitleId;
|
xboxkrnl::LaunchDataPage->Header.dwTitleId = g_pCertificate->dwTitleId;
|
||||||
xboxkrnl::LaunchDataPage->Header.dwFlags = 0; // TODO : What to put in here?
|
xboxkrnl::LaunchDataPage->Header.dwFlags = 0; // TODO : What to put in here?
|
||||||
xboxkrnl::LaunchDataPage->Header.dwLaunchDataType = LDT_TITLE;
|
xboxkrnl::LaunchDataPage->Header.dwLaunchDataType = LDT_TITLE;
|
||||||
|
|
||||||
if (pLaunchData != NULL)
|
xboxkrnl::MmPersistContiguousMemory((PVOID)xboxkrnl::LaunchDataPage, PAGE_SIZE, TRUE);
|
||||||
|
|
||||||
|
if (pLaunchData != xbnull)
|
||||||
// Save the launch data
|
// Save the launch data
|
||||||
memcpy(&(xboxkrnl::LaunchDataPage->LaunchData[0]), pLaunchData, sizeof(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
|
// If no path is specified, then the xbe is rebooting to dashboard
|
||||||
char szDashboardPath[MAX_PATH] = { 0 };
|
char szDashboardPath[MAX_PATH] = { 0 };
|
||||||
|
@ -1089,8 +1095,6 @@ DWORD WINAPI XTL::EMUPATCH(XLaunchNewImageA)
|
||||||
RETURN(ERROR_GEN_FAILURE);
|
RETURN(ERROR_GEN_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD g_XGetLaunchInfo_Status = -1;
|
|
||||||
|
|
||||||
#if 0 // patch disabled
|
#if 0 // patch disabled
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: XGetLaunchInfo
|
// * 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