Cleanup XbState code: Preparing for bug fixes/improvements

This commit is contained in:
Luke Usher 2019-04-03 11:47:32 +01:00
parent f58d3ce6cf
commit ed559e5fd6
3 changed files with 315 additions and 326 deletions

View File

@ -156,10 +156,8 @@ inline D3DBLEND EmuXB2PC_D3DBLEND(X_D3DBLEND Value)
case 0x306: return D3DBLEND_DESTCOLOR;
case 0x307: return D3DBLEND_INVDESTCOLOR;
case 0x308: return D3DBLEND_SRCALPHASAT;
// Unsupported (on host) Xbox Extensions
// TODO: Find a way to implement these: Xbox sets a constant blend colour using D3DRS_BLENDCOLOR
case 0x8001: EmuLogEx(LOG_PREFIX_D3DCVT, LOG_LEVEL::WARNING, "Unsupported Xbox D3DBlend Extension: D3DBLEND_CONSTANTCOLOR"); return D3DBLEND_ONE;
case 0x8002: EmuLogEx(LOG_PREFIX_D3DCVT, LOG_LEVEL::WARNING, "Unsupported Xbox D3DBlend Extension: D3DBLEND_INVCONSTANTCOLOR "); return D3DBLEND_ONE;
case 0x8001:return D3DBLEND_BLENDFACTOR;
case 0x8002:return D3DBLEND_INVBLENDFACTOR;
case 0x8003: EmuLogEx(LOG_PREFIX_D3DCVT, LOG_LEVEL::WARNING, "Unsupported Xbox D3DBlend Extension: D3DBLEND_CONSTANTALPHA"); return D3DBLEND_ONE;
case 0x8004: EmuLogEx(LOG_PREFIX_D3DCVT, LOG_LEVEL::WARNING, "Unsupported Xbox D3DBlend Extension: D3DBLEND_INVCONSTANTALPHA"); return D3DBLEND_ONE;
}

View File

@ -1041,6 +1041,14 @@ constexpr DWORD X_D3DTADDRESS_CLAMP = 3;
constexpr DWORD X_D3DTADDRESS_BORDER = 4;
constexpr DWORD X_D3DTADDRESS_CLAMPTOEDGE = 5;
// X_D3DTEXTUREFILTERTYPE Values
constexpr DWORD X_D3DTEXF_NONE = 0;
constexpr DWORD X_D3DTEXF_POINT = 1;
constexpr DWORD X_D3DTEXF_LINEAR = 2;
constexpr DWORD X_D3DTEXF_ANISOTROPIC = 3;
constexpr DWORD X_D3DTEXF_QUINCUNX = 4; // Xbox extension
constexpr DWORD X_D3DTEXF_GAUSSIANCUBIC = 5;
// X_D3DCLEAR values :
constexpr DWORD X_D3DCLEAR_ZBUFFER = 0x00000001;
constexpr DWORD X_D3DCLEAR_STENCIL = 0x00000002;

View File

