Port CxbxRemoveIndexBuffer
More work is still required. CreateDevice really needs to be unpatched, there's no avoiding this now!
This commit is contained in:
parent
a8997b4b41
commit
7939ca665d
|
@ -1498,6 +1498,154 @@ static void EmuUnswizzleTextureStages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD IndexData;
|
||||||
|
DWORD IndexEnd;
|
||||||
|
XTL::IDirect3DIndexBuffer8* pHostIndexBuffer;
|
||||||
|
} ConvertedIndexBuffer;
|
||||||
|
|
||||||
|
std::vector<ConvertedIndexBuffer> g_ConvertedIndexBuffers;
|
||||||
|
|
||||||
|
void CxbxRemoveIndexBuffer(PWORD pData)
|
||||||
|
{
|
||||||
|
// Now, see if we already have a (partial) index buffer for this range :
|
||||||
|
ConvertedIndexBuffer* pConvertedIndexBuffer = nullptr;
|
||||||
|
|
||||||
|
auto it = g_ConvertedIndexBuffers.begin();
|
||||||
|
for (; it != g_ConvertedIndexBuffers.end(); ++it) {
|
||||||
|
// Check if we found an index buffer containing this pointer
|
||||||
|
if ((DWORD)it->IndexData <= (DWORD)pData && (DWORD)pData < (DWORD)it->IndexEnd) {
|
||||||
|
pConvertedIndexBuffer = &(*it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pConvertedIndexBuffer != nullptr) {
|
||||||
|
DbgPrintf("DxbxRemoveIndexBuffer: Removing buffer for 0x%08x-0x%08x", pConvertedIndexBuffer->IndexData, pConvertedIndexBuffer->IndexEnd);
|
||||||
|
pConvertedIndexBuffer->pHostIndexBuffer->Release();
|
||||||
|
g_ConvertedIndexBuffers.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CxbxUpdateActiveIndexBuffer
|
||||||
|
(
|
||||||
|
PWORD pIndexData,
|
||||||
|
UINT IndexCount,
|
||||||
|
UINT &uiStartIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PWORD pwInitialStart = pIndexData; // Remember this to calculate StartIndex later!
|
||||||
|
PWORD pwIndexEnd = pIndexData + IndexCount;
|
||||||
|
bool MustCopy = false;
|
||||||
|
|
||||||
|
// Note : We assume that all outdated index buffer(s) are already removed,
|
||||||
|
// so that we'll never merge with buffers already destroyed on the Xbox side!
|
||||||
|
|
||||||
|
// Now, see if we already have a (partial) index buffer for this range :
|
||||||
|
ConvertedIndexBuffer* pConvertedIndexBuffer = nullptr;
|
||||||
|
|
||||||
|
for (auto it = g_ConvertedIndexBuffers.begin(); it != g_ConvertedIndexBuffers.end(); ++it) {
|
||||||
|
// Check if the given index range overlaps with this buffer :
|
||||||
|
if ((DWORD)pIndexData > (DWORD)it->IndexEnd) {
|
||||||
|
// new buffer starts beyond current (so no overlap)
|
||||||
|
}
|
||||||
|
else if ((DWORD)pwIndexEnd < (DWORD)it->IndexData) {
|
||||||
|
// new buffer end before current (so no overlap)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The new and current buffer overlap - we found a merge candidate!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pConvertedIndexBuffer = &(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we find a merge candidate?
|
||||||
|
if (pConvertedIndexBuffer == nullptr) {
|
||||||
|
DbgPrintf("DxbxUpdateActiveIndexBuffer: Creating new buffer for 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
||||||
|
|
||||||
|
// No merge, so add a new converted index buffer to the chain :
|
||||||
|
ConvertedIndexBuffer buffer;
|
||||||
|
g_ConvertedIndexBuffers.push_back(buffer);
|
||||||
|
|
||||||
|
pConvertedIndexBuffer = &g_ConvertedIndexBuffers.back();
|
||||||
|
MustCopy = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We found an existing index buffer, see if we must extend it's bounds :
|
||||||
|
if ((DWORD)pIndexData < pConvertedIndexBuffer->IndexData) {
|
||||||
|
MustCopy = true; // The merge has a new start pointer
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pIndexData = (PWORD)pConvertedIndexBuffer->IndexData; // The merge keeps the old start pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((DWORD)pwIndexEnd > pConvertedIndexBuffer->IndexEnd) {
|
||||||
|
MustCopy = true; // The merge has a new end pointer
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pwIndexEnd = (PWORD)pConvertedIndexBuffer->IndexEnd; // The merge keeps the old end pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : What if this grow causes two (or more) existing ranges to overlap - we should merge them all...
|
||||||
|
// TOOD : What if the index buffer exceeds D3DCaps.MaxVertexIndex ?
|
||||||
|
|
||||||
|
// TODO : If not MustCopy, Add a CRC check on the contents (forcing MustCopy) ?
|
||||||
|
|
||||||
|
if (MustCopy) {
|
||||||
|
DbgPrintf("DxbxUpdateActiveIndexBuffer: Enlarging buffer to 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
||||||
|
|
||||||
|
// Remove previous native buffer (this might leave one stale reference,
|
||||||
|
// but this one will be released automatically in the next SetIndices call) :
|
||||||
|
pConvertedIndexBuffer->pHostIndexBuffer->Release();
|
||||||
|
pConvertedIndexBuffer->pHostIndexBuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hRet;
|
||||||
|
|
||||||
|
if (MustCopy) {
|
||||||
|
// Remember the (new) buffer bounds :
|
||||||
|
pConvertedIndexBuffer->IndexData = (DWORD)pIndexData;
|
||||||
|
pConvertedIndexBuffer->IndexEnd = (DWORD)pwIndexEnd;
|
||||||
|
IndexCount = pwIndexEnd - pIndexData; // Calculate the number of WORD's between start & end
|
||||||
|
|
||||||
|
// Create a new native index buffer of the above determined size :
|
||||||
|
hRet = g_pD3DDevice8->CreateIndexBuffer(
|
||||||
|
IndexCount * 2,
|
||||||
|
D3DUSAGE_WRITEONLY,
|
||||||
|
XTL::D3DFMT_INDEX16,
|
||||||
|
XTL::D3DPOOL_MANAGED,
|
||||||
|
&pConvertedIndexBuffer->pHostIndexBuffer);
|
||||||
|
|
||||||
|
if (FAILED(hRet)) {
|
||||||
|
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: IndexBuffer Create Failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the xbox indexes into this native buffer :
|
||||||
|
BYTE* pData = nullptr;
|
||||||
|
|
||||||
|
pConvertedIndexBuffer->pHostIndexBuffer->Lock(0, 0, &pData, 0);
|
||||||
|
if (pData == nullptr) {
|
||||||
|
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: Could not lock index buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgPrintf("DxbxUpdateActiveIndexBuffer: Copying %d indices (D3DFMT_INDEX16)\n", IndexCount);
|
||||||
|
memcpy(pData, pIndexData, IndexCount * 2); // TODO : Why does this crash at the 4th copy in Cartoon sample?
|
||||||
|
|
||||||
|
pConvertedIndexBuffer->pHostIndexBuffer->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate the new native index buffer :
|
||||||
|
hRet = g_pD3DDevice8->SetIndices(pConvertedIndexBuffer->pHostIndexBuffer, 0);
|
||||||
|
if (FAILED(hRet)) {
|
||||||
|
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: SetIndices Failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the caller knows what StartIndex it has to use to point to the indicated index start pointer :
|
||||||
|
uiStartIndex = (UINT)pwInitialStart - (UINT)pConvertedIndexBuffer->IndexData;
|
||||||
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: Direct3D_CreateDevice
|
// * patch: Direct3D_CreateDevice
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -5247,9 +5395,13 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
||||||
}
|
}
|
||||||
|
|
||||||
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
||||||
}
|
} else if (pThis->Common & X_D3DCOMMON_TYPE_INDEXBUFFER) {
|
||||||
else
|
if ((pThis->Common & X_D3DCOMMON_REFCOUNT_MASK) == 1) {
|
||||||
{
|
CxbxRemoveIndexBuffer((PWORD)GetDataFromXboxResource(pThis));
|
||||||
|
}
|
||||||
|
|
||||||
|
uRet = pThis->Common--; // Release
|
||||||
|
} else {
|
||||||
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
|
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
|
||||||
|
|
||||||
if(pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
|
if(pThis->Lock == X_D3DRESOURCE_LOCK_PALETTE)
|
||||||
|
@ -7861,130 +8013,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawVerticesUP)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DWORD IndexData;
|
|
||||||
DWORD IndexEnd;
|
|
||||||
XTL::IDirect3DIndexBuffer8* pHostIndexBuffer;
|
|
||||||
} ConvertedIndexBuffer;
|
|
||||||
|
|
||||||
std::vector<ConvertedIndexBuffer> g_ConvertedIndexBuffers;
|
|
||||||
|
|
||||||
void CxbxUpdateActiveIndexBuffer
|
|
||||||
(
|
|
||||||
PWORD pIndexData,
|
|
||||||
UINT IndexCount,
|
|
||||||
UINT &uiStartIndex
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PWORD pwInitialStart = pIndexData; // Remember this to calculate StartIndex later!
|
|
||||||
PWORD pwIndexEnd = pIndexData + IndexCount;
|
|
||||||
bool MustCopy = false;
|
|
||||||
|
|
||||||
// Note : We assume that all outdated index buffer(s) are already removed,
|
|
||||||
// so that we'll never merge with buffers already destroyed on the Xbox side!
|
|
||||||
|
|
||||||
// Now, see if we already have a (partial) index buffer for this range :
|
|
||||||
ConvertedIndexBuffer* pConvertedIndexBuffer = nullptr;
|
|
||||||
|
|
||||||
for(auto it = g_ConvertedIndexBuffers.begin(); it != g_ConvertedIndexBuffers.end(); ++it) {
|
|
||||||
// Check if the given index range overlaps with this buffer :
|
|
||||||
if ((DWORD)pIndexData > (DWORD)it->IndexEnd) {
|
|
||||||
// new buffer starts beyond current (so no overlap)
|
|
||||||
}
|
|
||||||
else if ((DWORD)pwIndexEnd < (DWORD)it->IndexData) {
|
|
||||||
// new buffer end before current (so no overlap)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The new and current buffer overlap - we found a merge candidate!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pConvertedIndexBuffer = &(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did we find a merge candidate?
|
|
||||||
if (pConvertedIndexBuffer == nullptr) {
|
|
||||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Creating new buffer for 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
|
||||||
|
|
||||||
// No merge, so add a new converted index buffer to the chain :
|
|
||||||
ConvertedIndexBuffer buffer;
|
|
||||||
g_ConvertedIndexBuffers.push_back(buffer);
|
|
||||||
|
|
||||||
pConvertedIndexBuffer = &g_ConvertedIndexBuffers.back();
|
|
||||||
MustCopy = true;
|
|
||||||
} else {
|
|
||||||
// We found an existing index buffer, see if we must extend it's bounds :
|
|
||||||
if ((DWORD)pIndexData < pConvertedIndexBuffer->IndexData) {
|
|
||||||
MustCopy = true; // The merge has a new start pointer
|
|
||||||
} else {
|
|
||||||
pIndexData = (PWORD)pConvertedIndexBuffer->IndexData; // The merge keeps the old start pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((DWORD)pwIndexEnd > pConvertedIndexBuffer->IndexEnd) {
|
|
||||||
MustCopy = true; // The merge has a new end pointer
|
|
||||||
} else {
|
|
||||||
pwIndexEnd = (PWORD)pConvertedIndexBuffer->IndexEnd; // The merge keeps the old end pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO : What if this grow causes two (or more) existing ranges to overlap - we should merge them all...
|
|
||||||
// TOOD : What if the index buffer exceeds D3DCaps.MaxVertexIndex ?
|
|
||||||
|
|
||||||
// TODO : If not MustCopy, Add a CRC check on the contents (forcing MustCopy) ?
|
|
||||||
|
|
||||||
if (MustCopy) {
|
|
||||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Enlarging buffer to 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
|
||||||
|
|
||||||
// Remove previous native buffer (this might leave one stale reference,
|
|
||||||
// but this one will be released automatically in the next SetIndices call) :
|
|
||||||
pConvertedIndexBuffer->pHostIndexBuffer->Release();
|
|
||||||
pConvertedIndexBuffer->pHostIndexBuffer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT hRet;
|
|
||||||
|
|
||||||
if (MustCopy) {
|
|
||||||
// Remember the (new) buffer bounds :
|
|
||||||
pConvertedIndexBuffer->IndexData = (DWORD)pIndexData;
|
|
||||||
pConvertedIndexBuffer->IndexEnd = (DWORD)pwIndexEnd;
|
|
||||||
IndexCount = pwIndexEnd - pIndexData; // Calculate the number of WORD's between start & end
|
|
||||||
|
|
||||||
// Create a new native index buffer of the above determined size :
|
|
||||||
hRet = g_pD3DDevice8->CreateIndexBuffer(
|
|
||||||
IndexCount * 2,
|
|
||||||
D3DUSAGE_WRITEONLY,
|
|
||||||
XTL::D3DFMT_INDEX16,
|
|
||||||
XTL::D3DPOOL_MANAGED,
|
|
||||||
&pConvertedIndexBuffer->pHostIndexBuffer);
|
|
||||||
|
|
||||||
if (FAILED(hRet)) {
|
|
||||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: IndexBuffer Create Failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the xbox indexes into this native buffer :
|
|
||||||
BYTE* pData = nullptr;
|
|
||||||
|
|
||||||
pConvertedIndexBuffer->pHostIndexBuffer->Lock(0, 0, &pData, 0);
|
|
||||||
if (pData == nullptr) {
|
|
||||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: Could not lock index buffer!");
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Copying %d indices (D3DFMT_INDEX16)\n", IndexCount);
|
|
||||||
memcpy(pData, pIndexData, IndexCount * 2); // TODO : Why does this crash at the 4th copy in Cartoon sample?
|
|
||||||
|
|
||||||
pConvertedIndexBuffer->pHostIndexBuffer->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activate the new native index buffer :
|
|
||||||
hRet = g_pD3DDevice8->SetIndices(pConvertedIndexBuffer->pHostIndexBuffer, 0);
|
|
||||||
if (FAILED(hRet)) {
|
|
||||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: SetIndices Failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the caller knows what StartIndex it has to use to point to the indicated index start pointer :
|
|
||||||
uiStartIndex = (UINT)pwInitialStart - (UINT)pConvertedIndexBuffer->IndexData;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VERTICES_PER_QUAD 4
|
#define VERTICES_PER_QUAD 4
|
||||||
#define TRIANGLES_PER_QUAD 2
|
#define TRIANGLES_PER_QUAD 2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue