Merge pull request #254 from PatrickvL/ContiguousMemory
MemoryRelatedImprovements
This commit is contained in:
commit
71b81a821c
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
// ******************************************************************
|
||||
|
|
|
@ -723,11 +723,6 @@ DWORD WINAPI EMUPATCH(XInputGetDeviceDescription)
|
|||
PVOID pDescription
|
||||
);
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XAutoPowerDownResetTimer
|
||||
// ******************************************************************
|
||||
int WINAPI EMUPATCH(XAutoPowerDownResetTimer)();
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: ReadFileEx
|
||||
// ******************************************************************
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue