Merge pull request #168 from PatrickvL/master
Various improvements to kernel, vertices, comments and code quality
This commit is contained in:
commit
95687f153a
|
@ -224,7 +224,11 @@ XBSYSAPI EXPORTNUM(128) VOID NTAPI KeQuerySystemTime
|
|||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(129) UCHAR NTAPI KeRaiseIrqlToDpcLevel();
|
||||
|
||||
XBSYSAPI VOID *KeRaiseIrqlToSynchLevel;
|
||||
// ******************************************************************
|
||||
// * 0x0082 - KeRaiseIrqlToSynchLevel()
|
||||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(130) UCHAR NTAPI KeRaiseIrqlToSynchLevel();
|
||||
|
||||
XBSYSAPI VOID *KeReleaseMutant;
|
||||
XBSYSAPI VOID *KeReleaseSemaphore;
|
||||
XBSYSAPI VOID *KeRemoveByKeyDeviceQueue;
|
||||
|
|
|
@ -1903,18 +1903,19 @@ typedef struct _KPRCB
|
|||
struct _KTHREAD* NextThread; // 0x04, KPCR : 0x2C
|
||||
struct _KTHREAD* IdleThread; // 0x08, KPCR : 0x30
|
||||
|
||||
ULONG Unknown1[8]; // 0x0C, KPCR : 0x34
|
||||
ULONG Unknown1[7]; // 0x0C, KPCR : 0x34
|
||||
|
||||
ULONG DpcRoutineActive; // 0x2C, KPCR : 0x54
|
||||
LIST_ENTRY DpcListHead; // 0x28, KPCR : 0x50
|
||||
ULONG DpcRoutineActive; // 0x30, KPCR : 0x58
|
||||
|
||||
// This is the total size of the structure (presumably)
|
||||
UCHAR Unknown[0x22C];
|
||||
// This completes the total size of the structure (presumably)
|
||||
UCHAR Unknown[0x224];
|
||||
}
|
||||
KPRCB, *PKPRCB;
|
||||
|
||||
|
||||
// ******************************************************************
|
||||
// * KPCR
|
||||
// * KPCR (Kernel Processor Control Region)
|
||||
// ******************************************************************
|
||||
// *
|
||||
// * NOTE: KPCR is the structure which exists at the FS: segment.
|
||||
|
|
|
@ -46,11 +46,16 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Opcodes
|
||||
#define OPCODE_NOP_90 0x90
|
||||
#define OPCODE_INT3_CC 0xCC
|
||||
#define OPCODE_CALL_E8 0xE8
|
||||
#define OPCODE_JMP_E9 0xE9
|
||||
|
||||
// Thread Information Block offsets - see https://www.microsoft.com/msj/archive/S2CE.aspx
|
||||
#define TIB_ArbitraryDataSlot 0x14
|
||||
#define TIB_LinearSelfAddress 0x18
|
||||
|
||||
/*! xbaddr is the type of a physical address */
|
||||
typedef uint32 xbaddr;
|
||||
|
||||
|
|
|
@ -504,124 +504,122 @@ bool XTL::VertexPatcher::PatchStream(VertexPatchDesc *pPatchDesc,
|
|||
|
||||
for (uint32 uiVertex = 0; uiVertex < pPatchDesc->dwVertexCount; uiVertex++)
|
||||
{
|
||||
DWORD dwPosOrig = 0;
|
||||
uint08 *pOrigVertex = &pOrigData[uiVertex * uiStride];
|
||||
uint08 *pNewDataPos = &pNewData[uiVertex * pStreamPatch->ConvertedStride];
|
||||
for (UINT uiType = 0; uiType < pStreamPatch->NbrTypes; uiType++)
|
||||
{
|
||||
// Dxbx note : The following code handles only the D3DVSDT enums that need conversion;
|
||||
// All other cases are catched by the memcpy in the default-block.
|
||||
switch (pStreamPatch->pTypes[uiType])
|
||||
{
|
||||
case X_D3DVSDT_NORMPACKED3: // 0x16:
|
||||
{
|
||||
DWORD dwPacked = ((DWORD *)&pOrigData[uiVertex * uiStride + dwPosOrig])[0];
|
||||
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)(dwPacked & 0x7ff)) / 1023.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((dwPacked >> 11) & 0x7ff)) / 1023.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((dwPacked >> 22) & 0x3ff)) / 511.0f;
|
||||
|
||||
dwPosOrig += sizeof(DWORD);
|
||||
case X_D3DVSDT_NORMPACKED3: { // 0x16: // Make it FLOAT3
|
||||
// Hit by Dashboard
|
||||
int32 iPacked = ((int32 *)pOrigVertex)[0];
|
||||
// Cxbx note : to make each component signed, two need to be shifted towards the sign-bit first :
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((iPacked << 21) >> 21)) / 1023.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((iPacked << 10) >> 21)) / 1023.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((iPacked ) >> 22)) / 511.0f;
|
||||
pOrigVertex += 1 * sizeof(int32);
|
||||
break;
|
||||
}
|
||||
case X_D3DVSDT_SHORT1: // 0x15:
|
||||
// Make it a SHORT2
|
||||
((SHORT *)pNewDataPos)[0] = *(SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig];
|
||||
case X_D3DVSDT_SHORT1: { // 0x15: // Make it SHORT2 and set the second short to 0
|
||||
((SHORT *)pNewDataPos)[0] = ((SHORT*)pOrigVertex)[0];
|
||||
((SHORT *)pNewDataPos)[1] = 0x00;
|
||||
|
||||
dwPosOrig += 1 * sizeof(SHORT);
|
||||
pOrigVertex += 1 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_SHORT3: // 0x35:
|
||||
memcpy(pNewDataPos,
|
||||
&pOrigData[uiVertex * uiStride + dwPosOrig],
|
||||
3 * sizeof(SHORT));
|
||||
// Make it a SHORT4 and set the last short to 1
|
||||
//(*((SHORT *)&pNewData[uiVertex * pStreamPatch->ConvertedStride + dwPosNew + 3 * sizeof(SHORT)])) = 0x01;
|
||||
}
|
||||
case X_D3DVSDT_SHORT3: { // 0x35: // Make it a SHORT4 and set the fourth short to 1
|
||||
// Hit by Turok
|
||||
memcpy(pNewDataPos, pOrigVertex, 3 * sizeof(SHORT));
|
||||
((SHORT *)pNewDataPos)[3] = 0x01;
|
||||
|
||||
dwPosOrig += 3 * sizeof(SHORT);
|
||||
pOrigVertex += 3 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE1: // 0x14:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 255.0f;
|
||||
|
||||
dwPosOrig += 1 * sizeof(BYTE);
|
||||
|
||||
}
|
||||
case X_D3DVSDT_PBYTE1: { // 0x14: // Make it FLOAT1
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)pOrigVertex)[0]) / 255.0f;
|
||||
pOrigVertex += 1 * sizeof(BYTE);
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE2: // 0x24:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 255.0f;
|
||||
|
||||
dwPosOrig += 2 * sizeof(BYTE);
|
||||
|
||||
}
|
||||
case X_D3DVSDT_PBYTE2: { // 0x24: // Make it FLOAT2
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)pOrigVertex)[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)pOrigVertex)[1]) / 255.0f;
|
||||
pOrigVertex += 2 * sizeof(BYTE);
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE3: // 0x34:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[2]) / 255.0f;
|
||||
|
||||
dwPosOrig += 3 * sizeof(BYTE);
|
||||
|
||||
}
|
||||
case X_D3DVSDT_PBYTE3: { // 0x34: // Make it FLOAT3
|
||||
// Hit by Turok
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)pOrigVertex)[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)pOrigVertex)[1]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((BYTE*)pOrigVertex)[2]) / 255.0f;
|
||||
pOrigVertex += 3 * sizeof(BYTE);
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE4: // 0x44:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[2]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT)((BYTE*)&pOrigData[uiVertex * uiStride + dwPosOrig])[3]) / 255.0f;
|
||||
|
||||
dwPosOrig += 4 * sizeof(BYTE);
|
||||
|
||||
}
|
||||
case X_D3DVSDT_PBYTE4: { // 0x44: // Make it FLOAT4
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((BYTE*)pOrigVertex)[0]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((BYTE*)pOrigVertex)[1]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((BYTE*)pOrigVertex)[2]) / 255.0f;
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT)((BYTE*)pOrigVertex)[3]) / 255.0f;
|
||||
pOrigVertex += 4 * sizeof(BYTE);
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT1: // 0x11:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 32767.0f;
|
||||
|
||||
dwPosOrig += 1 * sizeof(SHORT);
|
||||
}
|
||||
case X_D3DVSDT_NORMSHORT1: { // 0x11: // Make it FLOAT1
|
||||
// UNTESTED - Need test-case!
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
|
||||
pOrigVertex += 1 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT2: // 0x21:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 32767.0f;
|
||||
|
||||
dwPosOrig += 2 * sizeof(SHORT);
|
||||
}
|
||||
case X_D3DVSDT_NORMSHORT2: { // 0x21: // Make it FLOAT2
|
||||
// UNTESTED - Need test-case!
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
|
||||
pOrigVertex += 2 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT3: // 0x31:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[2]) / 32767.0f;
|
||||
|
||||
dwPosOrig += 3 * sizeof(SHORT);
|
||||
}
|
||||
case X_D3DVSDT_NORMSHORT3: { // 0x31: // Make it FLOAT3
|
||||
// UNTESTED - Need test-case!
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)pOrigVertex)[2]) / 32767.0f;
|
||||
pOrigVertex += 3 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT4: // 0x41:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[2]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT)((SHORT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[3]) / 32767.0f;
|
||||
|
||||
dwPosOrig += 4 * sizeof(SHORT);
|
||||
}
|
||||
case X_D3DVSDT_NORMSHORT4: { // 0x41: // Make it FLOAT4
|
||||
// UNTESTED - Need test-case!
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)pOrigVertex)[2]) / 32767.0f;
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT)((SHORT*)pOrigVertex)[3]) / 32767.0f;
|
||||
pOrigVertex += 4 * sizeof(SHORT);
|
||||
break;
|
||||
case X_D3DVSDT_FLOAT2H: // 0x72:
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[0];
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[1];
|
||||
}
|
||||
case X_D3DVSDT_FLOAT2H: { // 0x72: // Make it FLOAT4 and set the third float to 0.0
|
||||
((FLOAT *)pNewDataPos)[0] = ((FLOAT*)pOrigVertex)[0];
|
||||
((FLOAT *)pNewDataPos)[1] = ((FLOAT*)pOrigVertex)[1];
|
||||
((FLOAT *)pNewDataPos)[2] = 0.0f;
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT*)&pOrigData[uiVertex * uiStride + dwPosOrig])[2];
|
||||
((FLOAT *)pNewDataPos)[3] = ((FLOAT*)pOrigVertex)[2];
|
||||
pOrigVertex += 3 * sizeof(FLOAT);
|
||||
break;
|
||||
|
||||
/*TODO
|
||||
case X_D3DVSDT_NONE: // 0x02:
|
||||
printf("D3DVSDT_NONE / xbox ext. nsp /");
|
||||
dwNewDataType = 0xFF;
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
}
|
||||
/*TODO
|
||||
case X_D3DVSDT_NONE: { // 0x02:
|
||||
printf("D3DVSDT_NONE / xbox ext. nsp /");
|
||||
dwNewDataType = 0xFF;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
default: {
|
||||
// Generic 'conversion' - just make a copy :
|
||||
memcpy(pNewDataPos,
|
||||
&pOrigData[uiVertex * uiStride + dwPosOrig],
|
||||
pStreamPatch->pSizes[uiType]);
|
||||
dwPosOrig += pStreamPatch->pSizes[uiType];
|
||||
memcpy(pNewDataPos, pOrigVertex, pStreamPatch->pSizes[uiType]);
|
||||
pOrigVertex += pStreamPatch->pSizes[uiType];
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
|
||||
// Increment the new pointer :
|
||||
pNewDataPos += pStreamPatch->pSizes[uiType];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!pPatchDesc->pVertexStreamZeroData)
|
||||
{
|
||||
//if(pNewVertexBuffer != nullptr) // Dxbx addition
|
||||
|
@ -651,6 +649,7 @@ bool XTL::VertexPatcher::PatchStream(VertexPatchDesc *pPatchDesc,
|
|||
m_pNewVertexStreamZeroData = pNewData;
|
||||
}
|
||||
}
|
||||
|
||||
pStream->uiOrigStride = uiStride;
|
||||
pStream->uiNewStride = pStreamPatch->ConvertedStride;
|
||||
m_bPatched = true;
|
||||
|
|
|
@ -1551,22 +1551,22 @@ DWORD Xb2PCRegisterType(DWORD VertexRegister)
|
|||
|
||||
static inline DWORD VshGetTokenType(DWORD Token)
|
||||
{
|
||||
return (Token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT;
|
||||
return (Token & X_D3DVSD_TOKENTYPEMASK) >> X_D3DVSD_TOKENTYPESHIFT;
|
||||
}
|
||||
|
||||
static inline DWORD VshGetVertexRegister(DWORD Token)
|
||||
{
|
||||
return (Token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT;
|
||||
return (Token & X_D3DVSD_VERTEXREGMASK) >> X_D3DVSD_VERTEXREGSHIFT;
|
||||
}
|
||||
|
||||
static inline DWORD VshGetVertexRegisterIn(DWORD Token)
|
||||
{
|
||||
return (Token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT;
|
||||
return (Token & X_D3DVSD_VERTEXREGINMASK) >> X_D3DVSD_VERTEXREGINSHIFT;
|
||||
}
|
||||
|
||||
static inline DWORD VshGetVertexStream(DWORD Token)
|
||||
{
|
||||
return (Token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT;
|
||||
return (Token & X_D3DVSD_STREAMNUMBERMASK) >> X_D3DVSD_STREAMNUMBERSHIFT;
|
||||
}
|
||||
|
||||
static void VshConvertToken_NOP(DWORD *pToken)
|
||||
|
@ -1584,8 +1584,8 @@ static DWORD VshConvertToken_CONSTMEM(DWORD *pToken)
|
|||
// D3DVSD_CONST
|
||||
DbgVshPrintf("\tD3DVSD_CONST(");
|
||||
|
||||
DWORD ConstantAddress = ((*pToken >> D3DVSD_CONSTADDRESSSHIFT) & 0xFF);
|
||||
DWORD Count = (*pToken & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT;
|
||||
DWORD ConstantAddress = (*pToken & X_D3DVSD_CONSTADDRESSMASK) >> X_D3DVSD_CONSTADDRESSSHIFT;
|
||||
DWORD Count = (*pToken & X_D3DVSD_CONSTCOUNTMASK) >> X_D3DVSD_CONSTCOUNTSHIFT;
|
||||
|
||||
DbgVshPrintf("%d, %d),\n", ConstantAddress, Count);
|
||||
|
||||
|
@ -1717,7 +1717,7 @@ static void VshConvertToken_STREAMDATA_SKIP(DWORD *pToken)
|
|||
{
|
||||
using namespace XTL;
|
||||
|
||||
XTL::DWORD SkipCount = (*pToken & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT;
|
||||
XTL::DWORD SkipCount = (*pToken & X_D3DVSD_SKIPCOUNTMASK) >> X_D3DVSD_SKIPCOUNTSHIFT;
|
||||
DbgVshPrintf("\tD3DVSD_SKIP(%d),\n", SkipCount);
|
||||
}
|
||||
|
||||
|
@ -1725,7 +1725,7 @@ static void VshConvertToken_STREAMDATA_SKIPBYTES(DWORD *pToken)
|
|||
{
|
||||
using namespace XTL;
|
||||
|
||||
XTL::DWORD SkipBytesCount = (*pToken & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT;
|
||||
XTL::DWORD SkipBytesCount = (*pToken & X_D3DVSD_SKIPCOUNTMASK) >> X_D3DVSD_SKIPCOUNTSHIFT;
|
||||
DbgVshPrintf("\tD3DVSD_SKIPBYTES(%d), /* xbox ext. */\n", SkipBytesCount);
|
||||
if(SkipBytesCount % sizeof(XTL::DWORD))
|
||||
{
|
||||
|
@ -1757,7 +1757,7 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
|
|||
|
||||
DbgVshPrintf(", ");
|
||||
|
||||
XTL::DWORD DataType = (*pToken >> D3DVSD_DATATYPESHIFT) & 0xFF;
|
||||
XTL::DWORD DataType = (*pToken & X_D3DVSD_DATATYPEMASK) >> X_D3DVSD_DATATYPESHIFT;
|
||||
XTL::DWORD NewDataType = 0;
|
||||
XTL::DWORD NewSize = 0;
|
||||
|
||||
|
@ -1800,31 +1800,31 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
|
|||
break;
|
||||
case X_D3DVSDT_NORMSHORT1: // 0x11:
|
||||
DbgVshPrintf("D3DVSDT_NORMSHORT1 /* xbox ext. */");
|
||||
NewDataType = D3DVSDT_SHORT2; // hmm, emulation?
|
||||
NewSize = 2*sizeof(XTL::SHORT);
|
||||
NewDataType = D3DVSDT_FLOAT1;
|
||||
NewSize = sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT2: // 0x21:
|
||||
DbgVshPrintf("D3DVSDT_NORMSHORT2 /* xbox ext. */");
|
||||
NewDataType = D3DVSDT_SHORT2;
|
||||
NewSize = 2*sizeof(XTL::SHORT);
|
||||
NewDataType = D3DVSDT_FLOAT2;
|
||||
NewSize = 2*sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT3: // 0x31:
|
||||
DbgVshPrintf("D3DVSDT_NORMSHORT3 /* xbox ext. nsp */");
|
||||
NewDataType = D3DVSDT_SHORT4;
|
||||
NewSize = 4*sizeof(XTL::SHORT);
|
||||
NewDataType = D3DVSDT_FLOAT3;
|
||||
NewSize = 3*sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_NORMSHORT4: // 0x41:
|
||||
DbgVshPrintf("D3DVSDT_NORMSHORT4 /* xbox ext. */");
|
||||
NewDataType = D3DVSDT_SHORT4;
|
||||
NewSize = 4*sizeof(XTL::SHORT);
|
||||
NewDataType = D3DVSDT_FLOAT4;
|
||||
NewSize = 4*sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_NORMPACKED3: // 0x16:
|
||||
DbgVshPrintf("D3DVSDT_NORMPACKED3 /* xbox ext. nsp */");
|
||||
NewDataType = D3DVSDT_FLOAT3;//0xFF; //32bit
|
||||
NewDataType = D3DVSDT_FLOAT3;
|
||||
NewSize = 3*sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
|
@ -1837,7 +1837,7 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
|
|||
case X_D3DVSDT_SHORT3: // 0x35:
|
||||
DbgVshPrintf("D3DVSDT_SHORT3 /* xbox ext. nsp */");
|
||||
NewDataType = D3DVSDT_SHORT4;
|
||||
NewSize = 4 * sizeof(XTL::SHORT);
|
||||
NewSize = 4*sizeof(XTL::SHORT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE1: // 0x14:
|
||||
|
@ -1858,11 +1858,12 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
|
|||
NewSize = 3*sizeof(FLOAT);
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_PBYTE4: // 0x44:
|
||||
case X_D3DVSDT_PBYTE4: // 0x44: // Hit by Panzer
|
||||
DbgVshPrintf("D3DVSDT_PBYTE4 /* xbox ext. */");
|
||||
NewDataType = D3DVSDT_FLOAT4;
|
||||
NewSize = 4*sizeof(FLOAT);
|
||||
break;
|
||||
pPatchData->NeedPatching = TRUE;
|
||||
break;
|
||||
case X_D3DVSDT_FLOAT2H: // 0x72:
|
||||
DbgVshPrintf("D3DVSDT_FLOAT2H /* xbox ext. */");
|
||||
NewDataType = D3DVSDT_FLOAT3;
|
||||
|
|
|
@ -722,4 +722,40 @@ const int X_D3DVSDT_NONE = 0x02; // xbox ext. nsp
|
|||
|
||||
const int MAX_NBR_STREAMS = 16;
|
||||
|
||||
#define X_D3DVSD_TOKENTYPESHIFT 29
|
||||
#define X_D3DVSD_TOKENTYPEMASK (7 << X_D3DVSD_TOKENTYPESHIFT)
|
||||
|
||||
#define X_D3DVSD_STREAMNUMBERSHIFT 0
|
||||
#define X_D3DVSD_STREAMNUMBERMASK (0xF << X_D3DVSD_STREAMNUMBERSHIFT)
|
||||
|
||||
#define X_D3DVSD_DATALOADTYPESHIFT 28
|
||||
#define X_D3DVSD_DATALOADTYPEMASK (0x1 << X_D3DVSD_DATALOADTYPESHIFT)
|
||||
|
||||
#define X_D3DVSD_DATATYPESHIFT 16
|
||||
#define X_D3DVSD_DATATYPEMASK (0xFF << X_D3DVSD_DATATYPESHIFT)
|
||||
|
||||
#define X_D3DVSD_SKIPCOUNTSHIFT 16
|
||||
#define X_D3DVSD_SKIPCOUNTMASK (0xF << X_D3DVSD_SKIPCOUNTSHIFT)
|
||||
|
||||
#define X_D3DVSD_VERTEXREGSHIFT 0
|
||||
#define X_D3DVSD_VERTEXREGMASK (0x1F << X_D3DVSD_VERTEXREGSHIFT)
|
||||
|
||||
#define X_D3DVSD_VERTEXREGINSHIFT 20
|
||||
#define X_D3DVSD_VERTEXREGINMASK (0xF << X_D3DVSD_VERTEXREGINSHIFT)
|
||||
|
||||
#define X_D3DVSD_CONSTCOUNTSHIFT 25
|
||||
#define X_D3DVSD_CONSTCOUNTMASK (0xF << X_D3DVSD_CONSTCOUNTSHIFT)
|
||||
|
||||
#define X_D3DVSD_CONSTADDRESSSHIFT 0
|
||||
#define X_D3DVSD_CONSTADDRESSMASK (0xFF << X_D3DVSD_CONSTADDRESSSHIFT)
|
||||
|
||||
#define X_D3DVSD_CONSTRSSHIFT 16
|
||||
#define X_D3DVSD_CONSTRSMASK (0x1FFF << X_D3DVSD_CONSTRSSHIFT)
|
||||
|
||||
#define X_D3DVSD_EXTCOUNTSHIFT 24
|
||||
#define X_D3DVSD_EXTCOUNTMASK (0x1F << X_D3DVSD_EXTCOUNTSHIFT)
|
||||
|
||||
#define X_D3DVSD_EXTINFOSHIFT 0
|
||||
#define X_D3DVSD_EXTINFOMASK (0xFFFFFF << X_D3DVSD_EXTINFOSHIFT)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace xboxkrnl
|
|||
#include <xboxkrnl/xboxkrnl.h>
|
||||
};
|
||||
|
||||
#include "EmuKrnl.h" // For InitializeListHead(), etc.
|
||||
#include "EmuFS.h"
|
||||
#include "EmuAlloc.h" // For CxbxCalloc()
|
||||
#include "CxbxKrnl.h"
|
||||
|
@ -51,193 +52,228 @@ namespace xboxkrnl
|
|||
#include <windows.h>
|
||||
#include <cstdio>
|
||||
|
||||
__declspec(naked) void EmuCmpEsiFs00()
|
||||
NT_TIB *GetNtTib()
|
||||
{
|
||||
NT_TIB *NtTib;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [TIB_LinearSelfAddress]
|
||||
mov NtTib, eax
|
||||
}
|
||||
|
||||
return NtTib;
|
||||
}
|
||||
|
||||
void EmuKeSetPcr(xboxkrnl::KPCR *Pcr)
|
||||
{
|
||||
// Store the Xbox KPCR pointer in FS (See KeGetPcr())
|
||||
//
|
||||
// Note : Cxbx currently doesn't do preemptive thread switching,
|
||||
// which implies that thread-state management is done by Windows.
|
||||
//
|
||||
// Xbox executable code expects thread-specific state data to
|
||||
// be available via the FS segment register. To emulate this,
|
||||
// Cxbx uses the user data-slot feature of Windows threads.
|
||||
//
|
||||
// Cxbx puts a pointer to a thread-specific copy of an entire
|
||||
// Kernel Processor Control Region (KPCR) into this data-slot.
|
||||
//
|
||||
// In the Xbox there's only be KPCR (as it's a per-processor-
|
||||
// structure, and the Xbox has only one processor).
|
||||
//
|
||||
// Since Cxbx doesn't control thread-swiches (yet), each thread
|
||||
// must have a thread-specific copy of the KPCR, to contain all
|
||||
// thread-specific data that can be reached via this structure
|
||||
// (like the NT_TIB structure and ETHREAD CurrentThread pointer).
|
||||
//
|
||||
// For this to work, Cxbx patches all executable code accessing
|
||||
// the FS segment register, so that the KPCR is accessed via
|
||||
// the user data-slot of each Windows thread Cxbx uses for an
|
||||
// Xbox thread.
|
||||
//
|
||||
__asm {
|
||||
mov eax, Pcr
|
||||
mov fs : [TIB_ArbitraryDataSlot], eax
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuFS_CmpEsiFs00()
|
||||
{
|
||||
// Note : eax must be preserved here, hence the push/pop
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
cmp esi, [eax]
|
||||
pop eax
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEaxFs00()
|
||||
__declspec(naked) void EmuFS_MovEaxFs00()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov eax, [eax]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEaxFs20()
|
||||
__declspec(naked) void EmuFS_MovEaxFs20()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov eax, [eax + 20h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEaxFs28()
|
||||
__declspec(naked) void EmuFS_MovEaxFs28()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov eax, [eax + 28h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEaxFs58()
|
||||
__declspec(naked) void EmuFS_MovEaxFs58()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov eax, [eax + 58h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEbxFs00()
|
||||
__declspec(naked) void EmuFS_MovEbxFs00()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ebx, fs : [0x14]
|
||||
mov ebx, fs : [TIB_ArbitraryDataSlot]
|
||||
mov ebx, [ebx]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEcxFs00()
|
||||
__declspec(naked) void EmuFS_MovEcxFs00()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ecx, fs : [0x14]
|
||||
mov ecx, fs : [TIB_ArbitraryDataSlot]
|
||||
mov ecx, [ecx]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEcxFs04()
|
||||
__declspec(naked) void EmuFS_MovEcxFs04()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ecx, fs : [0x14]
|
||||
mov ecx, fs : [TIB_ArbitraryDataSlot]
|
||||
mov ecx, [ecx + 04h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEdiFs00()
|
||||
__declspec(naked) void EmuFS_MovEdiFs00()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov edi, fs : [0x14]
|
||||
mov edi, fs : [TIB_ArbitraryDataSlot]
|
||||
mov edi, [edi]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEdiFs04()
|
||||
__declspec(naked) void EmuFS_MovEdiFs04()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov edi, fs : [0x14]
|
||||
mov edi, fs : [TIB_ArbitraryDataSlot]
|
||||
mov edi, [edi + 04h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMEsiFs00()
|
||||
__declspec(naked) void EmuFS_MovEsiFs00()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov esi, fs : [0x14]
|
||||
mov esi, fs : [TIB_ArbitraryDataSlot]
|
||||
mov esi, [esi]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMzxEaxBytePtrFs24()
|
||||
__declspec(naked) void EmuFS_MovzxEaxBytePtrFs24()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, fs : [0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
movzx eax, byte ptr[eax + 24h]
|
||||
ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMFs00Eax()
|
||||
__declspec(naked) void EmuFS_MovFs00Eax()
|
||||
{
|
||||
// Note : ebx must be preserved here, hence the push/pop
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
mov ebx, fs : [0x14]
|
||||
mov[ebx], eax
|
||||
pop ebx
|
||||
ret
|
||||
mov ebx, fs : [TIB_ArbitraryDataSlot]
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMFs00Ebx()
|
||||
__declspec(naked) void EmuFS_MovFs00Ebx()
|
||||
{
|
||||
// Note : eax must be preserved here, hence the push/pop
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
mov eax, fs : [0x14]
|
||||
mov[eax], ebx
|
||||
pop eax
|
||||
ret
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov [eax], ebx
|
||||
pop eax
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMFs00Ecx()
|
||||
__declspec(naked) void EmuFS_MovFs00Ecx()
|
||||
{
|
||||
// Note : eax must be preserved here, hence the push/pop
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
mov eax, fs : [0x14]
|
||||
mov[eax], ecx
|
||||
pop eax
|
||||
ret
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov [eax], ecx
|
||||
pop eax
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuMFs00Esp()
|
||||
__declspec(naked) void EmuFS_MovFs00Esp()
|
||||
{
|
||||
// Note : eax must be preserved here, hence the push/pop
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
mov eax, fs : [0x14]
|
||||
mov[eax], esp
|
||||
pop eax
|
||||
ret
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov [eax], esp
|
||||
pop eax
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuPushDwordPtrFs00()
|
||||
{
|
||||
uint32 returnAddr;
|
||||
uint32 temp;
|
||||
__asm
|
||||
{
|
||||
pop returnAddr
|
||||
mov temp, eax
|
||||
mov eax, fs : [0x14]
|
||||
push[eax]
|
||||
mov eax, temp
|
||||
push returnAddr
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuPopDwordPtrFs00()
|
||||
__declspec(naked) void EmuFS_PushDwordPtrFs00()
|
||||
{
|
||||
uint32 returnAddr;
|
||||
uint32 temp;
|
||||
|
@ -246,11 +282,28 @@ __declspec(naked) void EmuPopDwordPtrFs00()
|
|||
{
|
||||
pop returnAddr
|
||||
mov temp, eax
|
||||
mov eax, fs : [0x14]
|
||||
pop[eax]
|
||||
mov eax, temp
|
||||
push returnAddr
|
||||
ret
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
push [eax]
|
||||
mov eax, temp
|
||||
push returnAddr
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuFS_PopDwordPtrFs00()
|
||||
{
|
||||
uint32 returnAddr;
|
||||
uint32 temp;
|
||||
|
||||
__asm
|
||||
{
|
||||
pop returnAddr
|
||||
mov temp, eax
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
pop [eax]
|
||||
mov eax, temp
|
||||
push returnAddr
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,24 +315,24 @@ void EmuInitFS()
|
|||
* The entries must be in order of size, to keep the chance of false positives to a minimum.
|
||||
*/
|
||||
std::vector<fs_instruction_t> fsInstructions;
|
||||
fsInstructions.push_back({ { 0x64, 0x0F, 0xB6, 0x05, 0x24, 0x00, 0x00, 0x00 }, &EmuMzxEaxBytePtrFs24 });// movzx eax, large byte ptr fs:24
|
||||
fsInstructions.push_back({ { 0x64, 0x3B, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuCmpEsiFs00 }); // cmp esi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x1D, 0x00, 0x00, 0x00, 0x00 }, &EmuMEbxFs00 }); // mov ebx, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00 }, &EmuMEcxFs00 }); // mov ecx, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x0D, 0x04, 0x00, 0x00, 0x00 }, &EmuMEcxFs04 }); // mov ecx, large fs:4
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x3D, 0x00, 0x00, 0x00, 0x00 }, &EmuMEdiFs00 }); // mov edi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x3D, 0x04, 0x00, 0x00, 0x00 }, &EmuMEdiFs04 }); // mov edi, large fs:4
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuMEsiFs00 }); // mov esi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x1D, 0x00, 0x00, 0x00, 0x00 }, &EmuMFs00Ebx }); // mov large fs:0, ebx
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00 }, &EmuMFs00Ecx }); // mov large fs:0, ecx
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x25, 0x00, 0x00, 0x00, 0x00 }, &EmuMFs00Esp }); // mov large fs:0, esp
|
||||
fsInstructions.push_back({ { 0x64, 0x8F, 0x05, 0x00, 0x00, 0x00, 0x00 }, &EmuPopDwordPtrFs00 }); // pop large dword ptr fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xFF, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuPushDwordPtrFs00 }); // push large dword ptr fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00 }, &EmuMEaxFs00 }); // mov eax, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x20, 0x00, 0x00, 0x00 }, &EmuMEaxFs20 }); // mov eax, large fs:20
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x28, 0x00, 0x00, 0x00 }, &EmuMEaxFs28 }); // mov eax, large fs:28
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x58, 0x00, 0x00, 0x00 }, &EmuMEaxFs58 }); // mov eax, large fs:58
|
||||
fsInstructions.push_back({ { 0x64, 0xA3, 0x00, 0x00, 0x00, 0x00 }, &EmuMFs00Eax }); // mov large fs:0, eax
|
||||
fsInstructions.push_back({ { 0x64, 0x0F, 0xB6, 0x05, 0x24, 0x00, 0x00, 0x00 }, &EmuFS_MovzxEaxBytePtrFs24 });// movzx eax, large byte ptr fs:24
|
||||
fsInstructions.push_back({ { 0x64, 0x3B, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_CmpEsiFs00 }); // cmp esi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x1D, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovEbxFs00 }); // mov ebx, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovEcxFs00 }); // mov ecx, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x0D, 0x04, 0x00, 0x00, 0x00 }, &EmuFS_MovEcxFs04 }); // mov ecx, large fs:4
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x3D, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovEdiFs00 }); // mov edi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x3D, 0x04, 0x00, 0x00, 0x00 }, &EmuFS_MovEdiFs04 }); // mov edi, large fs:4
|
||||
fsInstructions.push_back({ { 0x64, 0x8B, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovEsiFs00 }); // mov esi, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x1D, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovFs00Ebx }); // mov large fs:0, ebx
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovFs00Ecx }); // mov large fs:0, ecx
|
||||
fsInstructions.push_back({ { 0x64, 0x89, 0x25, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovFs00Esp }); // mov large fs:0, esp
|
||||
fsInstructions.push_back({ { 0x64, 0x8F, 0x05, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_PopDwordPtrFs00 }); // pop large dword ptr fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xFF, 0x35, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_PushDwordPtrFs00 }); // push large dword ptr fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovEaxFs00 }); // mov eax, large fs:0
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x20, 0x00, 0x00, 0x00 }, &EmuFS_MovEaxFs20 }); // mov eax, large fs:20
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x28, 0x00, 0x00, 0x00 }, &EmuFS_MovEaxFs28 }); // mov eax, large fs:28
|
||||
fsInstructions.push_back({ { 0x64, 0xA1, 0x58, 0x00, 0x00, 0x00 }, &EmuFS_MovEaxFs58 }); // mov eax, large fs:58
|
||||
fsInstructions.push_back({ { 0x64, 0xA3, 0x00, 0x00, 0x00, 0x00 }, &EmuFS_MovFs00Eax }); // mov large fs:0, eax
|
||||
|
||||
DbgPrintf("Patching FS Register Accesses\n");
|
||||
DWORD sizeOfImage = CxbxKrnl_XbeHeader->dwSizeofImage;
|
||||
|
@ -335,103 +388,105 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
return;
|
||||
}
|
||||
|
||||
NT_TIB *OrgNtTib;
|
||||
xboxkrnl::KPCR *NewPcr;
|
||||
|
||||
uint08 *pNewTLS = NULL;
|
||||
|
||||
uint16 NewFS = -1, OrgFS = -1;
|
||||
void *pNewTLS = nullptr;
|
||||
|
||||
// copy global TLS to the current thread
|
||||
{
|
||||
uint32 dwCopySize = pTLS->dwDataEndAddr - pTLS->dwDataStartAddr;
|
||||
uint32 dwZeroSize = pTLS->dwSizeofZeroFill;
|
||||
|
||||
pNewTLS = (uint08*)CxbxCalloc(1, dwCopySize + dwZeroSize + 0x100 /* + HACK: extra safety padding 0x100*/);
|
||||
pNewTLS = CxbxCalloc(1, dwCopySize + dwZeroSize + 0x100 /* + HACK: extra safety padding 0x100*/);
|
||||
|
||||
memcpy(pNewTLS, pTLSData, dwCopySize);
|
||||
}
|
||||
|
||||
// dump raw TLS data
|
||||
{
|
||||
#ifdef _DEBUG_TRACE
|
||||
if (pNewTLS == 0)
|
||||
{
|
||||
// dump raw TLS data
|
||||
if (pNewTLS == nullptr)
|
||||
DbgPrintf("EmuFS: TLS Non-Existant (OK)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrintf("EmuFS: TLS Data Dump...\n");
|
||||
DbgPrintf("EmuFS: 0x%.08X: ", pNewTLS);
|
||||
|
||||
uint32 stop = pTLS->dwDataEndAddr - pTLS->dwDataStartAddr + pTLS->dwSizeofZeroFill;
|
||||
|
||||
// Note : Use printf instead of DbgPrintf here, which prefixes with GetCurrentThreadId() :
|
||||
for (uint32 v = 0;v<stop;v++)
|
||||
if (g_bPrintfOn)
|
||||
{
|
||||
uint08 *bByte = (uint08*)pNewTLS + v;
|
||||
for (uint32 v = 0; v < dwCopySize; v++) // Note : Don't dump dwZeroSize
|
||||
{
|
||||
uint08 *bByte = (uint08*)pNewTLS + v;
|
||||
|
||||
if (g_bPrintfOn) printf("%.01X", (uint32)*bByte);
|
||||
if (v % 0x10 == 0)
|
||||
DbgPrintf("EmuFS: 0x%.08X: ", (xbaddr)bByte);
|
||||
|
||||
if ((v + 1) % 0x10 == 0 && v + 1<stop)
|
||||
if (g_bPrintfOn) printf("\nEmuFS (0x%X): 0x%.08X: ", GetCurrentThreadId(), ((uint32)pNewTLS + v));
|
||||
// Note : Use printf instead of DbgPrintf here, which prefixes with GetCurrentThreadId() :
|
||||
printf("%.01X", (uint32)(*bByte));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (g_bPrintfOn) printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__asm
|
||||
{
|
||||
// Obtain "OrgFS"
|
||||
mov ax, fs
|
||||
mov OrgFS, ax
|
||||
|
||||
// Obtain "OrgNtTib"
|
||||
mov eax, fs:[0x18]
|
||||
mov OrgNtTib, eax
|
||||
}
|
||||
|
||||
// allocate KPCR structure
|
||||
{
|
||||
uint32 dwSize = sizeof(xboxkrnl::KPCR);
|
||||
|
||||
NewPcr = (xboxkrnl::KPCR*)CxbxCalloc(1, dwSize);
|
||||
}
|
||||
|
||||
// generate TIB
|
||||
xboxkrnl::ETHREAD *EThread = (xboxkrnl::ETHREAD*)CxbxCalloc(1, sizeof(xboxkrnl::ETHREAD)); // Clear, to prevent side-effects on random contents
|
||||
|
||||
EThread->Tcb.TlsData = (void*)pNewTLS;
|
||||
EThread->UniqueThread = GetCurrentThreadId();
|
||||
|
||||
memcpy(&NewPcr->NtTib, OrgNtTib, sizeof(NT_TIB));
|
||||
|
||||
NewPcr->NtTib.Self = &NewPcr->NtTib;
|
||||
|
||||
NewPcr->PrcbData.CurrentThread = (xboxkrnl::KTHREAD*)EThread;
|
||||
|
||||
NewPcr->Prcb = &NewPcr->PrcbData;
|
||||
|
||||
// Set the stack base
|
||||
NewPcr->NtTib.StackBase = pNewTLS;
|
||||
|
||||
// prepare TLS
|
||||
{
|
||||
// TLS Index Address := 0
|
||||
*(uint32*)pTLS->dwTLSIndexAddr = 0;
|
||||
*(xbaddr*)pTLS->dwTLSIndexAddr = (xbaddr)nullptr;
|
||||
|
||||
// dword @ pTLSData := pTLSData
|
||||
if (pNewTLS != 0)
|
||||
if (pNewTLS != nullptr)
|
||||
*(void**)pNewTLS = pNewTLS;
|
||||
}
|
||||
|
||||
// Store the new KPCR pointer in FS
|
||||
__asm {
|
||||
mov eax, NewPcr
|
||||
mov fs : [0x14], eax
|
||||
// Allocate the xbox KPCR structure
|
||||
xboxkrnl::KPCR *NewPcr = (xboxkrnl::KPCR*)CxbxCalloc(1, sizeof(xboxkrnl::KPCR));
|
||||
xboxkrnl::NT_TIB *XbTib = &(NewPcr->NtTib);
|
||||
xboxkrnl::PKPRCB Prcb = &(NewPcr->PrcbData);
|
||||
// Note : As explained above (at EmuKeSetPcr), Cxbx cannot allocate one NT_TIB and KPRCB
|
||||
// structure per thread, since Cxbx currently doesn't do thread-switching.
|
||||
// Thus, the only way to give each thread it's own PrcbData.CurrentThread, is to put the
|
||||
// KPCR pointer in the TIB_ArbitraryDataSlot, which is read by the above EmuFS_* patches.
|
||||
//
|
||||
// Once we simulate thread switching ourselves, we can update PrcbData.CurrentThread
|
||||
// and simplify this initialization, by using only one KPCR for the single Xbox processor.
|
||||
//
|
||||
// One way to do our own (preemprive) thread-switching would be to use this technique :
|
||||
// http://www.eran.io/implementing-a-preemptive-kernel-within-a-single-windows-thread/
|
||||
// See https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/issues/146 for more info.
|
||||
|
||||
// Copy the Nt TIB over to the emulated TIB :
|
||||
{
|
||||
memcpy(XbTib, GetNtTib(), sizeof(NT_TIB));
|
||||
// Fixup the TIB self pointer :
|
||||
NewPcr->NtTib.Self = XbTib;
|
||||
// Set the stack base - TODO : Verify this, doesn't look right?
|
||||
NewPcr->NtTib.StackBase = pNewTLS;
|
||||
}
|
||||
|
||||
DbgPrintf("EmuFS: OrgFS=%d NewFS=%d pTLS=0x%.08X\n", OrgFS, NewFS, pTLS);
|
||||
// Set flat address of this PCR
|
||||
NewPcr->SelfPcr = NewPcr;
|
||||
// Set pointer to Prcb
|
||||
NewPcr->Prcb = Prcb;
|
||||
|
||||
// Initialize the prcb :
|
||||
{
|
||||
// TODO : Once we do our own thread-switching (as mentioned above),
|
||||
// we can also start using Prcb->DpcListHead instead of DpcQueue :
|
||||
InitializeListHead(&(Prcb->DpcListHead));
|
||||
Prcb->DpcRoutineActive = 0;
|
||||
|
||||
// TODO : Should Irql be set? And if so, to what - PASSIVE_LEVEL, or perhaps better : APC_LEVEL?
|
||||
// NewPcr->Irql = PASSIVE_LEVEL; // See KeLowerIrql;
|
||||
}
|
||||
|
||||
// Initialize a fake PrcbData.CurrentThread
|
||||
{
|
||||
xboxkrnl::ETHREAD *EThread = (xboxkrnl::ETHREAD*)CxbxCalloc(1, sizeof(xboxkrnl::ETHREAD)); // Clear, to prevent side-effects on random contents
|
||||
|
||||
EThread->Tcb.TlsData = pNewTLS;
|
||||
EThread->UniqueThread = GetCurrentThreadId();
|
||||
// Set PrcbData.CurrentThread
|
||||
Prcb->CurrentThread = (xboxkrnl::KTHREAD*)EThread;
|
||||
}
|
||||
|
||||
// Make the KPCR struct available to KeGetPcr()
|
||||
EmuKeSetPcr(NewPcr);
|
||||
|
||||
DbgPrintf("EmuFS: Installed KPCR in TIB_ArbitraryDataSlot (with pTLS = 0x%.08X)\n", pTLS);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,72 @@ namespace NtDll
|
|||
#include "EmuNtDll.h"
|
||||
};
|
||||
|
||||
// See also :
|
||||
// https://github.com/reactos/reactos/blob/40a16a9cf1cdfca399e9154b42d32c30b63480f5/reactos/drivers/filesystems/udfs/Include/env_spec_w32.h
|
||||
void InitializeListHead(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
pListHead->Flink = pListHead->Blink = pListHead;
|
||||
}
|
||||
|
||||
bool IsListEmpty(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
return (pListHead->Flink == pListHead);
|
||||
}
|
||||
|
||||
void InsertHeadList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_ListHead = pListHead;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Flink = _EX_ListHead->Flink;
|
||||
|
||||
pEntry->Flink = _EX_Flink;
|
||||
pEntry->Blink = _EX_ListHead;
|
||||
_EX_Flink->Blink = pEntry;
|
||||
_EX_ListHead->Flink = pEntry;
|
||||
}
|
||||
|
||||
void InsertTailList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_ListHead = pListHead;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Blink = _EX_ListHead->Blink;
|
||||
|
||||
pEntry->Flink = _EX_ListHead;
|
||||
pEntry->Blink = _EX_Blink;
|
||||
_EX_Blink->Flink = pEntry;
|
||||
_EX_ListHead->Blink = pEntry;
|
||||
}
|
||||
|
||||
//#define RemoveEntryList(e) do { PLIST_ENTRY f = (e)->Flink, b = (e)->Blink; f->Blink = b; b->Flink = f; (e)->Flink = (e)->Blink = NULL; } while (0)
|
||||
|
||||
void RemoveEntryList(xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_Flink = pEntry->Flink;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Blink = pEntry->Blink;
|
||||
|
||||
if (_EX_Flink != nullptr) {
|
||||
_EX_Blink->Flink = _EX_Flink;
|
||||
}
|
||||
|
||||
if (_EX_Flink != nullptr) {
|
||||
_EX_Flink->Blink = _EX_Blink;
|
||||
}
|
||||
}
|
||||
|
||||
xboxkrnl::PLIST_ENTRY RemoveHeadList(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY Result = pListHead->Flink;
|
||||
|
||||
RemoveEntryList(pListHead->Flink);
|
||||
return Result;
|
||||
}
|
||||
|
||||
xboxkrnl::PLIST_ENTRY RemoveTailList(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY Result = pListHead->Blink;
|
||||
|
||||
RemoveEntryList(pListHead->Blink);
|
||||
return Result;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * Declaring this in a header causes errors with xboxkrnl
|
||||
// * namespace, so we must declare it within any file that uses it
|
||||
|
|
|
@ -34,4 +34,23 @@
|
|||
#ifndef EMUKRNL_H
|
||||
#define EMUKRNL_H
|
||||
|
||||
// CONTAINING_RECORD macro
|
||||
// Gets the value of structure member (field - num1),given the type(MYSTRUCT, in this code) and the List_Entry head(temp, in this code)
|
||||
// See http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi
|
||||
//#define CONTAINING_RECORD(ptr, type, field) \
|
||||
// (((type) *)((char *)(ptr) - offsetof((type), member)))
|
||||
|
||||
#define OBJECT_TO_OBJECT_HEADER(Object) \
|
||||
CONTAINING_RECORD(Object, OBJECT_HEADER, Body)
|
||||
|
||||
void InitializeListHead(xboxkrnl::PLIST_ENTRY pListHead);
|
||||
bool IsListEmpty(xboxkrnl::PLIST_ENTRY pListHead);
|
||||
void InsertHeadList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry);
|
||||
void InsertTailList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry);
|
||||
//#define RemoveEntryList(e) do { PLIST_ENTRY f = (e)->Flink, b = (e)->Blink; f->Blink = b; b->Flink = f; (e)->Flink = (e)->Blink = NULL; } while (0)
|
||||
|
||||
void RemoveEntryList(xboxkrnl::PLIST_ENTRY pEntry);
|
||||
xboxkrnl::PLIST_ENTRY RemoveHeadList(xboxkrnl::PLIST_ENTRY pListHead);
|
||||
xboxkrnl::PLIST_ENTRY RemoveTailList(xboxkrnl::PLIST_ENTRY pListHead);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -54,87 +54,25 @@ namespace NtDll
|
|||
|
||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
#include "EmuKrnl.h" // For InitializeListHead(), etc.
|
||||
#include "EmuFile.h" // For IsEmuHandle(), NtStatusToString()
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
// Copied over from Dxbx.
|
||||
// TODO : Move towards thread-simulation based Dpc emulation
|
||||
typedef struct _DpcData {
|
||||
CRITICAL_SECTION Lock;
|
||||
HANDLE DpcThread;
|
||||
HANDLE DpcEvent;
|
||||
xboxkrnl::LIST_ENTRY DpcQueue;
|
||||
xboxkrnl::LIST_ENTRY DpcQueue; // TODO : Use KeGetCurrentPrcb()->DpcListHead instead
|
||||
xboxkrnl::LIST_ENTRY TimerQueue;
|
||||
} DpcData;
|
||||
|
||||
DpcData g_DpcData = { 0 }; // TODO : InitializeCriticalSection(Lock)
|
||||
DpcData g_DpcData = { 0 }; // Note : g_DpcData is initialized in InitDpcAndTimerThread()
|
||||
|
||||
// See also :
|
||||
// https://github.com/reactos/reactos/blob/40a16a9cf1cdfca399e9154b42d32c30b63480f5/reactos/drivers/filesystems/udfs/Include/env_spec_w32.h
|
||||
void InitializeListHead(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
pListHead->Flink = pListHead->Blink = pListHead;
|
||||
}
|
||||
|
||||
bool IsListEmpty(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
return (pListHead->Flink == pListHead);
|
||||
}
|
||||
|
||||
void InsertHeadList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_ListHead = pListHead;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Flink = _EX_ListHead->Flink;
|
||||
|
||||
pEntry->Flink = _EX_Flink;
|
||||
pEntry->Blink = _EX_ListHead;
|
||||
_EX_Flink->Blink = pEntry;
|
||||
_EX_ListHead->Flink = pEntry;
|
||||
}
|
||||
|
||||
void InsertTailList(xboxkrnl::PLIST_ENTRY pListHead, xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_ListHead = pListHead;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Blink = _EX_ListHead->Blink;
|
||||
|
||||
pEntry->Flink = _EX_ListHead;
|
||||
pEntry->Blink = _EX_Blink;
|
||||
_EX_Blink->Flink = pEntry;
|
||||
_EX_ListHead->Blink = pEntry;
|
||||
}
|
||||
|
||||
//#define RemoveEntryList(e) do { PLIST_ENTRY f = (e)->Flink, b = (e)->Blink; f->Blink = b; b->Flink = f; (e)->Flink = (e)->Blink = NULL; } while (0)
|
||||
|
||||
void RemoveEntryList(xboxkrnl::PLIST_ENTRY pEntry)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY _EX_Flink = pEntry->Flink;
|
||||
xboxkrnl::PLIST_ENTRY _EX_Blink = pEntry->Blink;
|
||||
|
||||
if (_EX_Flink != nullptr) {
|
||||
_EX_Blink->Flink = _EX_Flink;
|
||||
}
|
||||
|
||||
if (_EX_Flink != nullptr) {
|
||||
_EX_Flink->Blink = _EX_Blink;
|
||||
}
|
||||
}
|
||||
|
||||
xboxkrnl::PLIST_ENTRY RemoveHeadList(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY Result = pListHead->Flink;
|
||||
|
||||
RemoveEntryList(pListHead->Flink);
|
||||
return Result;
|
||||
}
|
||||
|
||||
xboxkrnl::PLIST_ENTRY RemoveTailList(xboxkrnl::PLIST_ENTRY pListHead)
|
||||
{
|
||||
xboxkrnl::PLIST_ENTRY Result = pListHead->Blink;
|
||||
|
||||
RemoveEntryList(pListHead->Blink);
|
||||
return Result;
|
||||
}
|
||||
// TODO : Move all Ki* functions to EmuKrnlKi.h/cpp :
|
||||
|
||||
#define KiRemoveTreeTimer(Timer) \
|
||||
(Timer)->Header.Inserted = FALSE; \
|
||||
|
@ -190,11 +128,10 @@ xboxkrnl::KPCR* KeGetPcr()
|
|||
{
|
||||
xboxkrnl::KPCR* Pcr;
|
||||
|
||||
// See EmuKeSetPcr()
|
||||
__asm {
|
||||
push eax
|
||||
mov eax, fs:[0x14]
|
||||
mov eax, fs : [TIB_ArbitraryDataSlot]
|
||||
mov Pcr, eax
|
||||
pop eax
|
||||
}
|
||||
|
||||
return Pcr;
|
||||
|
@ -208,6 +145,14 @@ xboxkrnl::KPRCB *KeGetCurrentPrcb()
|
|||
return &(KeGetPcr()->PrcbData);
|
||||
}
|
||||
|
||||
// Forward KeLowerIrql() to KfLowerIrql()
|
||||
#define KeLowerIrql(NewIrql) \
|
||||
KfLowerIrql(NewIrql)
|
||||
|
||||
// Forward KeRaiseIrql() to KfRaiseIrql()
|
||||
#define KeRaiseIrql(NewIrql, OldIrql) \
|
||||
*OldIrql = KfRaiseIrql(NewIrql)
|
||||
|
||||
DWORD BootTickCount = 0;
|
||||
|
||||
// The Xbox GetTickCount is measured in milliseconds, just like the native GetTickCount.
|
||||
|
@ -218,12 +163,6 @@ DWORD CxbxXboxGetTickCount()
|
|||
return GetTickCount() - BootTickCount;
|
||||
}
|
||||
|
||||
// CONTAINING_RECORD macro
|
||||
// Gets the value of structure member (field - num1),given the type(MYSTRUCT, in this code) and the List_Entry head(temp, in this code)
|
||||
// See http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi
|
||||
//#define CONTAINING_RECORD(ptr, type, field) \
|
||||
// (((type) *)((char *)(ptr) - offsetof((type), member)))
|
||||
|
||||
DWORD __stdcall EmuThreadDpcHandler(LPVOID lpVoid)
|
||||
{
|
||||
xboxkrnl::PKDPC pkdpc;
|
||||
|
@ -251,7 +190,7 @@ DWORD __stdcall EmuThreadDpcHandler(LPVOID lpVoid)
|
|||
// Extract the head entry and retrieve the containing KDPC pointer for it:
|
||||
pkdpc = CONTAINING_RECORD(RemoveHeadList(&(g_DpcData.DpcQueue)), xboxkrnl::KDPC, DpcListEntry);
|
||||
// Mark it as no longer linked into the DpcQueue
|
||||
pkdpc->DpcListEntry.Flink = NULL;
|
||||
pkdpc->Inserted = FALSE;
|
||||
// Set DpcRoutineActive to support KeIsExecutingDpc:
|
||||
KeGetCurrentPrcb()->DpcRoutineActive = TRUE; // Experimental
|
||||
// Call the Deferred Procedure :
|
||||
|
@ -578,9 +517,7 @@ XBSYSAPI EXPORTNUM(103) xboxkrnl::KIRQL NTAPI xboxkrnl::KeGetCurrentIrql(void)
|
|||
{
|
||||
LOG_FUNC();
|
||||
|
||||
KIRQL Irql;
|
||||
|
||||
Irql = KeGetPcr()->Irql;
|
||||
KIRQL Irql = KeGetPcr()->Irql;
|
||||
|
||||
RETURN(Irql);
|
||||
}
|
||||
|
@ -592,9 +529,11 @@ XBSYSAPI EXPORTNUM(104) xboxkrnl::PKTHREAD NTAPI xboxkrnl::KeGetCurrentThread(vo
|
|||
{
|
||||
LOG_FUNC();
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
|
||||
RETURN(NULL);
|
||||
// Probably correct, but untested and currently faked in EmuGenerateFS
|
||||
// (to make this correct, we need to improve our thread emulation)
|
||||
KTHREAD *ret = KeGetCurrentPrcb()->CurrentThread;
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -663,16 +602,22 @@ XBSYSAPI EXPORTNUM(109) xboxkrnl::VOID NTAPI xboxkrnl::KeInitializeInterrupt
|
|||
LOG_FUNC_ARG(Vector)
|
||||
LOG_FUNC_ARG(Irql)
|
||||
LOG_FUNC_ARG(InterruptMode)
|
||||
LOG_FUNC_ARG(ShareVector)
|
||||
LOG_FUNC_ARG(ShareVector)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// TODO : Untested :
|
||||
Interrupt->ServiceRoutine = (PVOID)ServiceRoutine;
|
||||
Interrupt->ServiceContext = ServiceContext;
|
||||
Interrupt->BusInterruptLevel = Vector - 0x30;
|
||||
Interrupt->BusInterruptLevel = Vector - 0x30; // TODO : Constantify 0x30
|
||||
Interrupt->Irql = Irql;
|
||||
Interrupt->Connected = FALSE;
|
||||
// Unused : Interrupt->ShareVector = ShareVector;
|
||||
Interrupt->Mode = InterruptMode;
|
||||
Interrupt->ShareVector = ShareVector;
|
||||
// Interrupt->rsvd1 = 0; // not neccesary?
|
||||
// Interrupt->ServiceCount = 0; // not neccesary?
|
||||
|
||||
// Interrupt->DispatchCode = ?; //TODO : Populate this interrupt dispatch
|
||||
// code block, patch it up so it works with the address of this Interrupt
|
||||
// struct and calls the right dispatch routine (depending on InterruptMode).
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -718,26 +663,30 @@ XBSYSAPI EXPORTNUM(119) xboxkrnl::BOOLEAN NTAPI xboxkrnl::KeInsertQueueDpc
|
|||
LOG_FUNC_ARG(SystemArgument2)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Before going thread-save, check if the Dpc is not linked yet?
|
||||
if (Dpc->DpcListEntry.Flink == NULL)
|
||||
{
|
||||
// For thread safety, enter the Dpc lock:
|
||||
EnterCriticalSection(&(g_DpcData.Lock));
|
||||
// Is the Dpc still not linked yet ?
|
||||
if (Dpc->DpcListEntry.Flink == NULL)
|
||||
{
|
||||
// Remember the arguments and link it into our DpcQueue :
|
||||
Dpc->SystemArgument1 = SystemArgument1;
|
||||
Dpc->SystemArgument2 = SystemArgument2;
|
||||
InsertTailList(&(g_DpcData.DpcQueue), &(Dpc->DpcListEntry));
|
||||
// Signal the Dpc handling code there's work to do
|
||||
SetEvent(g_DpcData.DpcEvent);
|
||||
}
|
||||
// Thread-safety is no longer required anymore
|
||||
LeaveCriticalSection(&(g_DpcData.Lock));
|
||||
// For thread safety, enter the Dpc lock:
|
||||
EnterCriticalSection(&(g_DpcData.Lock));
|
||||
// TODO : Instead, disable interrupts - use KeRaiseIrql(HIGH_LEVEL, &(KIRQL)OldIrql) ?
|
||||
|
||||
|
||||
BOOLEAN NeedsInsertion = (Dpc->Inserted == FALSE);
|
||||
|
||||
if (NeedsInsertion) {
|
||||
// Remember the arguments and link it into our DpcQueue :
|
||||
Dpc->Inserted = TRUE;
|
||||
Dpc->SystemArgument1 = SystemArgument1;
|
||||
Dpc->SystemArgument2 = SystemArgument2;
|
||||
InsertTailList(&(g_DpcData.DpcQueue), &(Dpc->DpcListEntry));
|
||||
// TODO : Instead of DpcQueue, add the DPC to KeGetCurrentPrcb()->DpcListHead
|
||||
// TODO : Once that's done, use an apropriate signalling mechanism instead of this :
|
||||
// Signal the Dpc handling code there's work to do
|
||||
SetEvent(g_DpcData.DpcEvent);
|
||||
}
|
||||
|
||||
RETURN(TRUE);
|
||||
// Thread-safety is no longer required anymore
|
||||
LeaveCriticalSection(&(g_DpcData.Lock));
|
||||
// TODO : Instead, enable interrupts - use KeLowerIrql(&OldIrql) ?
|
||||
|
||||
RETURN(NeedsInsertion);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -880,7 +829,9 @@ XBSYSAPI EXPORTNUM(129) xboxkrnl::UCHAR NTAPI xboxkrnl::KeRaiseIrqlToDpcLevel()
|
|||
CxbxKrnlCleanup("Bugcheck: Caller of KeRaiseIrqlToDpcLevel is higher than DISPATCH_LEVEL!");
|
||||
|
||||
KIRQL kRet = NULL;
|
||||
KeGetPcr()->Irql = DISPATCH_LEVEL;
|
||||
|
||||
KPCR* Pcr = KeGetPcr();
|
||||
Pcr->Irql = DISPATCH_LEVEL;
|
||||
|
||||
#ifdef _DEBUG_TRACE
|
||||
DbgPrintf("Raised IRQL to DISPATCH_LEVEL (2).\n");
|
||||
|
@ -893,6 +844,19 @@ XBSYSAPI EXPORTNUM(129) xboxkrnl::UCHAR NTAPI xboxkrnl::KeRaiseIrqlToDpcLevel()
|
|||
RETURN(kRet);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * 0x0082 - KeRaiseIrqlToSynchLevel()
|
||||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(130) xboxkrnl::UCHAR NTAPI xboxkrnl::KeRaiseIrqlToSynchLevel()
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
// See KfRaiseIrql / KeRaiseIrqlToDpcLevel - use APC_LEVEL?
|
||||
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * 0x0089 - KeRemoveQueueDpc()
|
||||
// ******************************************************************
|
||||
|
@ -903,19 +867,23 @@ XBSYSAPI EXPORTNUM(137) xboxkrnl::BOOLEAN NTAPI xboxkrnl::KeRemoveQueueDpc
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(Dpc);
|
||||
|
||||
if (Dpc->DpcListEntry.Flink != NULL)
|
||||
{
|
||||
EnterCriticalSection(&(g_DpcData.Lock));
|
||||
if (Dpc->DpcListEntry.Flink != NULL)
|
||||
{
|
||||
RemoveEntryList(&(Dpc->DpcListEntry));
|
||||
Dpc->DpcListEntry.Flink = NULL;
|
||||
}
|
||||
// TODO : Instead of using a lock, emulate the Clear Interrupt Flag (cli) instruction
|
||||
// See https://msdn.microsoft.com/is-is/library/y14401ab(v=vs.80).aspx
|
||||
EnterCriticalSection(&(g_DpcData.Lock));
|
||||
|
||||
LeaveCriticalSection(&(g_DpcData.Lock));
|
||||
BOOLEAN Inserted = Dpc->Inserted;
|
||||
|
||||
if (Inserted)
|
||||
{
|
||||
RemoveEntryList(&(Dpc->DpcListEntry));
|
||||
Dpc->Inserted = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
// TODO : Instead of using a lock, emulate the Set Interrupt Flag (sti) instruction
|
||||
// See https://msdn.microsoft.com/en-us/library/ad820yz3(v=vs.80).aspx
|
||||
LeaveCriticalSection(&(g_DpcData.Lock));
|
||||
|
||||
RETURN(Inserted);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -53,16 +53,14 @@ namespace NtDll
|
|||
};
|
||||
|
||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||
#include "EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
|
||||
#include "Emu.h" // For EmuWarning()
|
||||
#include "EmuKrnl.h" // For OBJECT_TO_OBJECT_HEADER()
|
||||
#include "EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
|
||||
|
||||
#pragma warning(disable:4005) // Ignore redefined status values
|
||||
#include <ntstatus.h>
|
||||
#pragma warning(default:4005)
|
||||
|
||||
#define OBJECT_TO_OBJECT_HEADER(Object) \
|
||||
CONTAINING_RECORD(Object, OBJECT_HEADER, Body)
|
||||
|
||||
#define OB_FLAG_NAMED_OBJECT 1
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -118,6 +116,18 @@ XBSYSAPI EXPORTNUM(239) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObCreateObject
|
|||
if (NameSize == 0)
|
||||
ObjectHeader->Flags = 0;
|
||||
else {
|
||||
// TODO : For other Ob* API's it must become possible to get from
|
||||
// and Object(Header) address to the Name. Right now, this requires
|
||||
// adding ObjectSize to ObjectHeader. This won't be available outside
|
||||
// this function, so we need a better solution for this.
|
||||
// It might be possible to put the OBJECT_STRING struct BEFORE the
|
||||
// ObjectHeader (and the NameBuffer itself before that), which would
|
||||
// make it possible to simply offset everything off an Object.
|
||||
// It might also be possible to insert a linked list struct, so
|
||||
// ObReferenceObjectByName can iterate over all named objects.
|
||||
// (It's probably wise to use one list per pool, to reduce the number
|
||||
// of objects to walk through.)
|
||||
|
||||
// Copy name after object (we've reserved NameSize bytes there) :
|
||||
OBJECT_STRING *Name = (OBJECT_STRING *)((char *)ObjectHeader + ObjectSize);
|
||||
char *NameBuffer = (char *)Name + sizeof(OBJECT_STRING);
|
||||
|
@ -253,9 +263,26 @@ XBSYSAPI EXPORTNUM(244) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObOpenObjectByPointer
|
|||
LOG_FUNC_ARG_OUT(Handle)
|
||||
LOG_FUNC_END;
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
HANDLE new_handle;
|
||||
NTSTATUS result = ObReferenceObjectByPointer(Object, ObjectType);
|
||||
|
||||
RETURN(S_OK);
|
||||
if (!NT_SUCCESS(result))
|
||||
new_handle = (HANDLE)0;
|
||||
else {
|
||||
LOG_UNIMPLEMENTED();
|
||||
|
||||
// TODO : Create a new_handle for this object
|
||||
// if that fails, do something like :
|
||||
// {
|
||||
// // Detected out of memory
|
||||
// ObDereferenceObject(Object);
|
||||
// result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
// }
|
||||
}
|
||||
|
||||
// Set the new handle and return the correct status
|
||||
*Handle = new_handle;
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -286,10 +313,12 @@ XBSYSAPI EXPORTNUM(246) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObReferenceObjectByHa
|
|||
LOG_FUNC_ARG_OUT(ReturnedObject)
|
||||
LOG_FUNC_END;
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
|
||||
// This is probably incorrect
|
||||
// This is most certainly incorrect
|
||||
*ReturnedObject = Handle;
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
// TODO : Implement and use a handle registration data structure
|
||||
|
||||
RETURN(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -314,6 +343,7 @@ XBSYSAPI EXPORTNUM(247) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ObReferenceObjectByNa
|
|||
LOG_FUNC_END;
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
// TODO : Implement a mechanism by which all named objects can be queried. See comments in ObCreateObject
|
||||
|
||||
RETURN(S_OK);
|
||||
}
|
||||
|
@ -373,7 +403,7 @@ XBSYSAPI EXPORTNUM(250) xboxkrnl::VOID FASTCALL xboxkrnl::ObfDereferenceObject
|
|||
if (ObjectHeader->Type->DeleteProcedure != NULL)
|
||||
ObjectHeader->Type->DeleteProcedure(Object);
|
||||
|
||||
// TODO : How to handle named objects?
|
||||
// TODO : How to handle named objects? See comments in ObCreateObject
|
||||
ObjectHeader->Type->FreeProcedure(ObjectHeader); // TODO : Is this ever something else than ExFreePool ?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ extern PVOID g_pfnThreadNotification[PSP_MAX_CREATE_THREAD_NOTIFY] = { NULL };
|
|||
extern int g_iThreadNotificationCount = 0;
|
||||
|
||||
// Separate function for logging, otherwise in PCSTProxy __try wont work (Compiler Error C2712)
|
||||
void PCSTProxy_log
|
||||
void LOG_PCSTProxy
|
||||
(
|
||||
PVOID StartRoutine,
|
||||
PVOID StartContext,
|
||||
|
@ -112,16 +112,25 @@ static unsigned int WINAPI PCSTProxy
|
|||
// Once deleted, unable to directly access iPCSTProxyParam in remainder of function.
|
||||
delete iPCSTProxyParam;
|
||||
|
||||
PCSTProxy_log(StartRoutine, StartContext, SystemRoutine, StartSuspended, hStartedEvent);
|
||||
LOG_PCSTProxy(
|
||||
StartRoutine,
|
||||
StartContext,
|
||||
SystemRoutine,
|
||||
StartSuspended,
|
||||
hStartedEvent);
|
||||
|
||||
// Do minimal thread initialization
|
||||
{
|
||||
EmuGenerateFS(CxbxKrnl_TLS, CxbxKrnl_TLSData);
|
||||
|
||||
_controlfp(_PC_53, _MCW_PC); // Set Precision control to 53 bits (verified setting)
|
||||
_controlfp(_RC_NEAR, _MCW_RC); // Set Rounding control to near (unsure about this)
|
||||
}
|
||||
|
||||
if (StartSuspended == TRUE)
|
||||
// Suspend right before calling the thread notification routines
|
||||
SuspendThread(GetCurrentThread());
|
||||
|
||||
EmuGenerateFS(CxbxKrnl_TLS, CxbxKrnl_TLSData);
|
||||
|
||||
_controlfp(_PC_53, _MCW_PC); // Set Precision control to 53 bits (verified setting)
|
||||
_controlfp(_RC_NEAR, _MCW_RC); // Set Rounding control to near (unsure about this)
|
||||
|
||||
// call thread notification routine(s)
|
||||
if (g_iThreadNotificationCount != 0)
|
||||
{
|
||||
|
|
|
@ -606,12 +606,6 @@ static inline void EmuInstallPatch(xbaddr FunctionAddr, void *Patch)
|
|||
*(uint32*)&FuncBytes[1] = (uint32)Patch - FunctionAddr - 5;
|
||||
}
|
||||
|
||||
static inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OUT uint08 &value)
|
||||
{
|
||||
offset = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset;
|
||||
value = ((LOOVPA<1>*)oovpa)->Lovp[index].Value;
|
||||
}
|
||||
|
||||
static inline void GetXRefEntry(OOVPA *oovpa, int index, OUT uint32 &xref, OUT uint08 &offset)
|
||||
{
|
||||
// Note : These are stored swapped by the XREF_ENTRY macro, hence this difference from GetOovpaEntry :
|
||||
|
@ -619,13 +613,75 @@ static inline void GetXRefEntry(OOVPA *oovpa, int index, OUT uint32 &xref, OUT u
|
|||
offset = ((LOOVPA<1>*)oovpa)->Lovp[index].Value;
|
||||
}
|
||||
|
||||
static inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OUT uint08 &value)
|
||||
{
|
||||
offset = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset;
|
||||
value = ((LOOVPA<1>*)oovpa)->Lovp[index].Value;
|
||||
}
|
||||
|
||||
static boolean CompareOOVPAToAddress(OOVPA *Oovpa, xbaddr cur)
|
||||
{
|
||||
uint32 v = 0; // verification counter
|
||||
|
||||
// Check all XRefs, stop if any does not match
|
||||
for (; v < Oovpa->XRefCount; v++)
|
||||
{
|
||||
uint32 XRef;
|
||||
uint08 Offset;
|
||||
|
||||
// get currently registered (un)known address
|
||||
GetXRefEntry(Oovpa, v, XRef, Offset);
|
||||
xbaddr XRefAddr = XRefDataBase[XRef];
|
||||
// Undetermined XRef cannot be checked yet
|
||||
// (EmuLocateFunction already checked this, but this check
|
||||
// is cheap enough to keep, and keep this function generic).
|
||||
if (XRefAddr == XREF_ADDR_UNDETERMINED)
|
||||
return false;
|
||||
|
||||
xbaddr ActualAddr = *(xbaddr*)(cur + Offset);
|
||||
// check if PC-relative or direct reference matches XRef
|
||||
if ((ActualAddr + cur + Offset + 4 != XRefAddr) && (ActualAddr != XRefAddr))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check all (Offset,Value)-pairs, stop if any does not match
|
||||
for (; v < Oovpa->Count; v++)
|
||||
{
|
||||
uint32 Offset;
|
||||
uint08 ExpectedValue;
|
||||
|
||||
// get offset + value pair
|
||||
GetOovpaEntry(Oovpa, v, Offset, ExpectedValue);
|
||||
uint08 ActualValue = *(uint08*)(cur + Offset);
|
||||
if (ActualValue != ExpectedValue)
|
||||
return false;
|
||||
}
|
||||
|
||||
// all offsets matched
|
||||
return true;
|
||||
}
|
||||
|
||||
// locate the given function, searching within lower and upper bounds
|
||||
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
|
||||
{
|
||||
uint32 xref_count = Oovpa->XRefCount;
|
||||
// skip out if this is an unnecessary search
|
||||
if(!bXRefFirstPass && xref_count == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex)
|
||||
return (xbaddr)nullptr;
|
||||
// skip out if this is an unnecessary search
|
||||
if (!bXRefFirstPass && Oovpa->XRefCount == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex)
|
||||
return (xbaddr)nullptr;
|
||||
|
||||
// Check all XRefs are known (if not, don't do a useless scan) :
|
||||
for (uint32 v = 0; v < Oovpa->XRefCount; v++)
|
||||
{
|
||||
uint32 XRef;
|
||||
uint08 Offset;
|
||||
|
||||
// get currently registered (un)known address
|
||||
GetXRefEntry(Oovpa, v, XRef, Offset);
|
||||
xbaddr XRefAddr = XRefDataBase[XRef];
|
||||
// Undetermined XRef cannot be checked yet
|
||||
if (XRefAddr == XREF_ADDR_UNDETERMINED)
|
||||
// Skip this scan over the address range
|
||||
return (xbaddr)nullptr;
|
||||
}
|
||||
|
||||
// correct upper bound with highest Oovpa offset
|
||||
uint32 count = Oovpa->Count;
|
||||
|
@ -639,70 +695,27 @@ static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
|
|||
|
||||
// search all of the image memory
|
||||
for (xbaddr cur = lower; cur < upper; cur++)
|
||||
{
|
||||
uint32 v; // verification counter
|
||||
|
||||
// check all cross references
|
||||
for (v = 0; v < xref_count; v++)
|
||||
if (CompareOOVPAToAddress(Oovpa, cur))
|
||||
{
|
||||
uint32 XRef;
|
||||
uint08 Offset;
|
||||
|
||||
// get XRef offset + value pair and currently registered (un)known address
|
||||
GetXRefEntry(Oovpa, v, XRef, Offset);
|
||||
xbaddr XRefValue = XRefDataBase[XRef];
|
||||
|
||||
// unknown XRef cannot be checked yet
|
||||
if (XRefValue == XREF_ADDR_UNDETERMINED)
|
||||
break;
|
||||
|
||||
xbaddr RealValue = *(xbaddr*)(cur + Offset);
|
||||
// check if PC-relative or direct reference matches XRef
|
||||
if ((RealValue + cur + Offset + 4 != XRefValue) && (RealValue != XRefValue))
|
||||
break;
|
||||
}
|
||||
|
||||
// did all xrefs match?
|
||||
if (v == xref_count)
|
||||
{
|
||||
// check all OV pairs, moving on if any do not match
|
||||
for (; v < count; v++)
|
||||
// do we need to save the found address?
|
||||
if (Oovpa->XRefSaveIndex != XRefNoSaveIndex)
|
||||
{
|
||||
uint32 Offset;
|
||||
uint08 Value;
|
||||
|
||||
GetOovpaEntry(Oovpa, v, Offset, Value);
|
||||
uint08 RealValue = *(uint08*)(cur + Offset);
|
||||
if (RealValue != Value)
|
||||
break;
|
||||
}
|
||||
|
||||
// success if we found all pairs
|
||||
if (v == count)
|
||||
{
|
||||
// do we need to save the found address?
|
||||
if (Oovpa->XRefSaveIndex != XRefNoSaveIndex)
|
||||
// is the XRef not saved yet?
|
||||
if (XRefDataBase[Oovpa->XRefSaveIndex] == XREF_ADDR_UNDETERMINED)
|
||||
{
|
||||
// is the XRef not saved yet?
|
||||
if (XRefDataBase[Oovpa->XRefSaveIndex] == XREF_ADDR_UNDETERMINED)
|
||||
{
|
||||
// save and count the found address
|
||||
UnResolvedXRefs--;
|
||||
XRefDataBase[Oovpa->XRefSaveIndex] = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO : Check identical result?
|
||||
// already found, no bother patching again
|
||||
return XRefDataBase[Oovpa->XRefSaveIndex];
|
||||
}
|
||||
// save and count the found address
|
||||
UnResolvedXRefs--;
|
||||
XRefDataBase[Oovpa->XRefSaveIndex] = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XRefDataBase[Oovpa->XRefSaveIndex] != cur)
|
||||
EmuWarning("Found OOVPA on other address than in XRefDataBase!");
|
||||
}
|
||||
|
||||
// return found address
|
||||
return cur;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
// found nothing
|
||||
return (xbaddr)nullptr;
|
||||
|
|
|
@ -197,8 +197,8 @@ extern "C" CXBXKRNL_API uint32 CxbxKrnl_KernelThunkTable[379] =
|
|||
(uint32)FUNC(&xboxkrnl::KeQueryPerformanceFrequency), // 0x007F (127)
|
||||
(uint32)FUNC(&xboxkrnl::KeQuerySystemTime), // 0x0080 (128)
|
||||
(uint32)FUNC(&xboxkrnl::KeRaiseIrqlToDpcLevel), // 0x0081 (129)
|
||||
(uint32)PANIC(0x0082), // 0x0082 (130) KeRaiseIrqlToSynchLevel
|
||||
(uint32)PANIC(0x0083), // 0x0083 (131) KeRaiseIrqlToSynchLevel
|
||||
(uint32)FUNC(&xboxkrnl::KeRaiseIrqlToSynchLevel), // 0x0082 (130)
|
||||
(uint32)PANIC(0x0083), // 0x0083 (131) KeReleaseMutant
|
||||
(uint32)PANIC(0x0084), // 0x0084 (132) KeReleaseSemaphore
|
||||
(uint32)PANIC(0x0085), // 0x0085 (133) KeRemoveByKeyDeviceQueue
|
||||
(uint32)PANIC(0x0086), // 0x0086 (134) KeRemoveDeviceQueue
|
||||
|
|
Loading…
Reference in New Issue