@ -38,346 +38,329 @@ extern uint32_t g_BuildVersion;
#include "core\hle\Intercept.hpp" // For g_SymbolAddresses
// ******************************************************************
// * patch: UpdateDeferredStates
// ******************************************************************
void XTL::EmuUpdateDeferredStates()
void VerifyAndFixEmuDeferredRenderStateOffset()
{
using namespace XTL;
// Verify that EmuD3DDeferredRenderState is correct, if not, we can programatically correct it
// We should also flag up a warning so this can be fixed upstream in XboxSymbolDatabase!
// This is made possible by the registration of D3DRS_CULLMODE by XboxSymbolDatabase
static bool verifiedRenderStateOffset = false;
if (!verifiedRenderStateOffset) {
DWORD CullModeOffset = g_SymbolAddresses["D3DRS_CULLMODE"];
// If we found a valid CullMode offset, verify the symbol location
if (CullModeOffset != 0) {
// Calculate index of D3DRS_CULLMODE for this XDK. We start counting from the first deferred state (D3DRS_FOGENABLE)
DWORD CullModeIndex = 0;
for (int i = X_D3DRS_FOGENABLE; i < X_D3DRS_CULLMODE; i++) {
if (DxbxRenderStateInfo[i].V <= g_BuildVersion) {
CullModeIndex++;
}
}
// If the offset was incorrect, calculate the correct offset, log it, and fix it
if ((DWORD)(&EmuD3DDeferredRenderState[CullModeIndex]) != CullModeOffset) {
DWORD CorrectOffset = CullModeOffset - (CullModeIndex * sizeof(DWORD));
EmuLog(LOG_LEVEL::WARNING, "EmuD3DDeferredRenderState returned by XboxSymbolDatabase (0x%08X) was incorrect. Correcting to be 0x%08X.\nPlease file an issue with the XbSymbolDatabase project", EmuD3DDeferredRenderState, CorrectOffset);
EmuD3DDeferredRenderState = (DWORD*)CorrectOffset;
}
} else {
EmuLog(LOG_LEVEL::WARNING, "D3DRS_CULLMODE could not be found. Please update the XbSymbolDatabase submodule");
}
verifiedRenderStateOffset = true;
}
// Certain D3DRS values need to be checked on each Draw[Indexed]Vertices
if(EmuD3DDeferredRenderState != 0)
{
// Loop through all deferred render states
for (unsigned int RenderState = X_D3DRS_FOGENABLE; RenderState <= X_D3DRS_PATCHSEGMENTS; RenderState++) {
// If this render state does not have a PC counterpart, skip it
if (DxbxRenderStateInfo[RenderState].PC == 0) {
continue;
}
uint8_t index = RenderState - X_D3DRS_FOGENABLE;
// Some render states require special handling to convert to host, but most can be mapped 1:1
// We use a switch/case to handle the special states
switch (RenderState) {
case X_D3DRS_WRAP0: {
::DWORD dwConv = 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00000010) ? D3DWRAP_U : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00001000) ? D3DWRAP_V : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00100000) ? D3DWRAP_W : 0;
g_pD3DDevice->SetRenderState(D3DRS_WRAP0, dwConv);
} break;
case X_D3DRS_WRAP1: {
::DWORD dwConv = 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00000010) ? D3DWRAP_U : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00001000) ? D3DWRAP_V : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00100000) ? D3DWRAP_W : 0;
g_pD3DDevice->SetRenderState(D3DRS_WRAP1, dwConv);
} break;
default:
g_pD3DDevice->SetRenderState(DxbxRenderStateInfo[RenderState].PC, EmuD3DDeferredRenderState[index]);
break;
}
}
// Verify that EmuD3DDeferredRenderState is correct, if not, we can programatically correct it
// We should also flag up a warning so this can be fixed upstream in XboxSymbolDatabase!
// This is made possible by the registration of D3DRS_CULLMODE by XboxSymbolDatabase
static bool verifiedRenderStateOffset = false;
if (verifiedRenderStateOffset) {
return;
}
// For below XDK 3948, the actual D3DTSS flags have different values.
int Adjust1 = (g_BuildVersion <= 3948) ? 12 : 0;
int Adjust2 = (g_BuildVersion <= 3948) ? 10 : 0;
verifiedRenderStateOffset = true;
// Certain D3DTS values need to be checked on each Draw[Indexed]Vertices
if(EmuD3DDeferredTextureState != 0)
{
for(int v=0;v<4;v++)
{
::DWORD *pCur = &EmuD3DDeferredTextureState[v*32];
DWORD CullModeOffset = g_SymbolAddresses["D3DRS_CULLMODE"];
if(pCur[0+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[0+Adjust2] == 5)
EmuLog(LOG_LEVEL::WARNING, "ClampToEdge is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_ADDRESSU, pCur[0 + Adjust2]);
// If we found a valid CullMode offset, verify the symbol location
if (CullModeOffset == 0) {
EmuLog(LOG_LEVEL::WARNING, "D3DRS_CULLMODE could not be found. Please update the XbSymbolDatabase submodule");
return;
}
// Calculate index of D3DRS_CULLMODE for this XDK. We start counting from the first deferred state (D3DRS_FOGENABLE)
DWORD CullModeIndex = 0;
for (int i = XTL::X_D3DRS_FOGENABLE; i < XTL::X_D3DRS_CULLMODE; i++) {
if (XTL::DxbxRenderStateInfo[i].V <= g_BuildVersion) {
CullModeIndex++;
}
}
// If the offset was incorrect, calculate the correct offset, log it, and fix it
if ((DWORD)(&XTL::EmuD3DDeferredRenderState[CullModeIndex]) != CullModeOffset) {
DWORD CorrectOffset = CullModeOffset - (CullModeIndex * sizeof(DWORD));
EmuLog(LOG_LEVEL::WARNING, "EmuD3DDeferredRenderState returned by XboxSymbolDatabase (0x%08X) was incorrect. Correcting to be 0x%08X.\nPlease file an issue with the XbSymbolDatabase project", XTL::EmuD3DDeferredRenderState, CorrectOffset);
XTL::EmuD3DDeferredRenderState = (DWORD*)CorrectOffset;
}
}
void UpdateDeferredRenderStates()
{
// Certain D3DRS values need to be checked on each Draw[Indexed]Vertices
if (XTL::EmuD3DDeferredRenderState != 0) {
// Loop through all deferred render states
for (unsigned int RenderState = XTL::X_D3DRS_FOGENABLE; RenderState <= XTL::X_D3DRS_PATCHSEGMENTS; RenderState++) {
// If this render state does not have a PC counterpart, skip it
if (XTL::DxbxRenderStateInfo[RenderState].PC == 0) {
continue;
}
if(pCur[1+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[1+Adjust2] == 5)
EmuLog(LOG_LEVEL::WARNING, "ClampToEdge is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_ADDRESSV, pCur[1 + Adjust2]);
uint8_t index = RenderState - XTL::X_D3DRS_FOGENABLE;
// Some render states require special handling to convert to host, but most can be mapped 1:1
// We use a switch/case to handle the special states
switch (RenderState) {
case XTL::X_D3DRS_WRAP0: {
::DWORD dwConv = 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00000010) ? D3DWRAP_U : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00001000) ? D3DWRAP_V : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00100000) ? D3DWRAP_W : 0;
g_pD3DDevice->SetRenderState(XTL::D3DRS_WRAP0, dwConv);
} break;
case XTL::X_D3DRS_WRAP1: {
::DWORD dwConv = 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00000010) ? D3DWRAP_U : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00001000) ? D3DWRAP_V : 0;
dwConv |= (XTL::EmuD3DDeferredRenderState[index] & 0x00100000) ? D3DWRAP_W : 0;
g_pD3DDevice->SetRenderState(XTL::D3DRS_WRAP1, dwConv);
} break;
default:
g_pD3DDevice->SetRenderState(XTL::DxbxRenderStateInfo[RenderState].PC, XTL::EmuD3DDeferredRenderState[index]);
break;
}
}
}
}
if(pCur[2+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[2+Adjust2] == 5)
EmuLog(LOG_LEVEL::WARNING, "ClampToEdge is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_ADDRESSW, pCur[2 + Adjust2]);
}
if(pCur[3+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[3+Adjust2] == 4)
EmuLog(LOG_LEVEL::WARNING, "QuinCunx is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MAGFILTER, pCur[3 + Adjust2]);
}
if(pCur[4+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[4+Adjust2] == 4)
EmuLog(LOG_LEVEL::WARNING, "QuinCunx is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MINFILTER, pCur[4 + Adjust2]);
}
if(pCur[5+Adjust2] != X_D3DTSS_UNK)
{
if(pCur[5+Adjust2] == 4)
EmuLog(LOG_LEVEL::WARNING, "QuinCunx is unsupported (temporarily)");
else
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MIPFILTER, pCur[5 + Adjust2]);
}
if(pCur[6+Adjust2] != X_D3DTSS_UNK)
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MIPMAPLODBIAS, pCur[6 + Adjust2]);
if(pCur[7+Adjust2] != X_D3DTSS_UNK)
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MAXMIPLEVEL, pCur[7 + Adjust2]);
if(pCur[8+Adjust2] != X_D3DTSS_UNK)
g_pD3DDevice->SetSamplerState(v, D3DSAMP_MAXANISOTROPY, pCur[8 + Adjust2]);
if(pCur[12-Adjust1] != X_D3DTSS_UNK)
{
// TODO: This would be better split into it's own function, or a lookup array
switch (pCur[12 - Adjust1])
{
case X_D3DTOP_DISABLE:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_DISABLE);
break;
case X_D3DTOP_SELECTARG1:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
break;
case X_D3DTOP_SELECTARG2:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
break;
case X_D3DTOP_MODULATE:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATE);
break;
case X_D3DTOP_MODULATE2X:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
break;
case X_D3DTOP_MODULATE4X:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATE4X);
break;
case X_D3DTOP_ADD:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_ADD);
break;
case X_D3DTOP_ADDSIGNED:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
break;
case X_D3DTOP_ADDSIGNED2X:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_ADDSIGNED2X);
break;
case X_D3DTOP_SUBTRACT:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
break;
case X_D3DTOP_ADDSMOOTH:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_ADDSMOOTH);
break;
case X_D3DTOP_BLENDDIFFUSEALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
break;
case X_D3DTOP_BLENDCURRENTALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
break;
case X_D3DTOP_BLENDTEXTUREALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
break;
case X_D3DTOP_BLENDFACTORALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
break;
case X_D3DTOP_BLENDTEXTUREALPHAPM:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHAPM);
break;
case X_D3DTOP_PREMODULATE:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_PREMODULATE);
break;
case X_D3DTOP_MODULATEALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATEALPHA_ADDCOLOR);
break;
case X_D3DTOP_MODULATECOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATECOLOR_ADDALPHA);
break;
case X_D3DTOP_MODULATEINVALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATEINVALPHA_ADDCOLOR);
break;
case X_D3DTOP_MODULATEINVCOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MODULATEINVCOLOR_ADDALPHA);
break;
case X_D3DTOP_DOTPRODUCT3:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
break;
case X_D3DTOP_MULTIPLYADD:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
break;
case X_D3DTOP_LERP:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_LERP);
break;
case X_D3DTOP_BUMPENVMAP:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
break;
case X_D3DTOP_BUMPENVMAPLUMINANCE:
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
break;
default:
EmuLog(LOG_LEVEL::WARNING, "(Temporarily) Unsupported D3DTSS_COLOROP Value (%d)", pCur[12 - Adjust1]);
break;
}
}
if(pCur[13-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLORARG0, pCur[13-Adjust1]);
if(pCur[14-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLORARG1, pCur[14-Adjust1]);
if(pCur[15-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_COLORARG2, pCur[15-Adjust1]);
// TODO: Use a lookup table, this is not always a 1:1 map (same as D3DTSS_COLOROP)
if(pCur[16-Adjust1] != X_D3DTSS_UNK)
{
if(pCur[16-Adjust1] > 12 && pCur[16-Adjust1] != 14 && pCur[16-Adjust1] != 13)
EmuLog(LOG_LEVEL::WARNING, "(Temporarily) Unsupported D3DTSS_ALPHAOP Value (%d)", pCur[16-Adjust1]);
else
if( pCur[16-Adjust1] == 14 )
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAOP, D3DTOP_BLENDTEXTUREALPHA);
if( pCur[16-Adjust1] == 15 )
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAOP, D3DTOP_BLENDFACTORALPHA);
if( pCur[16-Adjust1] == 13 )
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAOP, D3DTOP_BLENDCURRENTALPHA);
else
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAOP, pCur[16-Adjust1]);
}
if(pCur[17-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAARG0, pCur[17-Adjust1]);
if(pCur[18-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAARG1, pCur[18-Adjust1]);
if(pCur[19-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_ALPHAARG2, pCur[19-Adjust1]);
if(pCur[20-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_RESULTARG, pCur[20-Adjust1]);
if(pCur[21-Adjust1] != X_D3DTSS_UNK)
g_pD3DDevice->SetTextureStageState(v, D3DTSS_TEXTURETRANSFORMFLAGS, pCur[21-Adjust1]);
/*if(pCur[29] != X_D3DTSS_UNK) // This is NOT a deferred texture state!
g_pD3DDevice->SetSamplerState(v, D3DSAMP_BORDERCOLOR, pCur[29]);
*/
/** To check for unhandled texture stage state changes
for(int r=0;r<32;r++)
{
static const int unchecked[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 29, 30, 31
};
if(pCur[r] != X_D3DTSS_UNK)
{
bool pass = true;
for(int q=0;q<sizeof(unchecked)/sizeof(int);q++)
{
if(r == unchecked[q])
{
pass = false;
break;
}
}
if(pass)
EmuLog(LOG_LEVEL::WARNING, "Unhandled TextureState Change @ %d->%d", v, r);
}
}
//**/
DWORD GetDeferredTextureStateFromIndex(DWORD State)
{
// On early XDKs, we need to shuffle the values around a little
// TODO: Verify which XDK version this change occurred at
if (g_BuildVersion <= 3948) {
// Values range 0-9 (D3DTSS_COLOROP to D3DTSS_TEXTURETRANSFORMFLAGS) become 12-21
if (State <= 9) {
return State + 12;
}
// if point sprites are enabled, copy stage 3 over to 0
if(EmuD3DDeferredRenderState[26] == TRUE)
{
// pCur = Texture Stage 3 States
::DWORD *pCur = &EmuD3DDeferredTextureState[2*32];
// All Remaining values 10-21 (D3DTSS_ADDRESSU to D3DTSS_ALPHAKILL) become 0-11
return State - 10;
}
IDirect3DBaseTexture *pTexture;
// On later XDKs, the mapping is identical to our representation
return State;
}
// set the point sprites texture
g_pD3DDevice->GetTexture(3, &pTexture);
g_pD3DDevice->SetTexture(0, pTexture);
void UpdateDeferredTextureStates()
{
// Iterate through all deferred texture states/stages
for (int Stage = 0; Stage < XTL::X_D3DTS_STAGECOUNT; Stage++) {
for (int StateIndex = XTL::X_D3DTSS_DEFERRED_FIRST; StateIndex <= XTL::X_D3DTSS_DEFERRED_LAST; StateIndex++) {
// Read the value of the current stage/state from the Xbox data structure
DWORD Value = XTL::EmuD3DDeferredTextureState[(Stage * XTL::X_D3DTS_STAGESIZE) + StateIndex];
// disable all other stages
g_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
// Convert the index of the current state to an index that we can use
// This handles the case when XDKs have different state values
DWORD State = GetDeferredTextureStateFromIndex(StateIndex);
// in that case we have to copy over the stage by hand
for(int v=0;v<30;v++)
{
if(pCur[v] != X_D3DTSS_UNK)
{
::DWORD dwValue;
switch (State) {
case XTL::X_D3DTSS_ADDRESSU: case XTL::X_D3DTSS_ADDRESSV: case XTL::X_D3DTSS_ADDRESSW:
if (Value == XTL::X_D3DTADDRESS_CLAMPTOEDGE) {
EmuLog(LOG_LEVEL::WARNING, "ClampToEdge is unsupported");
break;
}
// For Direct3D9, everything below X_D3DSAMP_MAXANISOTROPY needs to call GetSamplerState / SetSamplerState :
if (v <= X_D3DTSS_MAXANISOTROPY) {
g_pD3DDevice->GetSamplerState(3, (D3DSAMPLERSTATETYPE)v, &dwValue);
g_pD3DDevice->SetSamplerState(0, (D3DSAMPLERSTATETYPE)v, dwValue);
}
else
{
g_pD3DDevice->GetTextureStageState(3, (D3DTEXTURESTAGESTATETYPE)v, &dwValue);
g_pD3DDevice->SetTextureStageState(0, (D3DTEXTURESTAGESTATETYPE)v, dwValue);
}
// These states match the PC counterpart IDs
g_pD3DDevice->SetSamplerState(Stage, (XTL::D3DSAMPLERSTATETYPE)State, Value);
break;
case XTL::X_D3DTSS_MAGFILTER: case XTL::X_D3DTSS_MINFILTER: case XTL::X_D3DTSS_MIPFILTER:
if (Value == XTL::X_D3DTEXF_QUINCUNX) {
EmuLog(LOG_LEVEL::WARNING, "QuinCunx is unsupported");
break;
}
// These states (when incremented by 2) match the PC counterpart IDs
g_pD3DDevice->SetSamplerState(Stage, (XTL::D3DSAMPLERSTATETYPE)(State + 2), Value);
break;
case XTL::X_D3DTSS_MIPMAPLODBIAS:
g_pD3DDevice->SetSamplerState(Stage, XTL::D3DSAMP_MIPMAPLODBIAS, Value);
break;
case XTL::X_D3DTSS_MAXMIPLEVEL:
g_pD3DDevice->SetSamplerState(Stage, XTL::D3DSAMP_MAXMIPLEVEL, Value);
break;
case XTL::X_D3DTSS_MAXANISOTROPY:
g_pD3DDevice->SetSamplerState(Stage, XTL::D3DSAMP_MAXANISOTROPY, Value);
break;
case XTL::X_D3DTSS_COLORKEYOP: // Xbox ext
// Logging Disabled: Causes Dashboard to slow down massively
//EmuLog(LOG_LEVEL::WARNING, "D3DTSS_COLORKEYOP is unsupported");
break;
case XTL::X_D3DTSS_COLORSIGN: // Xbox ext
// Logging Disabled: Causes Dashboard to slow down massively
//EmuLog(LOG_LEVEL::WARNING, "D3DTSS_COLORSIGN is unsupported");
break;
case XTL::X_D3DTSS_ALPHAKILL: // Xbox ext
// Logging Disabled: Causes Dashboard to slow down massively
//EmuLog(LOG_LEVEL::WARNING, "D3DTSS_ALPHAKILL is unsupported");
break;
case XTL::X_D3DTSS_COLOROP:
// TODO: This would be better split into it's own function, or a lookup array
switch (Value) {
case XTL::X_D3DTOP_DISABLE:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_DISABLE);
break;
case XTL::X_D3DTOP_SELECTARG1:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SELECTARG1);
break;
case XTL::X_D3DTOP_SELECTARG2:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SELECTARG2);
break;
case XTL::X_D3DTOP_MODULATE:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE);
break;
case XTL::X_D3DTOP_MODULATE2X:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE2X);
break;
case XTL::X_D3DTOP_MODULATE4X:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE4X);
break;
case XTL::X_D3DTOP_ADD:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADD);
break;
case XTL::X_D3DTOP_ADDSIGNED:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSIGNED);
break;
case XTL::X_D3DTOP_ADDSIGNED2X:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSIGNED2X);
break;
case XTL::X_D3DTOP_SUBTRACT:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SUBTRACT);
break;
case XTL::X_D3DTOP_ADDSMOOTH:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSMOOTH);
break;
case XTL::X_D3DTOP_BLENDDIFFUSEALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDDIFFUSEALPHA);
break;
case XTL::X_D3DTOP_BLENDCURRENTALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDCURRENTALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDTEXTUREALPHA);
break;
case XTL::X_D3DTOP_BLENDFACTORALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDFACTORALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHAPM:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDTEXTUREALPHAPM);
break;
case XTL::X_D3DTOP_PREMODULATE:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_PREMODULATE);
break;
case XTL::X_D3DTOP_MODULATEALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATECOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATECOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_MODULATEINVALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEINVALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATEINVCOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEINVCOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_DOTPRODUCT3:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_DOTPRODUCT3);
break;
case XTL::X_D3DTOP_MULTIPLYADD:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MULTIPLYADD);
break;
case XTL::X_D3DTOP_LERP:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_LERP);
break;
case XTL::X_D3DTOP_BUMPENVMAP:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BUMPENVMAP);
break;
case XTL::X_D3DTOP_BUMPENVMAPLUMINANCE:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BUMPENVMAPLUMINANCE);
break;
default:
EmuLog(LOG_LEVEL::WARNING, "Unsupported D3DTSS_COLOROP Value (%d)", Value);
break;
}
break;
case XTL::X_D3DTSS_COLORARG0:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLORARG0, Value);
break;
case XTL::X_D3DTSS_COLORARG1:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLORARG1, Value);
break;
case XTL::X_D3DTSS_COLORARG2:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_COLORARG2, Value);
break;
case XTL::X_D3DTSS_ALPHAOP:
// TODO: Use a lookup table, this is not always a 1:1 map (same as D3DTSS_COLOROP)
if (Value != X_D3DTSS_UNK) {
if (Value > XTL::X_D3DTOP_BLENDDIFFUSEALPHA && Value != XTL::X_D3DTOP_BLENDTEXTUREALPHA && Value != XTL::X_D3DTOP_BLENDCURRENTALPHA) {
EmuLog(LOG_LEVEL::WARNING, "Unsupported D3DTSS_ALPHAOP Value (%d)", Value);
} else if (Value == XTL::X_D3DTOP_BLENDTEXTUREALPHA) {
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDTEXTUREALPHA);
}
if (Value == XTL::X_D3DTOP_BLENDFACTORALPHA) {
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDFACTORALPHA);
}
if (Value == XTL::X_D3DTOP_BLENDCURRENTALPHA) {
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDCURRENTALPHA);
} else {
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAOP, Value);
}
}
break;
case XTL::X_D3DTSS_ALPHAARG0:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAARG0, Value);
break;
case XTL::X_D3DTSS_ALPHAARG1:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAARG1, Value);
break;
case XTL::X_D3DTSS_ALPHAARG2:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_ALPHAARG2, Value);
break;
case XTL::X_D3DTSS_RESULTARG:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_RESULTARG, Value);
break;
case XTL::X_D3DTSS_TEXTURETRANSFORMFLAGS:
g_pD3DDevice->SetTextureStageState(Stage, XTL::D3DTSS_TEXTURETRANSFORMFLAGS, Value);
break;
default:
EmuLog(LOG_LEVEL::WARNING, "Unkown Xbox D3DTSS Value: %d", State);
break;
}
}
}
// if point sprites are enabled, copy stage 3 over to 0
// TODO: Verify/Fix this, it doesn't seem right (It calls host functions using Xbox indexes)
if (XTL::EmuD3DDeferredRenderState[XTL::X_D3DRS_POINTSPRITEENABLE - XTL::X_D3DRS_FOGENABLE] == TRUE) {
// Get a pointer to Stage 3
DWORD *pCur = &XTL::EmuD3DDeferredTextureState[2 * XTL::X_D3DTS_STAGESIZE];
XTL::IDirect3DBaseTexture *pTexture;
// set the point sprites texture
g_pD3DDevice->GetTexture(3, &pTexture);
g_pD3DDevice->SetTexture(0, pTexture);
// disable all other stages
g_pD3DDevice->SetTextureStageState(1, XTL::D3DTSS_COLOROP, XTL::D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_DISABLE);
for (int v = 0; v < 30; v++) {
if (pCur[v] != X_D3DTSS_UNK) {
DWORD dwValue = 0;
// For Direct3D9, everything below X_D3DSAMP_MAXANISOTROPY needs to call GetSamplerState / SetSamplerState :
if (v <= XTL::X_D3DTSS_MAXANISOTROPY) {
g_pD3DDevice->GetSamplerState(3, (XTL::D3DSAMPLERSTATETYPE)v, &dwValue);
g_pD3DDevice->SetSamplerState(0, (XTL::D3DSAMPLERSTATETYPE)v, dwValue);
} else {
g_pD3DDevice->GetTextureStageState(3, (XTL::D3DTEXTURESTAGESTATETYPE)v, &dwValue);
g_pD3DDevice->SetTextureStageState(0, (XTL::D3DTEXTURESTAGESTATETYPE)v, dwValue);
}
}
}
}
}
// ******************************************************************
// * patch: UpdateDeferredStates
// ******************************************************************
void XTL::EmuUpdateDeferredStates()
{
VerifyAndFixEmuDeferredRenderStateOffset();
UpdateDeferredRenderStates();
UpdateDeferredTextureStates();
}