Merge pull request #254 from PatrickvL/ContiguousMemory

MemoryRelatedImprovements
This commit is contained in:
Luke Usher 2017-03-21 22:25:13 +00:00 committed by GitHub
commit 71b81a821c
16 changed files with 323 additions and 150 deletions

View File

@ -201,6 +201,25 @@ typedef long NTSTATUS;
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
// ******************************************************************
// * MEM Masks
// ******************************************************************
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
#define MEM_DECOMMIT 0x4000
#define MEM_RELEASE 0x8000
#define MEM_FREE 0x10000
#define MEM_PRIVATE 0x20000
#define MEM_MAPPED 0x40000
//#define MEM_RESET 0x80000
#define MEM_TOP_DOWN 0x100000
#define MEM_WRITE_WATCH 0x200000
#define MEM_PHYSICAL 0x400000
#define MEM_NOZERO 0x800000 // Replaces MEM_ROTATE on WinXP+
//#define MEM_IMAGE 0x1000000 // Declare like below, to prevent warning C4005: 'MEM_IMAGE': macro redefinition
#define SEC_IMAGE 0x1000000
#define MEM_IMAGE SEC_IMAGE
// ******************************************************************
// * memory
// ******************************************************************
@ -219,6 +238,10 @@ typedef long NTSTATUS;
#define PAGE_SHIFT 12
// Xbox pages are (1 << 12) = 0x00001000 = 4096 bytes in size.
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (PAGE_SIZE - 1)
// Convert a physical frame number to its corresponding physical address.
#define MI_CONVERT_PFN_TO_PHYSICAL(Pfn) \
((PCHAR)MM_SYSTEM_PHYSICAL_MAP + ((ULONG)(Pfn) << PAGE_SHIFT))

View File

@ -40,18 +40,21 @@ extern "C"
{
#endif
#include "CxbxKrnl/EmuShared.h" // For EMU_MAX_MEMORY_SIZE and OPCODE_NOP_90
#include "CxbxKrnl/EmuShared.h" // For XBE_MAX_VA, XBE_IMAGE_BASE and CXBX_BASE_OF_CODE
// The following code reserves virtual addresses from 0x00011000 upwards;
#define VM_PLACEHOLDER_SIZE (XBE_MAX_VA - XBE_IMAGE_BASE - CXBX_BASE_OF_CODE)
// The following code claims 0x0001000 + 128 MB;
// First, declare the '.text' section again :
#pragma section(".text") // Note : 'read,write,execute' would cause a warning
// Then place the following variable into the '.text' section :
__declspec(allocate(".text"))
// This variable *MUST* be this large, for it to take up address space
// so that all other code and data in this module are placed outside of the
// maximum emulated memory range.
unsigned char emulated_memory_placeholder[EMU_MAX_MEMORY_SIZE]; // = { OPCODE_NOP_90 };
// TODO : Try to get the same result without enlarging the executable by 128 MB!
// maximum virtual memory range.
unsigned char virtual_memory_placeholder[VM_PLACEHOLDER_SIZE]; // = { OPCODE_NOP_90 };
// TODO : Try to get the same result without enlarging our executable by 128 MB!
#if defined(__cplusplus)
}

View File

