mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-26 16:00:35 +01:00
261 lines
7.5 KiB
C++
261 lines
7.5 KiB
C++
/* Reconstructed from January 2002 target code and genuine SDK declarations.
|
|
* NV2A method payloads are GPU commands, not native instruction emission. */
|
|
#include "draw_internal.h"
|
|
#include "push_internal.h"
|
|
#pragma code_seg("D3D")
|
|
using namespace D3D;
|
|
void WINAPI D3DDevice_SetVertexData2f(
|
|
int reg,
|
|
float x,
|
|
float y)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
PushCount(push, 0x1880 + reg * 8, 2);
|
|
memcpy(push + 1, &x, sizeof(x));
|
|
memcpy(push + 2, &y, sizeof(y));
|
|
device->EndPush(push + 3);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_SetVertexData4f(
|
|
int reg,
|
|
float x,
|
|
float y,
|
|
float z,
|
|
float w)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
DWORD method = reg == -1 ? 0x1518 : 0x1a00 + reg * 16;
|
|
PushCount(push, method, 4);
|
|
memcpy(push + 1, &x, sizeof(x));
|
|
memcpy(push + 2, &y, sizeof(y));
|
|
memcpy(push + 3, &z, sizeof(z));
|
|
memcpy(push + 4, &w, sizeof(w));
|
|
device->EndPush(push + 5);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_SetVertexData2s(
|
|
int reg,
|
|
short x,
|
|
short y)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x1900 + reg * 4, (WORD)x | ((DWORD)y << 16));
|
|
device->EndPush(push + 2);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_SetVertexData4s(
|
|
int reg,
|
|
short x,
|
|
short y,
|
|
short z,
|
|
short w)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
Push2(push, 0x1980 + reg * 8, (WORD)x | ((DWORD)y << 16),
|
|
(WORD)z | ((DWORD)w << 16));
|
|
device->EndPush(push + 3);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_SetVertexData4ub(
|
|
int reg,
|
|
BYTE x,
|
|
BYTE y,
|
|
BYTE z,
|
|
BYTE w)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x1940 + reg * 4, (((((DWORD)w << 8) | z) << 8) | y) << 8 | x);
|
|
device->EndPush(push + 2);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_SetVertexDataColor(
|
|
int reg,
|
|
D3DCOLOR color)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x1940 + reg * 4, SwapRgb(color));
|
|
device->EndPush(push + 2);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_Begin(
|
|
D3DPRIMITIVETYPE primitiveType)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
g_CurrentPrimitiveType = primitiveType;
|
|
SetState();
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x17fc, primitiveType);
|
|
device->EndPush(push + 2);
|
|
device->m_StateFlags |= 0x800;
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_End(
|
|
void)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
g_CurrentPrimitiveType = 0;
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x17fc, 0);
|
|
device->EndPush(push + 2);
|
|
if (device->m_StateFlags & 0x1000)
|
|
SetFence(1);
|
|
device->m_StateFlags &= ~0x1800;
|
|
return;
|
|
}
|
|
|
|
void WINAPI D3DDevice_DrawVertices(
|
|
D3DPRIMITIVETYPE primitiveType,
|
|
UINT startVertex,
|
|
UINT vertexCount)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
device->SetStateVB(0);
|
|
DWORD batchCount = ((vertexCount - 1) >> 8) + 1;
|
|
DWORD *push = device->StartPush(batchCount + 5);
|
|
Push1(push, 0x17fc, primitiveType);
|
|
PushCount(push + 2, 0x40001810, batchCount);
|
|
while (vertexCount > 256)
|
|
{
|
|
push[3] = startVertex | 0xff000000;
|
|
push++;
|
|
startVertex += 256;
|
|
vertexCount -= 256;
|
|
}
|
|
push[3] = startVertex | ((vertexCount - 1) << 24);
|
|
Push1(push + 4, 0x17fc, 0);
|
|
device->EndPush(push + 6);
|
|
return;
|
|
}
|
|
void WINAPI D3DDevice_PrimeVertexCache(
|
|
UINT vertexCount,
|
|
const WORD *indexData)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
device->SetStateVB(device->m_IndexBase);
|
|
DWORD dwordCount = vertexCount >> 1;
|
|
DWORD *push = device->StartPush();
|
|
PushCount(push, 0x40001800, dwordCount);
|
|
DWORD size = dwordCount * sizeof(DWORD);
|
|
memcpy(push + 1, indexData, size);
|
|
push += dwordCount + 1;
|
|
if (vertexCount & 1)
|
|
{
|
|
Push1(push, 0x1808, indexData[dwordCount * 2]);
|
|
push += 2;
|
|
}
|
|
device->EndPush(push);
|
|
return;
|
|
}
|
|
|
|
/* These user-pointer paths submit the original attribute-run representation.
|
|
* Integer byte cursors permit a signed/wrapping inter-run displacement without
|
|
* forming an invalid intermediate C++ pointer. Each copied range must be backed
|
|
* by the caller's valid vertex allocation, including DWORD attribute padding. */
|
|
void WINAPI D3DDevice_DrawVerticesUP(
|
|
D3DPRIMITIVETYPE primitiveType,
|
|
UINT vertexCount,
|
|
const void *vertexData,
|
|
UINT stride)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
device->SetStateUP();
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x17fc, primitiveType);
|
|
device->EndPush(push + 2);
|
|
device->m_StateFlags |= 0x800;
|
|
ULONG_PTR source = (ULONG_PTR)vertexData + device->m_InlineStartOffset;
|
|
DWORD attributeCount = device->m_InlineAttributeCount;
|
|
InlineAttributeData *attributes = device->m_InlineAttributeData;
|
|
attributes[attributeCount - 1].UP_Delta = stride + device->m_InlineDelta;
|
|
DWORD limit = vertexCount <= 16 ? 16 : 2047 / device->m_InlineVertexDwords;
|
|
do
|
|
{
|
|
DWORD batch = min(limit, vertexCount);
|
|
DWORD words = device->m_InlineVertexDwords * batch;
|
|
vertexCount -= batch;
|
|
push = device->StartPush(words + 3);
|
|
PushCount(push, 0x40001818, words);
|
|
push++;
|
|
do
|
|
{
|
|
for (DWORD i = 0; i < attributeCount; ++i)
|
|
{
|
|
DWORD bytes = attributes[i].UP_Count * sizeof(DWORD);
|
|
memcpy(push, (const void *)source, bytes);
|
|
push += attributes[i].UP_Count;
|
|
source += bytes + attributes[i].UP_Delta;
|
|
}
|
|
} while (--batch != 0);
|
|
if (vertexCount)
|
|
{
|
|
device->EndPush(push);
|
|
}
|
|
} while (vertexCount != 0);
|
|
Push1(push, 0x17fc, 0);
|
|
device->EndPush(push + 2);
|
|
if (device->m_StateFlags & 0x1000)
|
|
{
|
|
SetFence(1);
|
|
}
|
|
device->m_StateFlags &= ~0x1800UL;
|
|
return;
|
|
}
|
|
|
|
void WINAPI D3DDevice_DrawIndexedVerticesUP(
|
|
D3DPRIMITIVETYPE primitiveType,
|
|
UINT vertexCount,
|
|
const void *indexData,
|
|
const void *vertexData,
|
|
UINT stride)
|
|
{
|
|
const WORD *indices = (const WORD *)indexData;
|
|
CDevice *device = g_pDevice;
|
|
device->SetStateUP();
|
|
DWORD *push = device->StartPush();
|
|
Push1(push, 0x17fc, primitiveType);
|
|
device->EndPush(push + 2);
|
|
device->m_StateFlags |= 0x800;
|
|
ULONG_PTR base = (ULONG_PTR)vertexData + device->m_InlineStartOffset;
|
|
DWORD attributeCount = device->m_InlineAttributeCount;
|
|
const InlineAttributeData *attributes = device->m_InlineAttributeData;
|
|
DWORD limit = vertexCount <= 16 ? 16 : 2047 / device->m_InlineVertexDwords;
|
|
do
|
|
{
|
|
DWORD batch = min(limit, vertexCount);
|
|
DWORD words = device->m_InlineVertexDwords * batch;
|
|
vertexCount -= batch;
|
|
push = device->StartPush(words + 3);
|
|
PushCount(push, 0x40001818, words);
|
|
push++;
|
|
do
|
|
{
|
|
ULONG_PTR source = base + (DWORD)*indices++ * stride;
|
|
for (DWORD i = 0; i < attributeCount; ++i)
|
|
{
|
|
DWORD bytes = attributes[i].UP_Count * sizeof(DWORD);
|
|
memcpy(push, (const void *)source, bytes);
|
|
push += attributes[i].UP_Count;
|
|
source += bytes + attributes[i].UP_Delta;
|
|
}
|
|
} while (--batch != 0);
|
|
if (vertexCount)
|
|
{
|
|
device->EndPush(push);
|
|
}
|
|
} while (vertexCount != 0);
|
|
Push1(push, 0x17fc, 0);
|
|
device->EndPush(push + 2);
|
|
if (device->m_StateFlags & 0x1000)
|
|
{
|
|
SetFence(1);
|
|
}
|
|
device->m_StateFlags &= ~0x1800UL;
|
|
return;
|
|
}
|