mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-27 00:00:42 +01:00
719 lines
21 KiB
C++
719 lines
21 KiB
C++
/* January state-block reconstruction; target PDB and COFF are authoritative.
|
|
* Related RXDK block implementation: Copyright (C) 2026 Team Resurgent.
|
|
* SPDX-License-Identifier: GPL-3.0-or-later. See retained reference provenance. */
|
|
#include "block_internal.h"
|
|
#include "vshader_internal.h"
|
|
#include "memory_internal.h"
|
|
#pragma code_seg("D3D")
|
|
#pragma const_seg("D3D_RD")
|
|
extern "C"
|
|
{
|
|
BYTE D3D__StateBlockDirty[(D3DSBD_MAX + 3) & ~3];
|
|
}
|
|
namespace D3D
|
|
{
|
|
void WINAPI ClearStateBlockFlags(
|
|
void)
|
|
{
|
|
CDevice *device = g_pDevice;
|
|
ZeroMemory(D3D__StateBlockDirty, sizeof(D3D__StateBlockDirty));
|
|
Light *light = device->m_pLights;
|
|
for (DWORD i = 0; i < device->m_LightCount; ++i, ++light)
|
|
{
|
|
light->Flags &= ~(LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED);
|
|
}
|
|
return;
|
|
}
|
|
extern "C" void WINAPI D3DDevice_BeginStateBlock(
|
|
void)
|
|
{
|
|
g_pDevice->m_StateFlags |= STATE_RECORDBLOCK;
|
|
ClearStateBlockFlags();
|
|
return;
|
|
}
|
|
extern "C" void WINAPI D3DDevice_Suspend(
|
|
void)
|
|
{
|
|
g_pDevice->SetStateVB(0);
|
|
return;
|
|
}
|
|
extern "C" void WINAPI D3DDevice_ApplyStateBlock(
|
|
DWORD token)
|
|
{
|
|
DWORD i;
|
|
CDevice *device = g_pDevice;
|
|
StateBlock *block = (StateBlock *)token;
|
|
DWORD *data = StateBlockData(block);
|
|
for (i = 0; i < block->D0_Textures; ++i)
|
|
{
|
|
device->SetTexture(data[0], (D3DBaseTexture *)data[1]);
|
|
data += 2;
|
|
}
|
|
if (block->D1_PixelShader)
|
|
{
|
|
device->SetPixelShader(data[0]);
|
|
++data;
|
|
}
|
|
if (block->D2_VertexShader)
|
|
{
|
|
device->SetVertexShader(data[0]);
|
|
++data;
|
|
}
|
|
if (block->D3_Index)
|
|
{
|
|
device->SetIndices((D3DIndexBuffer *)data[1], data[0]);
|
|
data += 2;
|
|
}
|
|
for (i = 0; i < block->D4_Streams; ++i)
|
|
{
|
|
device->SetStreamSource(data[0], (D3DVertexBuffer *)data[2], data[1]);
|
|
data += 3;
|
|
}
|
|
for (i = 0; i < block->D6_PixelShaderConstants; ++i)
|
|
{
|
|
device->SetPixelShaderConstant(data[0], data + 1, 1);
|
|
data += 5;
|
|
}
|
|
for (i = 0; i < block->D7_VertexShaderConstants; ++i)
|
|
{
|
|
device->SetVertexShaderConstant(data[0] - 96, data + 1, 1);
|
|
data += 5;
|
|
}
|
|
for (i = 0; i < block->D8_RenderStates; ++i)
|
|
{
|
|
DWORD state = data[0];
|
|
DWORD value = data[1];
|
|
if (D3D__RenderState[state] != value)
|
|
{
|
|
device->SetRenderStateNotInline((D3DRENDERSTATETYPE)state, value);
|
|
}
|
|
data += 2;
|
|
}
|
|
for (i = 0; i < block->D9_TextureStates; ++i)
|
|
{
|
|
DWORD stage = data[0];
|
|
DWORD state = data[1];
|
|
DWORD value = data[2];
|
|
if (D3D__TextureState[stage][state] != value)
|
|
{
|
|
device->SetTextureStageStateNotInline(stage, (D3DTEXTURESTAGESTATETYPE)state, value);
|
|
}
|
|
data += 3;
|
|
}
|
|
for (i = 0; i < block->D10_Transforms; ++i)
|
|
{
|
|
device->SetTransform((D3DTRANSFORMSTATETYPE)data[0], (const D3DMATRIX *)(data + 1));
|
|
data += 1 + sizeof(D3DMATRIX) / sizeof(DWORD);
|
|
}
|
|
if (block->D11_Viewport)
|
|
{
|
|
device->SetViewport((const D3DVIEWPORT8 *)data);
|
|
data += sizeof(D3DVIEWPORT8) / sizeof(DWORD);
|
|
}
|
|
if (block->D12_Material)
|
|
{
|
|
device->SetMaterial((const D3DMATERIAL8 *)data);
|
|
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
|
}
|
|
if (block->D13_BackMaterial)
|
|
{
|
|
device->SetBackMaterial((const D3DMATERIAL8 *)data);
|
|
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
|
}
|
|
for (i = 0; i < block->D14_Lights; ++i)
|
|
{
|
|
device->SetLight(data[0], (const D3DLIGHT8 *)(data + 1));
|
|
data += 1 + sizeof(D3DLIGHT8) / sizeof(DWORD);
|
|
}
|
|
for (i = 0; i < block->D15_LightEnables; ++i)
|
|
{
|
|
device->LightEnable(data[0], data[1]);
|
|
data += 2;
|
|
}
|
|
return;
|
|
}
|
|
extern "C" void WINAPI D3DDevice_DeleteStateBlock(
|
|
DWORD token)
|
|
{
|
|
DWORD i;
|
|
StateBlock *block = (StateBlock *)token;
|
|
DWORD *data = StateBlockData(block);
|
|
for (i = 0; i < block->D0_Textures; ++i)
|
|
{
|
|
D3DBaseTexture *texture = (D3DBaseTexture *)data[1];
|
|
data += 2;
|
|
if (texture != NULL)
|
|
{
|
|
texture->Release();
|
|
}
|
|
}
|
|
if (block->D1_PixelShader)
|
|
{
|
|
DWORD handle = *data++;
|
|
if (handle != 0)
|
|
{
|
|
D3DDevice::DeletePixelShader(handle);
|
|
}
|
|
}
|
|
if (block->D2_VertexShader)
|
|
{
|
|
DWORD handle = *data++;
|
|
if (handle & D3DFVF_RESERVED0)
|
|
{
|
|
D3DDevice::DeleteVertexShader(handle);
|
|
}
|
|
}
|
|
if (block->D3_Index)
|
|
{
|
|
D3DIndexBuffer *indexBuffer = (D3DIndexBuffer *)data[1];
|
|
data += 2;
|
|
if (indexBuffer != NULL)
|
|
{
|
|
indexBuffer->Release();
|
|
}
|
|
}
|
|
for (i = 0; i < block->D4_Streams; ++i)
|
|
{
|
|
D3DVertexBuffer *vertexBuffer = (D3DVertexBuffer *)data[2];
|
|
data += 3;
|
|
if (vertexBuffer != NULL)
|
|
{
|
|
vertexBuffer->Release();
|
|
}
|
|
}
|
|
LocalFree(block);
|
|
return;
|
|
}
|
|
|
|
extern "C" void WINAPI D3DDevice_CaptureStateBlock(
|
|
DWORD token)
|
|
{
|
|
DWORD i;
|
|
CDevice *device = g_pDevice;
|
|
StateBlock *block = (StateBlock *)token;
|
|
DWORD *data = StateBlockData(block);
|
|
for (i = 0; i < block->D0_Textures; ++i)
|
|
{
|
|
DWORD stage = data[0];
|
|
D3DBaseTexture *texture = (D3DBaseTexture *)data[1];
|
|
if (texture) texture->Release();
|
|
texture = device->m_Textures[stage];
|
|
if (texture) texture->AddRef();
|
|
data[1] = (DWORD)texture;
|
|
data += 2;
|
|
}
|
|
if (block->D1_PixelShader)
|
|
{
|
|
DWORD handle = data[0];
|
|
if (handle) device->DeletePixelShader(handle);
|
|
handle = (DWORD)device->m_pPixelShader;
|
|
if (handle) ++device->m_pPixelShader->RefCount;
|
|
data[0] = handle;
|
|
++data;
|
|
}
|
|
if (block->D2_VertexShader)
|
|
{
|
|
DWORD handle = data[0];
|
|
if (handle & D3DFVF_RESERVED0) device->DeleteVertexShader(handle);
|
|
handle = device->m_VertexShaderHandle;
|
|
if (handle & D3DFVF_RESERVED0) ++device->m_pVertexShader->RefCount;
|
|
data[0] = handle;
|
|
++data;
|
|
}
|
|
if (block->D3_Index)
|
|
{
|
|
D3DIndexBuffer *indexBuffer = (D3DIndexBuffer *)data[1];
|
|
if (indexBuffer) indexBuffer->Release();
|
|
indexBuffer = device->m_pIndexBuffer;
|
|
if (indexBuffer) indexBuffer->AddRef();
|
|
data[0] = device->m_IndexBase;
|
|
data[1] = (DWORD)indexBuffer;
|
|
data += 2;
|
|
}
|
|
for (i = 0; i < block->D4_Streams; ++i)
|
|
{
|
|
DWORD index = data[0];
|
|
D3DVertexBuffer *vertexBuffer = (D3DVertexBuffer *)data[2];
|
|
if (vertexBuffer) vertexBuffer->Release();
|
|
vertexBuffer = g_Stream[index].pVertexBuffer;
|
|
if (vertexBuffer) vertexBuffer->AddRef();
|
|
data[1] = g_Stream[index].Stride;
|
|
data[2] = (DWORD)vertexBuffer;
|
|
data += 3;
|
|
}
|
|
for (i = 0; i < block->D6_PixelShaderConstants; ++i)
|
|
{
|
|
DWORD index = data[0];
|
|
void *constantData = data + 1;
|
|
memcpy(constantData, device->m_PixelShaderConstants[index], 4 * sizeof(FLOAT));
|
|
data += 5;
|
|
}
|
|
for (i = 0; i < block->D7_VertexShaderConstants; ++i)
|
|
{
|
|
DWORD index = data[0];
|
|
void *constantData = data + 1;
|
|
memcpy(constantData, device->m_VertexShaderConstants[index], 4 * sizeof(FLOAT));
|
|
data += 5;
|
|
}
|
|
for (i = 0; i < block->D8_RenderStates; ++i)
|
|
{
|
|
DWORD state = data[0];
|
|
data[1] = D3D__RenderState[state];
|
|
data += 2;
|
|
}
|
|
for (i = 0; i < block->D9_TextureStates; ++i)
|
|
{
|
|
DWORD stage = data[0];
|
|
DWORD state = data[1];
|
|
data[2] = D3D__TextureState[stage][state];
|
|
data += 3;
|
|
}
|
|
for (i = 0; i < block->D10_Transforms; ++i)
|
|
{
|
|
DWORD state = data[0];
|
|
memcpy((void *)(data + 1), &device->m_Transform[state], sizeof(device->m_Transform[state]));
|
|
data += 1 + sizeof(D3DMATRIX) / sizeof(DWORD);
|
|
}
|
|
if (block->D11_Viewport)
|
|
{
|
|
memcpy(data, &device->m_Viewport, sizeof(D3DVIEWPORT8));
|
|
data += sizeof(D3DVIEWPORT8) / sizeof(DWORD);
|
|
}
|
|
if (block->D12_Material)
|
|
{
|
|
memcpy(data, &device->m_Material, sizeof(D3DMATERIAL8));
|
|
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
|
}
|
|
if (block->D13_BackMaterial)
|
|
{
|
|
memcpy(data, &device->m_BackMaterial, sizeof(D3DMATERIAL8));
|
|
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
|
}
|
|
for (i = 0; i < block->D14_Lights; ++i)
|
|
{
|
|
DWORD index = data[0];
|
|
memcpy(data + 1, &device->m_pLights[index].Light8, sizeof(D3DLIGHT8));
|
|
data += 1 + sizeof(D3DLIGHT8) / sizeof(DWORD);
|
|
}
|
|
for (i = 0; i < block->D15_LightEnables; ++i)
|
|
{
|
|
device->GetLightEnable(data[0], (BOOL *)(data + 1));
|
|
data += 2;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Cursor is a byte count during sizing and an allocated address during writing.
|
|
* Using ULONG_PTR avoids the historical NULL-based member/pointer arithmetic.
|
|
* Each conversion to a writable record occurs only after allocation succeeded.
|
|
* The dirty set and device state must not change concurrently between passes. */
|
|
HRESULT WINAPI RecordStateBlock(
|
|
DWORD *token)
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
BYTE *dirty;
|
|
StateBlock *block = NULL;
|
|
ULONG_PTR cursor = offsetof(StateBlock, Data);
|
|
CDevice *device = g_pDevice;
|
|
Light *lights = device->m_pLights;
|
|
*token = 0;
|
|
for (;;)
|
|
{
|
|
dirty = D3D__StateBlockDirty;
|
|
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
|
{
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
D3DBaseTexture *texture = device->m_Textures[i];
|
|
++block->D0_Textures;
|
|
data[0] = i;
|
|
data[1] = (DWORD)texture;
|
|
if (texture) texture->AddRef();
|
|
}
|
|
cursor += 2 * sizeof(DWORD);
|
|
}
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
PixelShader *shader = device->m_pPixelShader;
|
|
block->D1_PixelShader = TRUE;
|
|
*(DWORD *)cursor = (DWORD)shader;
|
|
if (shader) ++shader->RefCount;
|
|
}
|
|
cursor += sizeof(DWORD);
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD handle = device->m_VertexShaderHandle;
|
|
block->D2_VertexShader = TRUE;
|
|
*(DWORD *)cursor = handle;
|
|
if (handle & D3DFVF_RESERVED0) ++device->m_pVertexShader->RefCount;
|
|
}
|
|
cursor += sizeof(DWORD);
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
D3DIndexBuffer *indexBuffer = device->m_pIndexBuffer;
|
|
block->D3_Index = TRUE;
|
|
data[0] = device->m_IndexBase;
|
|
data[1] = (DWORD)indexBuffer;
|
|
if (indexBuffer) indexBuffer->AddRef();
|
|
}
|
|
cursor += 2 * sizeof(DWORD);
|
|
}
|
|
for (i = 0; i < D3DVS_STREAMS_MAX_V1_0; ++i)
|
|
{
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
D3DVertexBuffer *vertexBuffer = g_Stream[i].pVertexBuffer;
|
|
++block->D4_Streams;
|
|
data[0] = i;
|
|
data[1] = g_Stream[i].Stride;
|
|
data[2] = (DWORD)vertexBuffer;
|
|
if (vertexBuffer) vertexBuffer->AddRef();
|
|
}
|
|
cursor += 3 * sizeof(DWORD);
|
|
}
|
|
}
|
|
for (i = 0; i < D3DPS_CONSTREG_MAX_DX8; ++i)
|
|
{
|
|
if (*dirty++ && device->m_pPixelShader)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D6_PixelShaderConstants;
|
|
data[0] = i;
|
|
memcpy(data + 1, device->m_PixelShaderConstants[i], 4 * sizeof(FLOAT));
|
|
}
|
|
cursor += 5 * sizeof(DWORD);
|
|
}
|
|
}
|
|
for (i = 0; i < D3DVS_CONSTREG_COUNT_XBOX; ++i)
|
|
{
|
|
if (*dirty++ && i >= 96)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D7_VertexShaderConstants;
|
|
data[0] = i;
|
|
memcpy(data + 1, device->m_VertexShaderConstants[i], 4 * sizeof(FLOAT));
|
|
}
|
|
cursor += 5 * sizeof(DWORD);
|
|
}
|
|
}
|
|
for (i = 0; i < D3DRS_MAX; ++i)
|
|
{
|
|
if (*dirty++)
|
|
{
|
|
if (device->m_pPixelShader || i < D3DRS_PSALPHAINPUTS0 ||
|
|
(i > D3DRS_PSINPUTTEXTURE && i != D3DRS_PSTEXTUREMODES))
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D8_RenderStates;
|
|
data[0] = i;
|
|
data[1] = D3D__RenderState[i];
|
|
}
|
|
cursor += 2 * sizeof(DWORD);
|
|
}
|
|
}
|
|
}
|
|
for (j = 0; j < D3DTSS_MAX; ++j)
|
|
{
|
|
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
|
{
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D9_TextureStates;
|
|
data[0] = i;
|
|
data[1] = j;
|
|
data[2] = D3D__TextureState[i][j];
|
|
}
|
|
cursor += 3 * sizeof(DWORD);
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < D3DTS_MAX; ++i)
|
|
{
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D10_Transforms;
|
|
data[0] = i;
|
|
memcpy(data + 1, &device->m_Transform[i], sizeof(D3DMATRIX));
|
|
}
|
|
cursor += sizeof(DWORD) + sizeof(D3DMATRIX);
|
|
}
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
block->D11_Viewport = TRUE;
|
|
memcpy((void *)cursor, &device->m_Viewport, sizeof(D3DVIEWPORT8));
|
|
}
|
|
cursor += sizeof(D3DVIEWPORT8);
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
block->D12_Material = TRUE;
|
|
memcpy((void *)cursor, &device->m_Material, sizeof(D3DMATERIAL8));
|
|
}
|
|
cursor += sizeof(D3DMATERIAL8);
|
|
}
|
|
if (*dirty++)
|
|
{
|
|
if (block)
|
|
{
|
|
block->D13_BackMaterial = TRUE;
|
|
memcpy((void *)cursor, &device->m_BackMaterial, sizeof(D3DMATERIAL8));
|
|
}
|
|
cursor += sizeof(D3DMATERIAL8);
|
|
}
|
|
for (i = 0; i < device->m_LightCount; ++i)
|
|
{
|
|
if (lights[i].Flags & LIGHT_STATEBLOCK_SET)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D14_Lights;
|
|
data[0] = i;
|
|
/* Original record path copies Light8 from the first light,
|
|
* whereas CaptureStateBlock uses the indexed light. Preserve
|
|
* this observed distinction; do not call it a corrected API. */
|
|
memcpy(data + 1, &lights->Light8, sizeof(D3DLIGHT8));
|
|
}
|
|
cursor += sizeof(DWORD) + sizeof(D3DLIGHT8);
|
|
}
|
|
}
|
|
for (i = 0; i < device->m_LightCount; ++i)
|
|
{
|
|
if (lights[i].Flags & LIGHT_STATEBLOCK_ENABLED)
|
|
{
|
|
if (block)
|
|
{
|
|
DWORD *data = (DWORD *)cursor;
|
|
++block->D15_LightEnables;
|
|
data[0] = i;
|
|
device->GetLightEnable(i, (BOOL *)(data + 1));
|
|
}
|
|
cursor += 2 * sizeof(DWORD);
|
|
}
|
|
}
|
|
if (block)
|
|
{
|
|
*token = (DWORD)block;
|
|
return S_OK;
|
|
}
|
|
block = (StateBlock *)LocalAlloc(LMEM_FIXED, cursor);
|
|
if (!block) return E_OUTOFMEMORY;
|
|
ZeroMemory(block, offsetof(StateBlock, Data));
|
|
cursor = (ULONG_PTR)StateBlockData(block);
|
|
}
|
|
}
|
|
|
|
const BYTE g_PixelRenderStates[] =
|
|
{
|
|
D3DRS_ZENABLE,
|
|
D3DRS_FILLMODE,
|
|
D3DRS_SHADEMODE,
|
|
D3DRS_ZWRITEENABLE,
|
|
D3DRS_ALPHATESTENABLE,
|
|
D3DRS_SRCBLEND,
|
|
D3DRS_DESTBLEND,
|
|
D3DRS_ZFUNC,
|
|
D3DRS_ALPHAREF,
|
|
D3DRS_ALPHAFUNC,
|
|
D3DRS_DITHERENABLE,
|
|
D3DRS_FOGSTART,
|
|
D3DRS_FOGEND,
|
|
D3DRS_FOGDENSITY,
|
|
D3DRS_EDGEANTIALIAS,
|
|
D3DRS_ALPHABLENDENABLE,
|
|
D3DRS_ZBIAS,
|
|
D3DRS_STENCILENABLE,
|
|
D3DRS_STENCILFAIL,
|
|
D3DRS_STENCILZFAIL,
|
|
D3DRS_STENCILPASS,
|
|
D3DRS_STENCILFUNC,
|
|
D3DRS_STENCILREF,
|
|
D3DRS_STENCILMASK,
|
|
D3DRS_STENCILWRITEMASK,
|
|
D3DRS_TEXTUREFACTOR,
|
|
D3DRS_WRAP0,
|
|
D3DRS_WRAP1,
|
|
D3DRS_WRAP2,
|
|
D3DRS_WRAP3,
|
|
D3DRS_COLORWRITEENABLE,
|
|
D3DRS_BLENDOP,
|
|
};
|
|
|
|
const BYTE g_PixelTextureStates[] =
|
|
{
|
|
D3DTSS_COLOROP,
|
|
D3DTSS_COLORARG1,
|
|
D3DTSS_COLORARG2,
|
|
D3DTSS_ALPHAOP,
|
|
D3DTSS_ALPHAARG1,
|
|
D3DTSS_ALPHAARG2,
|
|
D3DTSS_BUMPENVMAT00,
|
|
D3DTSS_BUMPENVMAT01,
|
|
D3DTSS_BUMPENVMAT10,
|
|
D3DTSS_BUMPENVMAT11,
|
|
D3DTSS_TEXCOORDINDEX,
|
|
D3DTSS_ADDRESSU,
|
|
D3DTSS_ADDRESSV,
|
|
D3DTSS_BORDERCOLOR,
|
|
D3DTSS_MAGFILTER,
|
|
D3DTSS_MINFILTER,
|
|
D3DTSS_MIPFILTER,
|
|
D3DTSS_MIPMAPLODBIAS,
|
|
D3DTSS_MAXMIPLEVEL,
|
|
D3DTSS_MAXANISOTROPY,
|
|
D3DTSS_BUMPENVLSCALE,
|
|
D3DTSS_BUMPENVLOFFSET,
|
|
D3DTSS_TEXTURETRANSFORMFLAGS,
|
|
D3DTSS_ADDRESSW,
|
|
D3DTSS_COLORARG0,
|
|
D3DTSS_ALPHAARG0,
|
|
D3DTSS_RESULTARG,
|
|
};
|
|
|
|
const BYTE g_VertexRenderStates[] =
|
|
{
|
|
D3DRS_SHADEMODE,
|
|
D3DRS_SPECULARENABLE,
|
|
D3DRS_CULLMODE,
|
|
D3DRS_FOGENABLE,
|
|
D3DRS_FOGCOLOR,
|
|
D3DRS_FOGTABLEMODE,
|
|
D3DRS_FOGSTART,
|
|
D3DRS_FOGEND,
|
|
D3DRS_FOGDENSITY,
|
|
D3DRS_RANGEFOGENABLE,
|
|
D3DRS_AMBIENT,
|
|
D3DRS_COLORVERTEX,
|
|
D3DRS_LIGHTING,
|
|
D3DRS_NORMALIZENORMALS,
|
|
D3DRS_LOCALVIEWER,
|
|
D3DRS_EMISSIVEMATERIALSOURCE,
|
|
D3DRS_AMBIENTMATERIALSOURCE,
|
|
D3DRS_DIFFUSEMATERIALSOURCE,
|
|
D3DRS_SPECULARMATERIALSOURCE,
|
|
D3DRS_VERTEXBLEND,
|
|
D3DRS_POINTSIZE,
|
|
D3DRS_POINTSIZE_MIN,
|
|
D3DRS_POINTSPRITEENABLE,
|
|
D3DRS_POINTSCALEENABLE,
|
|
D3DRS_POINTSCALE_A,
|
|
D3DRS_POINTSCALE_B,
|
|
D3DRS_POINTSCALE_C,
|
|
D3DRS_MULTISAMPLEANTIALIAS,
|
|
D3DRS_MULTISAMPLEMASK,
|
|
D3DRS_PATCHEDGESTYLE,
|
|
D3DRS_PATCHSEGMENTS,
|
|
D3DRS_POINTSIZE_MAX,
|
|
};
|
|
|
|
const BYTE g_VertexTextureStates[] =
|
|
{
|
|
D3DTSS_TEXCOORDINDEX,
|
|
D3DTSS_TEXTURETRANSFORMFLAGS,
|
|
};
|
|
|
|
extern "C" HRESULT WINAPI D3DDevice_CreateStateBlock(
|
|
D3DSTATEBLOCKTYPE type,
|
|
DWORD *token)
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
CDevice *device = g_pDevice;
|
|
if (type == D3DSBT_ALL)
|
|
{
|
|
memset(D3D__StateBlockDirty, 0xff, sizeof(D3D__StateBlockDirty));
|
|
Light *lights = device->m_pLights;
|
|
for (i = 0; i < device->m_LightCount; ++i)
|
|
{
|
|
if (lights[i].Flags & LIGHT_SET)
|
|
lights[i].Flags |= LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearStateBlockFlags();
|
|
if (type == D3DSBT_PIXELSTATE)
|
|
{
|
|
D3D__StateBlockDirty[D3DSBD_PIXELSHADER] = TRUE;
|
|
memset(D3D__StateBlockDirty + D3DSBD_PIXELSHADERCONSTANTS, 0xff, D3DPS_CONSTREG_MAX_DX8);
|
|
for (i = 0; i < sizeof(g_PixelRenderStates); ++i)
|
|
D3D__StateBlockDirty[D3DSBD_RENDERSTATES + g_PixelRenderStates[i]] = TRUE;
|
|
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
|
for (j = 0; j < sizeof(g_PixelTextureStates); ++j)
|
|
D3D__StateBlockDirty[D3DSBD_TEXTURESTATES + g_PixelTextureStates[j] * D3DTSS_MAXSTAGES + i] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
D3D__StateBlockDirty[D3DSBD_VERTEXSHADER] = TRUE;
|
|
memset(D3D__StateBlockDirty + D3DSBD_VERTEXSHADERCONSTANTS, 0xff, D3DVS_CONSTREG_COUNT_XBOX);
|
|
for (i = 0; i < sizeof(g_VertexRenderStates); ++i)
|
|
D3D__StateBlockDirty[D3DSBD_RENDERSTATES + g_VertexRenderStates[i]] = TRUE;
|
|
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
|
for (j = 0; j < sizeof(g_VertexTextureStates); ++j)
|
|
D3D__StateBlockDirty[D3DSBD_TEXTURESTATES + g_VertexTextureStates[j] * D3DTSS_MAXSTAGES + i] = TRUE;
|
|
Light *lights = device->m_pLights;
|
|
for (i = 0; i < device->m_LightCount; ++i)
|
|
{
|
|
if (lights[i].Flags & LIGHT_SET)
|
|
lights[i].Flags |= LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED;
|
|
}
|
|
}
|
|
}
|
|
return RecordStateBlock(token);
|
|
}
|
|
extern "C" HRESULT WINAPI D3DDevice_EndStateBlock(
|
|
DWORD *token)
|
|
{
|
|
g_pDevice->m_StateFlags &= ~STATE_RECORDBLOCK;
|
|
return RecordStateBlock(token);
|
|
}
|
|
extern "C" void WINAPI D3DDevice_Resume(
|
|
BOOL reset)
|
|
{
|
|
if (reset)
|
|
{
|
|
/* The original Resume path assumes state-block allocation succeeds.
|
|
* This is not a checked recovery path for allocation failure. */
|
|
DWORD token;
|
|
D3DDevice_CreateStateBlock(D3DSBT_ALL, &token);
|
|
D3DDevice_ApplyStateBlock(token);
|
|
D3DDevice_DeleteStateBlock(token);
|
|
}
|
|
return;
|
|
}
|
|
}
|