@ -42,6 +42,8 @@
#include <cstring>
#include <ctime>
#define PAGE_SIZE 0x1000
// construct via Xbe file
Xbe::Xbe(const char *x_szFilename)
{
@ -99,7 +101,7 @@ Xbe::Xbe(const char *x_szFilename)
{
printf("Xbe::Xbe: Reading Image Header Extra Bytes...");
m_ExSize = RoundUp(m_Header.dwSizeofHeaders, 0x1000) - sizeof(m_Header);
m_ExSize = RoundUp(m_Header.dwSizeofHeaders, PAGE_SIZE) - sizeof(m_Header);
m_HeaderEx = new char[m_ExSize];
@ -463,7 +465,7 @@ void Xbe::Export(const char *x_szXbeFilename)
fgetpos(XbeFile, &pos);
remaining = (uint32)(0x1000 - ftell(XbeFile)%0x1000);
remaining = (uint32)(PAGE_SIZE - ftell(XbeFile) % PAGE_SIZE);
// write remaining bytes
{

View File

@ -52,7 +52,7 @@ namespace xboxkrnl
#include "EmuShared.h"
#include "EmuNV2A.h" // For InitOpenGLContext
#include "HLEIntercept.h"
#include "ReservedMemory.h" // For emulated_memory_placeholder
#include "ReservedMemory.h" // For virtual_memory_placeholder
#include <shlobj.h>
#include <clocale>
@ -83,6 +83,7 @@ char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
char szFilePath_LaunchDataPage_bin[MAX_PATH] = { 0 };
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
char szFilePath_memory_bin[MAX_PATH] = { 0 };
std::string CxbxBasePath;
HANDLE CxbxBasePathHandle;
@ -224,6 +225,77 @@ void RestoreExeImageHeader()
ExeOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] = NewOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
}
#define CONTIGUOUS_MEMORY_SIZE (64 * ONE_MB)
void *CxbxRestoreContiguousMemory(char *szFilePath_memory_bin)
{
// First, try to open an existing memory.bin file :
HANDLE hFile = CreateFile(szFilePath_memory_bin,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* lpSecurityAttributes */nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
/* hTemplateFile */nullptr);
bool NeedsInitialization = (hFile == INVALID_HANDLE_VALUE);
if (NeedsInitialization)
{
// If the memory.bin file doesn't exist yet, create it :
hFile = CreateFile(szFilePath_memory_bin,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* lpSecurityAttributes */nullptr,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
/* hTemplateFile */nullptr);
if (hFile == INVALID_HANDLE_VALUE)
{
CxbxKrnlCleanup("CxbxRestoreContiguousMemory : Couldn't create memory.bin file!\n");
return nullptr;
}
}
// TODO : Make sure memory.bin is at least 64 MB in size - FileSeek(hFile, CONTIGUOUS_MEMORY_SIZE, soFromBeginning);
HANDLE hFileMapping = CreateFileMapping(
hFile,
/* lpFileMappingAttributes */nullptr,
PAGE_READWRITE,
/* dwMaximumSizeHigh */0,
/* dwMaximumSizeLow */CONTIGUOUS_MEMORY_SIZE,
/**/nullptr);
if (hFileMapping == NULL)
{
CxbxKrnlCleanup("CxbxRestoreContiguousMemory : Couldn't create contiguous memory.bin file mapping!\n");
return nullptr;
}
// Map memory.bin contents into memory :
void *memory = (void *)MapViewOfFileEx(
hFileMapping,
FILE_MAP_READ | FILE_MAP_WRITE,
/* dwFileOffsetHigh */0,
/* dwFileOffsetLow */0,
CONTIGUOUS_MEMORY_SIZE,
(void *)MM_SYSTEM_PHYSICAL_MAP);
if (memory == NULL)
{
CxbxKrnlCleanup("CxbxRestoreContiguousMemory: Couldn't map contiguous memory.bin into memory!");
return nullptr;
}
if (NeedsInitialization)
{
memset(memory, 0, CONTIGUOUS_MEMORY_SIZE);
DbgPrintf("EmuMain: Initialized contiguous memory\n");
}
else
DbgPrintf("EmuMain: Loaded contiguous memory.bin\n");
return memory;
}
void CxbxKrnlMain(int argc, char* argv[])
{
// Skip '/load' switch
@ -251,14 +323,24 @@ void CxbxKrnlMain(int argc, char* argv[])
// Now we got the arguments, start by initializing the Xbox memory map :
// PrepareXBoxMemoryMap()
{
// Our executable DOS image header must be loaded at 0x00010000
// Assert(ExeDosHeader == XBE_IMAGE_BASE);
// Determine EXE's header locations & size :
ExeNtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)ExeDosHeader + ExeDosHeader->e_lfanew); // = + 0x138
ExeOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&(ExeNtHeader->OptionalHeader);
// verify emulated_memory_placeholder is located at 0x00011000
if ((UINT_PTR)(&(emulated_memory_placeholder[0])) != (XBE_IMAGE_BASE + ExeNtHeader->OptionalHeader.BaseOfCode))
// verify base of code of our executable is 0x00001000
if (ExeNtHeader->OptionalHeader.BaseOfCode != CXBX_BASE_OF_CODE)
{
MessageBox(NULL, "emulated_memory_placeholder is not loaded to base address 0x00011000 (which is a requirement for Xbox emulation)", "Cxbx-Reloaded", MB_OK);
MessageBox(NULL, "Cxbx-Reloaded executuable requires it's base of code to be 0x00001000", "Cxbx-Reloaded", MB_OK);
return; // TODO : Halt(0);
}
// verify virtual_memory_placeholder is located at 0x00011000
if ((UINT_PTR)(&(virtual_memory_placeholder[0])) != (XBE_IMAGE_BASE + CXBX_BASE_OF_CODE))
{
MessageBox(NULL, "virtual_memory_placeholder is not loaded to base address 0x00011000 (which is a requirement for Xbox emulation)", "Cxbx-Reloaded", MB_OK);
return; // TODO : Halt(0);
}
@ -276,15 +358,15 @@ void CxbxKrnlMain(int argc, char* argv[])
// Note : NewOptionalHeader->ImageBase can stay at ExeOptionalHeader->ImageBase = 0x00010000
// Note : Since emulated_memory_placeholder prevents overlap between reserved xbox memory
// and Cxbx.exe sections, the new section headers don't have to be patched up.
// Note : Since virtual_memory_placeholder prevents overlap between reserved xbox memory
// and Cxbx.exe sections, section headers don't have to be patched up.
// Mark the entire emulated memory range accessible
// Mark the virtual memory range completely accessible
DWORD OldProtection;
VirtualProtect((void*)XBE_IMAGE_BASE, EMU_MAX_MEMORY_SIZE, PAGE_EXECUTE_READWRITE, &OldProtection);
VirtualProtect((void*)XBE_IMAGE_BASE, XBE_MAX_VA - XBE_IMAGE_BASE, PAGE_EXECUTE_READWRITE, &OldProtection);
// Clear out the entire memory range
memset((void*)ExeDosHeader, 0, EMU_MAX_MEMORY_SIZE);
// Clear out the virtual memory range
memset((void*)XBE_IMAGE_BASE, 0, XBE_MAX_VA - XBE_IMAGE_BASE);
// Restore enough of the executable image headers to keep WinAPI's working :
RestoreExeImageHeader();
@ -292,18 +374,23 @@ void CxbxKrnlMain(int argc, char* argv[])
CxbxInitFilePaths();
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
if (EEPROM == nullptr)
CxbxKrnlCleanup("EmuMain : Couldn't init EEPROM!");
CxbxRestoreContiguousMemory(szFilePath_memory_bin);
CxbxRestorePersistentMemoryRegions();
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
if (EEPROM == nullptr)
{
MessageBox(NULL, "Couldn't init EEPROM!", "Cxbx-Reloaded", MB_OK);
return; // TODO : Halt(0);
}
// TODO : Instead of loading an Xbe here, initialize the kernel so that it will launch the Xbe on itself.
// Now we can load and run the XBE :
// MapAndRunXBE(XbePath, DCHandle);
{
// Load Xbe (this will reside above WinMain's emulated_memory_placeholder)
// Load Xbe (this one will reside above WinMain's virtual_memory_placeholder)
g_EmuShared->SetXbePath(xbePath.c_str());
CxbxKrnl_Xbe = new Xbe(xbePath.c_str()); // TODO : Instead of using the Xbe class, port Dxbx _ReadXbeBlock()
@ -324,6 +411,16 @@ void CxbxKrnlMain(int argc, char* argv[])
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwLibraryVersionsAddr, CxbxKrnl_Xbe->m_LibraryVersion, CxbxKrnl_Xbe->m_Header.dwLibraryVersions * sizeof(DWORD));
// TODO : Actually, instead of copying from CxbxKrnl_Xbe, we should load the entire Xbe directly into memory, like Dxbx does - see _ReadXbeBlock()
// Verify no section would load outside virtual_memory_placeholder (which would overwrite Cxbx code)
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
xbaddr section_end = CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr + CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw;
if (section_end >= XBE_MAX_VA)
{
MessageBox(NULL, "Couldn't load XBE section - please report this!", "Cxbx-Reloaded", MB_OK);
return; // TODO : Halt(0);
}
}
// Load all sections to their requested Virtual Address :
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
memcpy((void*)CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr, CxbxKrnl_Xbe->m_bzSection[i], CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw);
@ -477,13 +574,7 @@ void CxbxKrnlInit
IMAGE_SECTION_HEADER SectionHeader;
} *PDUMMY_KERNEL;
PDUMMY_KERNEL DummyKernel = (PDUMMY_KERNEL)VirtualAlloc(
(PVOID)XBOX_KERNEL_BASE, sizeof(DUMMY_KERNEL),
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE
);
if (DummyKernel == NULL)
CxbxKrnlCleanup("InitializeDummyKernel: Could not allocate dummy kernel.");
PDUMMY_KERNEL DummyKernel = (PDUMMY_KERNEL)XBOX_KERNEL_BASE;
memset(DummyKernel, 0, sizeof(DUMMY_KERNEL));
// XapiRestrictCodeSelectorLimit only checks these fields.
@ -662,7 +753,8 @@ void CxbxInitFilePaths()
CxbxKrnlCleanup("CxbxInitFilePaths : Couldn't create CxbxReloaded AppData folder!");
snprintf(szFilePath_LaunchDataPage_bin, MAX_PATH, "%s\\CxbxLaunchDataPage.bin", szFolder_CxbxReloadedData);
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData); // TODO : Start using this
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData);
snprintf(szFilePath_memory_bin, MAX_PATH, "%s\\memory.bin", szFolder_CxbxReloadedData);
GetModuleFileName(GetModuleHandle(NULL), szFilePath_CxbxReloaded_Exe, MAX_PATH);
}

