Cxbx-reloaded: Several games throws exception at VertexBuffer.cpp#L806 (uiVertexCount)

Created on 13 Mar 2018  Â·  7Comments  Â·  Source: Cxbx-Reloaded/Cxbx-Reloaded

Tested by https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/commit/93cf2ab789aaa422ef8f3a194b45f22e6f990731

Issued games:

Army Men: Major Malfunction
Blood Wake
Cars
Galleon
Goblin Commander: Unleash the Horde
Jurassic Park: Operation Genesis
Loons: The Fight for Fame
Metal Arms: Glitch in the System
Metal Dungeon
Motocross Mania 3
Test Drive Off-Road Wide Open
Worms 4: Mayhem
Worms Forts: Under Siege

https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/master/src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp#L806

bool XTL::VertexPatcher::PatchPrimitive(VertexPatchDesc *pPatchDesc,
                                        UINT             uiStream)
{
    PATCHEDSTREAM *pStream = &m_pStreams[uiStream];

    if((pPatchDesc->XboxPrimitiveType < X_D3DPT_POINTLIST) || (pPatchDesc->XboxPrimitiveType >= X_D3DPT_MAX))
    {
        EmuWarning("Unknown primitive type: 0x%.02X\n", pPatchDesc->XboxPrimitiveType);
        return false;
    }

    if (pPatchDesc->pXboxVertexStreamZeroData == nullptr)
    {
        pStream->pOriginalStream = g_D3DStreams[uiStream];
        pStream->uiOrigStride = g_D3DStreamStrides[uiStream];
        pStream->uiNewStride = pStream->uiOrigStride; // The stride is still the same
    }
    else
    {
        pStream->uiOrigStride = pPatchDesc->uiXboxVertexStreamZeroStride;
    }

    DWORD uiLength = GetVertexBufferSize(pPatchDesc->dwVertexCount, pStream->uiOrigStride, pPatchDesc->pIndexData, pPatchDesc->dwStartVertex, pPatchDesc->dwIndexBase);
    ►►► DWORD uiVertexCount = uiLength / pStream->uiOrigStride;

    // Unsupported primitives that don't need deep patching.
    switch(pPatchDesc->XboxPrimitiveType)
    {
        // Quad strip is just like a triangle strip, but requires two
        // vertices per primitive.
        case X_D3DPT_QUADSTRIP:
            pPatchDesc->dwVertexCount -= pPatchDesc->dwVertexCount % 2;
            pPatchDesc->XboxPrimitiveType = X_D3DPT_TRIANGLESTRIP;
            break;

        // Convex polygon is the same as a triangle fan.
        case X_D3DPT_POLYGON:
            pPatchDesc->XboxPrimitiveType = X_D3DPT_TRIANGLEFAN;
            break;
    }
bug graphics

All 7 comments

This exception, is it a division by zero by any chance?

It appears so. Often division by 0 occurs if (pPatchDesc->pXboxVertexStreamZeroData == nullptr).

That implies the stride is not being set properly..
if pXboxVertexStreamData is nullptr, g_D3DStreamStrides[uiStream] should be a valid value, otherwise, uiXboxVertexStreamZeroStride should be used..

So, for these titles, the stride must not be being set properly. Best to make sure that the titles are actually calling D3DDevice_SetStreamSource properly, and with a valid stride. Perhaps the function signature changed at some point, breaking our patch?

The D3DDevice_SetStreamSource signature is still valid.

In the Blood Wake title, it is safe that pXboxVertexStreamData is nullptr, or valid that while keeping in the menu. However, it will break when reaching in-game.
Crash log on line 1194750.

KrnlDebug.zip

[0x1878] KRNL: KeDelayExecutionThread(
   WaitMode             : \x01
   Alertable            : 0x00
   Interval             : 0x0C57FE6C -> LARGE_INTEGER* {
   .QuadPart             : FFFFFFFFFFFD8F00}
);
D3DXERR_INVALIDDATA: Unknown D3D error.[0x1AC4] CxbxUpdateActiveIndexBuffer: Copying 1405 indices (D3DFMT_INDEX16)
pXboxVertexStreamZeroData is nullptr!
pOriginalStream 0d928b50 uiLength 00005b40 uiOrigStride 00000020
pXboxVertexStreamZeroData is nullptr!
pOriginalStream 00000000 uiLength 00000000 uiOrigStride 00000000
[0x1AC4] MAIN: Received Exception (Code := 0xC0000094)

 EIP := 0x040D50B5
 EFL := 0x00210246
 EAX := 0x00000000 EBX := 0x00000000 ECX := 0x08BCF5B8 EDX := 0x00000000
 ESI := 0x08BCF4D8 EDI := 0x08BCF4C8 ESP := 0x08BCF468 EBP := 0x08BCF4C8
 CR2 := 0x00000000

Same as Metal Dungeon title, just before division by 0 occurs CxbxUpdateActiveIndexBuffer has been called. Is this function affecting?

Thanks for the detailed report @jarupxx ! CxbxUpdateActiveIndexBuffer shouldn't fail, so that's certainly a problem that needs to be investigated and fixed. But, that's a separate issue from the division by zero, which is certainly caused by uiOrigStride 00000000. This also needs to be investigated and fixed (probably in the area(s) where VertexPatchDesc is/are initialized).

https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/pull/1152 re-implemented much of what's described here - for me, Galleon goes in-game now. @JohnGodgames please re-test the above on that Pull Request, and report back here.

It's been a few months and no reply. #1152 fixed much of what was discussed here. Closing for now.

Was this page helpful?
0 / 5 - 0 ratings