View File

@ -52,6 +52,10 @@ extern "C" {
#define OPCODE_CALL_E8 0xE8
#define OPCODE_JMP_E9 0xE9
// Sizes
#define ONE_KB 1024
#define ONE_MB (1024 * 1024)
// Thread Information Block offsets - see https://www.microsoft.com/msj/archive/S2CE.aspx
#define TIB_ArbitraryDataSlot 0x14
#define TIB_LinearSelfAddress 0x18
@ -63,21 +67,26 @@ typedef uint32 xbaddr;
#define XBADDR_MAX UINT32_MAX
/*! memory size per system */
#define XBOX_MEMORY_SIZE 64 * 1024 * 1024
#define CHIHIRO_MEMORY_SIZE 128 * 1024 * 1024
/*! maximum memory size our emulator must support */
#define EMU_MAX_MEMORY_SIZE CHIHIRO_MEMORY_SIZE
#define XBOX_MEMORY_SIZE (64 * ONE_MB)
#define CHIHIRO_MEMORY_SIZE (128 * ONE_MB)
/*! base addresses of various components */
#define XBOX_BASE_ADDR 0x00010000
#define XBOX_KERNEL_BASE 0x80010000
#define XBOX_NV2A_INIT_VECTOR 0xFF000008
#define XBE_IMAGE_BASE XBOX_BASE_ADDR
#define XBE_IMAGE_BASE 0x00010000
// For now, virtual addresses are somewhat limited, as we use
// these soley for loading XBE sections. The largest that we
// know of, is "BLiNX: the time sweeper", which has a section
// (called "$$XTIMAG") at 0x031C5260+0x00002800, which would
// fit in 51 MB. If we ever encounter an even larger XBE, this
// value will have to be increased likewise (maybe up to 64 MB
// for XBOX_MEMORY_SIZE or even 128 MB for CHIHIRO_MEMORY_SIZE).
#define XBE_MAX_VA (51 * ONE_MB)
/*! base address of Cxbx host executable, see Cxbx project options, Linker, Advanced, Base Address */
#define CXBX_BASE_ADDR XBE_IMAGE_BASE
#define CXBX_BASE_OF_CODE 0x00001000
#define MAX_BUS_INTERRUPT_LEVEL 27
// MAX_BUS_INTERRUPT_LEVEL = PROFILE_LEVEL = 27

View File

@ -238,6 +238,23 @@ VOID XTL::CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize)
SetFocus(g_hEmuWindow);
}
XTL::IDirect3DResource8 *GetHostResource(XTL::X_D3DResource *pThis)
{
if (pThis->Data == X_D3DRESOURCE_DATA_YUV_SURFACE)
return nullptr;
if (pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
return nullptr;
if (pThis->EmuResource8 == nullptr)
{
__asm int 3;
//EmuWarning("EmuResource is not a valid pointer!");
}
return pThis->EmuResource8;
}
int GetD3DResourceRefCount(XTL::IDirect3DResource8 *EmuResource)
{
if (EmuResource != nullptr)
@ -2367,14 +2384,7 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetRenderTarget2)()
X_D3DSurface *result = g_pCachedRenderTarget;
if (result != NULL)
{
IDirect3DSurface8 *pSurface8 = result->EmuSurface8;
if (pSurface8 != nullptr)
pSurface8->AddRef();
result->Common++; // AddRef
}
EMUPATCH(D3DResource_AddRef)(result);
DbgPrintf("EmuD3D8: RenderTarget := 0x%.08X\n", result);
@ -2408,14 +2418,7 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)()
X_D3DSurface *result = g_pCachedDepthStencil;
if (result != NULL)
{
IDirect3DSurface8 *pSurface8 = result->EmuSurface8;
if (pSurface8 != nullptr)
pSurface8->AddRef();
result->Common++; // AddRef
}
EMUPATCH(D3DResource_AddRef)(result);
DbgPrintf("EmuD3D8: DepthStencilSurface := 0x%.08X\n", result);
@ -5078,29 +5081,27 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef)
");\n",
pThis);
ULONG uRet = 0;
if (!pThis) {
if (!pThis)
{
EmuWarning("IDirect3DResource8::AddRef() was not passed a valid pointer!");
return 0;
}
else
{
pThis->Common++; // AddRef
if (pThis->Data == X_D3DRESOURCE_DATA_YUV_SURFACE)
uRet = pThis->Common;
else
{
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
if(pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
uRet = ++pThis->Lock;
else if(pResource8 != 0)
uRet = pResource8->AddRef();
if(!pResource8)
__asm int 3;
//EmuWarning("EmuResource is not a valid pointer!");
}
}
// Initially, increment the Xbox refcount and return that
ULONG uRet = (++(pThis->Common)) & X_D3DCOMMON_REFCOUNT_MASK;
// If this is the first reference on a surface
if (uRet == 1)
if (pThis->Common & X_D3DCOMMON_TYPE_SURFACE)
// Try to AddRef the parent too
if (((X_D3DSurface *)pThis)->Parent != NULL)
((X_D3DSurface *)pThis)->Parent->Common++;
// Try to retrieve the host resource behind this resource
IDirect3DResource8 *pResource8 = GetHostResource(pThis);
if (pResource8 != 0)
// if there's a host resource, AddRef it too and return that
uRet = pResource8->AddRef();
return uRet;
}
@ -5669,9 +5670,10 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DTexture_GetSurfaceLevel2)
EmuWarning("EmuIDirect3DTexture8_GetSurfaceLevel Failed!");
result->Parent = pThis;
pThis->Common++; // AddRef Parent too
}
pThis->Common++; // AddRef
result->Common++; // Don't EMUPATCH(D3DResource_AddRef)(result) - that would AddRef Parent one too many
}
DbgPrintf("EmuD3D8: EmuIDirect3DTexture8_GetSurfaceLevel := 0x%.08X\n", result);
@ -5856,6 +5858,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DDevice_Release)()
DbgPrintf("EmuD3D8: EmuD3DDevice_Release();\n");
// See GetD3DResourceRefCount()
g_pD3DDevice8->AddRef();
DWORD RefCount = g_pD3DDevice8->Release();
if (RefCount == 1)
@ -8894,13 +8897,13 @@ PVOID WINAPI XTL::EMUPATCH(D3D_AllocContiguousMemory)
// so that we can return a valid page aligned pointer
//
PVOID pRet = CxbxMalloc(dwSize + 0x1000);
PVOID pRet = CxbxMalloc(dwSize + PAGE_SIZE);
// align to page boundary
{
DWORD dwRet = (DWORD)pRet;
dwRet += 0x1000 - dwRet%0x1000;
dwRet += PAGE_SIZE - dwRet % PAGE_SIZE;
g_AlignCache.insert(dwRet, pRet);

View File

@ -386,8 +386,8 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
// Be aware that TLS might be absent (for example in homebrew "Wolf3d-xbox")
if (pTLS != nullptr) {
// Make sure the TLS Start and End addresses are within Xbox Memory
if (pTLS->dwDataStartAddr >= EMU_MAX_MEMORY_SIZE || pTLS->dwDataEndAddr >= EMU_MAX_MEMORY_SIZE) {
// Make sure the TLS Start and End addresses are within Xbox virtual memory
if (pTLS->dwDataStartAddr >= XBE_MAX_VA || pTLS->dwDataEndAddr >= XBE_MAX_VA) {
return;
}

View File

@ -517,7 +517,7 @@ XBSYSAPI EXPORTNUM(29) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExSaveNonVolatileSetti
const EEPROMInfo* info = EmuFindEEPROMInfo((XC_VALUE_INDEX)ValueIndex);
if (info != nullptr)
{
value_addr = (void *)(EEPROM + info->value_offset);
value_addr = (void *)((PBYTE)EEPROM + info->value_offset);
result_length = info->value_length;
};
}

View File

@ -87,17 +87,6 @@ std::ostream& operator<<(std::ostream& os, const PULONG& value)
//
FLAGS2STR_START(ALLOCATION_TYPE)
FLAG2STR(PAGE_NOACCESS)
FLAG2STR(PAGE_READONLY)
FLAG2STR(PAGE_READWRITE)
FLAG2STR(PAGE_WRITECOPY)
FLAG2STR(PAGE_EXECUTE)
FLAG2STR(PAGE_EXECUTE_READ)
FLAG2STR(PAGE_EXECUTE_READWRITE)
FLAG2STR(PAGE_EXECUTE_WRITECOPY)
FLAG2STR(PAGE_GUARD)
FLAG2STR(PAGE_NOCACHE)
FLAG2STR(PAGE_WRITECOMBINE)
FLAG2STR(MEM_COMMIT)
FLAG2STR(MEM_RESERVE)
FLAG2STR(MEM_DECOMMIT)
@ -105,19 +94,12 @@ FLAGS2STR_START(ALLOCATION_TYPE)
FLAG2STR(MEM_FREE)
FLAG2STR(MEM_PRIVATE)
FLAG2STR(MEM_MAPPED)
FLAG2STR(MEM_RESET)
//FLAG2STR(MEM_RESET)
FLAG2STR(MEM_TOP_DOWN)
FLAG2STR(MEM_WRITE_WATCH)
FLAG2STR(MEM_PHYSICAL)
FLAG2STR(SEC_FILE)
FLAG2STR(SEC_IMAGE)
FLAG2STR(SEC_RESERVE)
FLAG2STR(SEC_COMMIT)
FLAG2STR(SEC_NOCACHE)
FLAG2STR(MEM_LARGE_PAGES)
FLAG2STR(MEM_4MB_PAGES)
// MEM_IMAGE = SEC_IMAGE;
// WRITE_WATCH_FLAG_RESET = $01;
FLAG2STR(MEM_NOZERO)
FLAG2STR(MEM_IMAGE)
FLAGS2STR_END_and_LOGRENDER(ALLOCATION_TYPE)
ENUM2STR_START(BUS_DATA_TYPE)
@ -322,6 +304,20 @@ ENUM2STR_START(NTSTATUS) // Not really an enum
ENUM2STR_END_and_LOGRENDER(NTSTATUS)
*/
FLAGS2STR_START(PROTECTION_TYPE)
FLAG2STR(PAGE_NOACCESS)
FLAG2STR(PAGE_READONLY)
FLAG2STR(PAGE_READWRITE)
FLAG2STR(PAGE_WRITECOPY)
FLAG2STR(PAGE_EXECUTE)
FLAG2STR(PAGE_EXECUTE_READ)
FLAG2STR(PAGE_EXECUTE_READWRITE)
FLAG2STR(PAGE_EXECUTE_WRITECOPY)
FLAG2STR(PAGE_GUARD)
FLAG2STR(PAGE_NOCACHE)
FLAG2STR(PAGE_WRITECOMBINE)
FLAGS2STR_END_and_LOGRENDER(PROTECTION_TYPE)
ENUM2STR_START(RETURN_FIRMWARE)
ENUM2STR_CASE(ReturnFirmwareHalt)
ENUM2STR_CASE(ReturnFirmwareReboot)

View File

@ -45,6 +45,7 @@ namespace xboxkrnl
enum ALLOCATION_TYPE;
enum CREATE_DISPOSITION;
enum CREATE_OPTION;
enum PROTECTION_TYPE;
};
@ -74,6 +75,7 @@ LOGRENDER_HEADER(KWAIT_REASON);
LOGRENDER_HEADER(KOBJECTS);
LOGRENDER_HEADER(MODE);
//LOGRENDER_HEADER(NTSTATUS); // Not really an enum
LOGRENDER_HEADER(PROTECTION_TYPE); // Not really an enum
LOGRENDER_HEADER(RETURN_FIRMWARE);
LOGRENDER_HEADER(TIMER_TYPE);
LOGRENDER_HEADER(WAIT_TYPE);

View File

@ -89,6 +89,8 @@ XBSYSAPI EXPORTNUM(165) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
return MmAllocateContiguousMemoryEx(NumberOfBytes, 0, MAXULONG_PTR, 0, PAGE_READWRITE);
}
#define PAGE_KNOWN_FLAGS (PAGE_READONLY | PAGE_READWRITE | PAGE_NOCACHE | PAGE_WRITECOMBINE)
// ******************************************************************
// * 0x00A6 - MmAllocateContiguousMemoryEx()
// ******************************************************************
@ -106,29 +108,44 @@ XBSYSAPI EXPORTNUM(166) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateContiguousMemo
LOG_FUNC_ARG(LowestAcceptableAddress)
LOG_FUNC_ARG(HighestAcceptableAddress)
LOG_FUNC_ARG(Alignment)
LOG_FUNC_ARG(ProtectionType)
LOG_FUNC_ARG_TYPE(PROTECTION_TYPE, ProtectionType)
LOG_FUNC_END;
if(Alignment == 0)
Alignment = 0x1000; // page boundary at least
//
// NOTE: Kludgey (but necessary) solution:
//
// Since this memory must be aligned on a page boundary, we must allocate an extra page
// so that we can return a valid page aligned pointer
//
PVOID pRet = (PVOID)1; // Marker, never returned, overwritten with NULL on input error
// TODO : Allocate differently if(ProtectionType & PAGE_WRITECOMBINE)
PVOID pRet = CxbxMalloc(NumberOfBytes + Alignment);
if (Alignment < PAGE_SIZE)
Alignment = PAGE_SIZE; // page boundary at least
// align to page boundary
// Only known flags are allowed
if ((ProtectionType & ~PAGE_KNOWN_FLAGS) != 0)
pRet = NULL;
// Either PAGE_READONLY or PAGE_READWRITE must be set (not both, nor none)
if (((ProtectionType & PAGE_READONLY) > 0) == ((ProtectionType & PAGE_READWRITE) > 0))
pRet = NULL;
// Combining PAGE_NOCACHE and PAGE_WRITECOMBINE isn't allowed
if ((ProtectionType & (PAGE_NOCACHE | PAGE_WRITECOMBINE)) == (PAGE_NOCACHE | PAGE_WRITECOMBINE))
pRet = NULL;
// Allocate when input arguments are valid
if (pRet != NULL)
{
//
// NOTE: Kludgey (but necessary) solution:
//
// Since this memory must be aligned on a page boundary, we must allocate an extra page
// so that we can return a valid page aligned pointer
//
// TODO : Allocate differently if(ProtectionType & PAGE_WRITECOMBINE)
pRet = CxbxMalloc(NumberOfBytes + Alignment);
// align to page boundary
DWORD dwRet = (DWORD)pRet;
dwRet += Alignment - dwRet % Alignment;
g_AlignCache.insert(dwRet, pRet);
pRet = (PVOID)dwRet;
}

View File

@ -61,6 +61,12 @@ namespace NtDll
#include <ntstatus.h>
#pragma warning(default:4005)
#define MEM_KNOWN_FLAGS (MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_RESET | MEM_NOZERO)
#define MM_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF
#define X64K ((ULONG)64*1024)
#define MM_HIGHEST_VAD_ADDRESS ((PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - X64K))
// ******************************************************************
// * 0x00B8 - NtAllocateVirtualMemory()
// ******************************************************************
@ -81,27 +87,65 @@ XBSYSAPI EXPORTNUM(184) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtAllocateVirtualMemo
LOG_FUNC_ARG(Protect)
LOG_FUNC_END;
// TODO: The flag known as MEM_NOZERO (which appears to be exclusive to Xbox) has the exact
// same value as MEM_ROTATE which causes problems for Windows XP, but not Vista. Removing
// this flag fixes Azurik for XP.
DWORD MEM_NOZERO = 0x800000;
NTSTATUS ret = 0;
if (AllocationType & MEM_NOZERO)
PVOID RequestedBaseAddress = *BaseAddress;
ULONG RequestedAllocationSize = *AllocationSize;
// Don't allow base address to exceed highest virtual address
if (RequestedBaseAddress > MM_HIGHEST_VAD_ADDRESS)
ret = STATUS_INVALID_PARAMETER;
// Limit number of zero bits upto 20
if (ZeroBits > 21)
ret = STATUS_INVALID_PARAMETER;
// No empty allocation allowed
if (RequestedAllocationSize == 0)
ret = STATUS_INVALID_PARAMETER;
// Allocation should fit in remaining address range
if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)RequestedBaseAddress + 1) < RequestedAllocationSize)
ret = STATUS_INVALID_PARAMETER;
// Only known flags are allowed
if ((AllocationType & ~MEM_KNOWN_FLAGS) != 0)
ret = STATUS_INVALID_PARAMETER;
// No other flags allowed in combination with MEM_RESET
if (AllocationType & MEM_RESET)
{
EmuWarning("MEM_NOZERO flag is not supported!");
AllocationType &= ~MEM_NOZERO;
if (AllocationType != MEM_RESET)
ret = STATUS_INVALID_PARAMETER;
}
else
// At least MEM_RESET, MEM_COMMIT or MEM_RESERVE must be set
if ((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == 0)
ret = STATUS_INVALID_PARAMETER;
NTSTATUS ret = NtDll::NtAllocateVirtualMemory(
/*ProcessHandle=*/g_CurrentProcessHandle,
BaseAddress,
ZeroBits,
/*RegionSize=*/AllocationSize,
AllocationType,
Protect);
if (ret == 0)
{
// TODO: The flag known as MEM_NOZERO (which appears to be exclusive to Xbox) has the exact
// same value as MEM_ROTATE which causes problems for Windows XP, but not Vista. Removing
// this flag fixes Azurik for XP.
if (ret == 0xC00000F3)
EmuWarning("Invalid Param!");
if (AllocationType & MEM_NOZERO)
{
EmuWarning("MEM_NOZERO flag is not supported!");
AllocationType &= ~MEM_NOZERO;
}
ret = NtDll::NtAllocateVirtualMemory(
/*ProcessHandle=*/g_CurrentProcessHandle,
BaseAddress,
ZeroBits,
/*RegionSize=*/AllocationSize,
AllocationType,
Protect);
if (ret == STATUS_INVALID_PARAMETER_5) // = 0xC00000F3
EmuWarning("Invalid Param!");
}
RETURN(ret);
}

View File

@ -766,8 +766,8 @@ bool EmuX86_Opcode_OUT(LPEXCEPTION_POINTERS e, _DInst& info)
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
{
// Only decode instructions within Xbox memory space
if (e->ContextRecord->Eip > EMU_MAX_MEMORY_SIZE || e->ContextRecord->Eip < XBOX_BASE_ADDR) {
// Only decode instructions which reside in the loaded Xbe
if (e->ContextRecord->Eip > XBE_MAX_VA || e->ContextRecord->Eip < XBE_IMAGE_BASE) {
return false;
}

View File

@ -1217,19 +1217,6 @@ DWORD WINAPI XTL::EMUPATCH(XInputGetDeviceDescription)
RETURN(ERROR_NOT_SUPPORTED); // ERROR_DEVICE_NOT_CONNECTED;
}
// ******************************************************************
// * patch: XAutoPowerDownResetTimer
// ******************************************************************
int WINAPI XTL::EMUPATCH(XAutoPowerDownResetTimer)()
{
LOG_FUNC();
// Meh, that's what the 'X' is for! =]
LOG_UNIMPLEMENTED();
RETURN(TRUE);
}
// ******************************************************************
// * patch: XMountMURootA
// ******************************************************************

View File

@ -723,11 +723,6 @@ DWORD WINAPI EMUPATCH(XInputGetDeviceDescription)
PVOID pDescription
);
// ******************************************************************
// * patch: XAutoPowerDownResetTimer
// ******************************************************************
int WINAPI EMUPATCH(XAutoPowerDownResetTimer)();
// ******************************************************************
// * patch: ReadFileEx
// ******************************************************************

View File

@ -1098,7 +1098,7 @@ OOVPATable XAPI_3911[] = {
REGISTER_OOVPA(XMountMUA, 3911, PATCH),
REGISTER_OOVPA(XLaunchNewImage, 3911, ALIAS, XLaunchNewImageA),
REGISTER_OOVPA(XGetLaunchInfo, 3911, DISABLED),
REGISTER_OOVPA(XAutoPowerDownResetTimer, 3911, PATCH),
REGISTER_OOVPA(XAutoPowerDownResetTimer, 3911, DISABLED), // Just calls KeSetTimer
REGISTER_OOVPA(XMountMURootA, 3911, PATCH),
REGISTER_OOVPA(XMountUtilityDrive, 3911, PATCH),
REGISTER_OOVPA(OutputDebugStringA, 3911, PATCH),