Merge pull request #1578 from LukeUsher/fix-render-texture-states

Minor Cleanup of Render State and Texture State handling
This commit is contained in:
PatrickvL 2019-04-07 13:07:05 +02:00 committed by GitHub
commit 13daf887c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 622 additions and 635 deletions

View File

@ -195,10 +195,12 @@ bool Settings::Init()
int iRet = MessageBox(nullptr, szSettings_save_user_option_message, "Cxbx-Reloaded", MB_YESNOCANCEL | MB_ICONQUESTION);
if (iRet == IDYES) {
saveFile = GenerateExecDirectoryStr();
saveFile = GenerateExecDirectoryStr();
m_gui.DataStorageToggle = CXBX_DATA_EXECDIR;
}
else if (iRet == IDNO){
saveFile = GenerateUserProfileDirectoryStr();
saveFile = GenerateUserProfileDirectoryStr();
m_gui.DataStorageToggle = CXBX_DATA_APPDATA;
if (saveFile.size() == 0) {
return false;
}
@ -221,7 +223,7 @@ bool Settings::Init()
saveFile.append(szSettings_settings_file);
// Call LoadConfig, this will load the config, applying defaults for any missing fields
bRet = LoadConfig();
bRet = LoadConfig();
if (!bRet) {
MessageBox(nullptr, szSettings_setup_error, "Cxbx-Reloaded", MB_OK);
@ -293,7 +295,7 @@ bool Settings::LoadConfig()
m_gui.szCxbxDebugFile = si_data;
}
m_gui.DataStorageToggle = m_si.GetLongValue(section_gui, sect_gui_keys.DataStorageToggle, /*Default=*/CXBX_DATA_APPDATA);
m_gui.DataStorageToggle = m_si.GetLongValue(section_gui, sect_gui_keys.DataStorageToggle, /*Default=*/m_gui.DataStorageToggle);
si_data = m_si.GetValue(section_gui, sect_gui_keys.DataCustomLocation, /*Default=*/nullptr);
// Fallback to null string if value is empty or contains a bigger string.
if (si_data == nullptr || std::strlen(si_data) >= MAX_PATH) {

View File

@ -6006,213 +6006,158 @@ VOID __fastcall XTL::EMUPATCH(D3DDevice_SetRenderState_Simple)
(
DWORD Method,
DWORD Value
)
)
{
LOG_FUNC_BEGIN
LOG_FUNC_ARG(Method)
LOG_FUNC_ARG(Value)
LOG_FUNC_END;
LOG_FUNC_BEGIN
LOG_FUNC_ARG(Method)
LOG_FUNC_ARG(Value)
LOG_FUNC_END;
XB_trampoline(VOID, __fastcall, D3DDevice_SetRenderState_Simple, (DWORD, DWORD));
XB_D3DDevice_SetRenderState_Simple(Method, Value);
XB_trampoline(VOID, __fastcall, D3DDevice_SetRenderState_Simple, (DWORD, DWORD));
XB_D3DDevice_SetRenderState_Simple(Method, Value);
// Special Case: Handle PixelShader related Render States
// TODO: Port over EmuMappedD3DRenderState and related code from Dxbx or Wip_LessVertexPatching
// After this, we don't need to do this part anymore
switch (Method & 0x00001FFC) {
case NV2A_RC_IN_ALPHA(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS0] = Value; return;
case NV2A_RC_IN_ALPHA(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS1] = Value; return;
case NV2A_RC_IN_ALPHA(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS2] = Value; return;
case NV2A_RC_IN_ALPHA(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS3] = Value; return;
case NV2A_RC_IN_ALPHA(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS4] = Value; return;
case NV2A_RC_IN_ALPHA(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS5] = Value; return;
case NV2A_RC_IN_ALPHA(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS6] = Value; return;
case NV2A_RC_IN_ALPHA(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS7] = Value; return;
case NV2A_RC_FINAL0: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERINPUTSABCD] = Value; return;
case NV2A_RC_FINAL1: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERINPUTSEFG] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_0] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_1] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_2] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_3] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_4] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_5] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_6] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_7] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_0] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_1] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_2] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_3] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_4] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_5] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_6] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_7] = Value; return;
case NV2A_RC_OUT_ALPHA(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS0] = Value; return;
case NV2A_RC_OUT_ALPHA(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS1] = Value; return;
case NV2A_RC_OUT_ALPHA(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS2] = Value; return;
case NV2A_RC_OUT_ALPHA(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS3] = Value; return;
case NV2A_RC_OUT_ALPHA(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS4] = Value; return;
case NV2A_RC_OUT_ALPHA(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS5] = Value; return;
case NV2A_RC_OUT_ALPHA(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS6] = Value; return;
case NV2A_RC_OUT_ALPHA(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS7] = Value; return;
case NV2A_RC_IN_RGB(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS0] = Value; return;
case NV2A_RC_IN_RGB(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS1] = Value; return;
case NV2A_RC_IN_RGB(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS2] = Value; return;
case NV2A_RC_IN_RGB(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS3] = Value; return;
case NV2A_RC_IN_RGB(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS4] = Value; return;
case NV2A_RC_IN_RGB(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS5] = Value; return;
case NV2A_RC_IN_RGB(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS6] = Value; return;
case NV2A_RC_IN_RGB(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS7] = Value; return;
case NV2A_TX_SHADER_CULL_MODE: TemporaryPixelShaderRenderStates[X_D3DRS_PSCOMPAREMODE] = Value; return;
case NV2A_RC_COLOR0: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERCONSTANT0] = Value; return;
case NV2A_RC_COLOR1: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERCONSTANT1] = Value; return;
case NV2A_RC_OUT_RGB(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS0] = Value; return;
case NV2A_RC_OUT_RGB(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS1] = Value; return;
case NV2A_RC_OUT_RGB(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS2] = Value; return;
case NV2A_RC_OUT_RGB(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS3] = Value; return;
case NV2A_RC_OUT_RGB(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS4] = Value; return;
case NV2A_RC_OUT_RGB(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS5] = Value; return;
case NV2A_RC_OUT_RGB(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS6] = Value; return;
case NV2A_RC_OUT_RGB(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS7] = Value; return;
case NV2A_RC_ENABLE: TemporaryPixelShaderRenderStates[X_D3DRS_PSCOMBINERCOUNT] = Value; return;
case NV2A_NOP: TemporaryPixelShaderRenderStates[X_D3DRS_PS_RESERVED] = Value; return; // Dxbx note : This takes the slot of X_D3DPIXELSHADERDEF.PSTextureModes, set by D3DDevice_SetRenderState_LogicOp?
case NV2A_TX_SHADER_DOTMAPPING: TemporaryPixelShaderRenderStates[X_D3DRS_PSDOTMAPPING] = Value; return;
case NV2A_TX_SHADER_PREVIOUS: TemporaryPixelShaderRenderStates[X_D3DRS_PSINPUTTEXTURE] = Value; return;
}
// Special Case: Handle PixelShader related Render States
// TODO: Port over EmuMappedD3DRenderState and related code from Dxbx or Wip_LessVertexPatching
// After this, we don't need to do this part anymore
switch (Method & 0x00001FFC) {
case NV2A_RC_IN_ALPHA(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS0] = Value; return;
case NV2A_RC_IN_ALPHA(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS1] = Value; return;
case NV2A_RC_IN_ALPHA(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS2] = Value; return;
case NV2A_RC_IN_ALPHA(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS3] = Value; return;
case NV2A_RC_IN_ALPHA(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS4] = Value; return;
case NV2A_RC_IN_ALPHA(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS5] = Value; return;
case NV2A_RC_IN_ALPHA(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS6] = Value; return;
case NV2A_RC_IN_ALPHA(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAINPUTS7] = Value; return;
case NV2A_RC_FINAL0: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERINPUTSABCD] = Value; return;
case NV2A_RC_FINAL1: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERINPUTSEFG] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_0] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_1] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_2] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_3] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_4] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_5] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_6] = Value; return;
case NV2A_RC_CONSTANT_COLOR0(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT0_7] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_0] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_1] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_2] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_3] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_4] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_5] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_6] = Value; return;
case NV2A_RC_CONSTANT_COLOR1(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSCONSTANT1_7] = Value; return;
case NV2A_RC_OUT_ALPHA(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS0] = Value; return;
case NV2A_RC_OUT_ALPHA(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS1] = Value; return;
case NV2A_RC_OUT_ALPHA(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS2] = Value; return;
case NV2A_RC_OUT_ALPHA(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS3] = Value; return;
case NV2A_RC_OUT_ALPHA(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS4] = Value; return;
case NV2A_RC_OUT_ALPHA(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS5] = Value; return;
case NV2A_RC_OUT_ALPHA(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS6] = Value; return;
case NV2A_RC_OUT_ALPHA(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSALPHAOUTPUTS7] = Value; return;
case NV2A_RC_IN_RGB(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS0] = Value; return;
case NV2A_RC_IN_RGB(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS1] = Value; return;
case NV2A_RC_IN_RGB(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS2] = Value; return;
case NV2A_RC_IN_RGB(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS3] = Value; return;
case NV2A_RC_IN_RGB(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS4] = Value; return;
case NV2A_RC_IN_RGB(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS5] = Value; return;
case NV2A_RC_IN_RGB(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS6] = Value; return;
case NV2A_RC_IN_RGB(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBINPUTS7] = Value; return;
case NV2A_TX_SHADER_CULL_MODE: TemporaryPixelShaderRenderStates[X_D3DRS_PSCOMPAREMODE] = Value; return;
case NV2A_RC_COLOR0: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERCONSTANT0] = Value; return;
case NV2A_RC_COLOR1: TemporaryPixelShaderRenderStates[X_D3DRS_PSFINALCOMBINERCONSTANT1] = Value; return;
case NV2A_RC_OUT_RGB(0): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS0] = Value; return;
case NV2A_RC_OUT_RGB(1): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS1] = Value; return;
case NV2A_RC_OUT_RGB(2): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS2] = Value; return;
case NV2A_RC_OUT_RGB(3): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS3] = Value; return;
case NV2A_RC_OUT_RGB(4): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS4] = Value; return;
case NV2A_RC_OUT_RGB(5): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS5] = Value; return;
case NV2A_RC_OUT_RGB(6): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS6] = Value; return;
case NV2A_RC_OUT_RGB(7): TemporaryPixelShaderRenderStates[X_D3DRS_PSRGBOUTPUTS7] = Value; return;
case NV2A_RC_ENABLE: TemporaryPixelShaderRenderStates[X_D3DRS_PSCOMBINERCOUNT] = Value; return;
case NV2A_NOP: TemporaryPixelShaderRenderStates[X_D3DRS_PS_RESERVED] = Value; return; // Dxbx note : This takes the slot of X_D3DPIXELSHADERDEF.PSTextureModes, set by D3DDevice_SetRenderState_LogicOp?
case NV2A_TX_SHADER_DOTMAPPING: TemporaryPixelShaderRenderStates[X_D3DRS_PSDOTMAPPING] = Value; return;
case NV2A_TX_SHADER_PREVIOUS: TemporaryPixelShaderRenderStates[X_D3DRS_PSINPUTTEXTURE] = Value; return;
}
// Fallback to non-shader render state handling
int State = -1;
// Todo: make this faster and more elegant
for (int v = 0; v<174; v++)
{
if (EmuD3DRenderStateSimpleEncoded[v] == Method)
{
State = v;
break;
}
}
if (State == -1) {
// Attempt to determine renderstate name for unsupported types
std::string name = "Unknown";
for (int i = 0; i <= X_D3DRS_DONOTCULLUNCOMPRESSED; i++) {
if (DxbxRenderStateInfo[i].M == (Method & 0x00001FFC)) {
name = DxbxRenderStateInfo[i].S;
break;
}
}
EmuLog(LOG_LEVEL::WARNING, "RenderState_Simple(0x%.08X (%s), 0x%.08X) is unsupported!", Method, name.c_str(), Value);
}
else
{
switch(State)
{
case D3DRS_COLORWRITEENABLE:
{
DWORD OrigValue = Value;
Value = 0;
if(OrigValue & (1L<<16))
Value |= D3DCOLORWRITEENABLE_RED;
if(OrigValue & (1L<<8))
Value |= D3DCOLORWRITEENABLE_GREEN;
if(OrigValue & (1L<<0))
Value |= D3DCOLORWRITEENABLE_BLUE;
if(OrigValue & (1L<<24))
Value |= D3DCOLORWRITEENABLE_ALPHA;
DBG_PRINTF("D3DRS_COLORWRITEENABLE := 0x%.08X\n", Value);
}
// Fetch the RenderState conversion info for the given input
int XboxRenderStateIndex = -1;
for (int i = 0; i <= X_D3DRS_DONOTCULLUNCOMPRESSED; i++) {
if (DxbxRenderStateInfo[i].M == (Method & 0x00001FFC)) {
XboxRenderStateIndex = i;
break;
}
}
case D3DRS_SHADEMODE:
Value = EmuXB2PC_D3DSHADEMODE(Value);
DBG_PRINTF("D3DRS_SHADEMODE := 0x%.08X\n", Value);
break;
// If we could not map it, log and return
if (XboxRenderStateIndex == -1) {
EmuLog(LOG_LEVEL::WARNING, "RenderState_Simple(0x%.08X (%s), 0x%.08X) could not be found in RenderState table", Method, DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
return;
}
case D3DRS_BLENDOP:
Value = EmuXB2PC_D3DBLENDOP(Value);
DBG_PRINTF("D3DRS_BLENDOP := 0x%.08X\n", Value);
break;
DBG_PRINTF("RenderState_Simple: %s = 0x%08X", DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
case D3DRS_SRCBLEND:
Value = EmuXB2PC_D3DBLEND(Value);
DBG_PRINTF("D3DRS_SRCBLEND := 0x%.08X\n", Value);
break;
// Perform Conversion
switch (XboxRenderStateIndex) {
case X_D3DRS_COLORWRITEENABLE: {
DWORD OrigValue = Value;
Value = 0;
case D3DRS_DESTBLEND:
Value = EmuXB2PC_D3DBLEND(Value);
DBG_PRINTF("D3DRS_DESTBLEND := 0x%.08X\n", Value);
break;
if (OrigValue & (1L << 16)) {
Value |= D3DCOLORWRITEENABLE_RED;
}
case D3DRS_ZFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DBG_PRINTF("D3DRS_ZFUNC := 0x%.08X\n", Value);
break;
if (OrigValue & (1L << 8)) {
Value |= D3DCOLORWRITEENABLE_GREEN;
}
case D3DRS_ALPHAFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DBG_PRINTF("D3DRS_ALPHAFUNC := 0x%.08X\n", Value);
break;
if (OrigValue & (1L << 0)) {
Value |= D3DCOLORWRITEENABLE_BLUE;
}
case D3DRS_ALPHATESTENABLE:
DBG_PRINTF("D3DRS_ALPHATESTENABLE := 0x%.08X\n", Value);
break;
if (OrigValue & (1L << 24)) {
Value |= D3DCOLORWRITEENABLE_ALPHA;
}
} break;
case X_D3DRS_SHADEMODE:
Value = EmuXB2PC_D3DSHADEMODE(Value);
break;
case X_D3DRS_BLENDOP:
Value = EmuXB2PC_D3DBLENDOP(Value);
break;
case X_D3DRS_SRCBLEND:
case X_D3DRS_DESTBLEND:
Value = EmuXB2PC_D3DBLEND(Value);
break;
case X_D3DRS_ZFUNC:
case X_D3DRS_ALPHAFUNC:
case X_D3DRS_STENCILFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
break;
case X_D3DRS_STENCILZFAIL:
case X_D3DRS_STENCILPASS:
Value = EmuXB2PC_D3DSTENCILOP(Value);
break;
case X_D3DRS_SWATHWIDTH:
// X_D3DRS_SWATHWIDTH safely ignored as it has no visible behavior:
// It simply changes the fill-rate for performance tweaking
// Just log and return
EmuLog(LOG_LEVEL::DEBUG, "RenderState_Simple(0x%.08X (%s), 0x%.08X) was ignored!", Method, DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
return;
case X_D3DRS_ALPHATESTENABLE: case X_D3DRS_ALPHABLENDENABLE:
case X_D3DRS_ALPHAREF: case X_D3DRS_ZWRITEENABLE:
case X_D3DRS_DITHERENABLE: case X_D3DRS_STENCILREF:
case X_D3DRS_STENCILMASK: case X_D3DRS_STENCILWRITEMASK:
// These render states require no conversion, so we simply
// allow SetRenderState to be called with no changes
break;
default:
// RenderState is unsupported/unimplemented, report and return
EmuLog(LOG_LEVEL::WARNING, "RenderState_Simple(0x%.08X (%s), 0x%.08X) is unsupported!", Method, DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
return;
}
case D3DRS_ALPHABLENDENABLE:
DBG_PRINTF("D3DRS_ALPHABLENDENABLE := 0x%.08X\n", Value);
break;
case D3DRS_ALPHAREF:
DBG_PRINTF("D3DRS_ALPHAREF := %lf\n", DWtoF(Value));
break;
case D3DRS_ZWRITEENABLE:
DBG_PRINTF("D3DRS_ZWRITEENABLE := 0x%.08X\n", Value);
break;
case D3DRS_DITHERENABLE:
DBG_PRINTF("D3DRS_DITHERENABLE := 0x%.08X\n", Value);
break;
case D3DRS_STENCILZFAIL:
Value = EmuXB2PC_D3DSTENCILOP(Value);
DBG_PRINTF("D3DRS_STENCILZFAIL := 0x%.08X\n", Value);
break;
case D3DRS_STENCILPASS:
Value = EmuXB2PC_D3DSTENCILOP(Value);
DBG_PRINTF("D3DRS_STENCILPASS := 0x%.08X\n", Value);
break;
case D3DRS_STENCILFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DBG_PRINTF("D3DRS_STENCILFUNC := 0x%.08X\n", Value);
break;
case D3DRS_STENCILREF:
DBG_PRINTF("D3DRS_STENCILREF := 0x%.08X\n", Value);
break;
case D3DRS_STENCILMASK:
DBG_PRINTF("D3DRS_STENCILMASK := 0x%.08X\n", Value);
break;
case D3DRS_STENCILWRITEMASK:
DBG_PRINTF("D3DRS_STENCILWRITEMASK := 0x%.08X\n", Value);
break;
default:
CxbxKrnlCleanup("Unsupported RenderState (0x%.08X)", State);
break;
};
// TODO: verify these params as you add support for them!
HRESULT hRet = g_pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)State, Value);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState");
}
HRESULT hRet = g_pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)(DxbxRenderStateInfo[XboxRenderStateIndex].PC), Value);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState");
}
// ******************************************************************

View File

@ -1215,101 +1215,6 @@ XTL::D3DPRIMITIVETYPE XTL::EmuPrimitiveTypeLookup[] =
/* D3DPT_MAX = 11, */ (XTL::D3DPRIMITIVETYPE)11
};
// render state conversion table
CONST DWORD XTL::EmuD3DRenderStateSimpleEncoded[174] =
{
// WARNING: This lookup table strongly binds us to an SDK with these
// specific #define values for D3DRS_*. Make VERY sure that you have
// the correct lookup values;
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 0
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 2
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 4
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 6
X_D3DRSSE_UNK, 0x0004037c, // 8 - , D3DRS_SHADEMODE
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 10
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 12
0x0004035c, 0x00040300, // 14 - D3DRS_ZWRITEENABLE, D3DRS_ALPHATESTENABLE
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 16
X_D3DRSSE_UNK, 0x00040344, // 18 - , D3DRS_SRCBLEND
0x00040348, X_D3DRSSE_UNK, // 20 - D3DRS_DESTBLEND
X_D3DRSSE_UNK, 0x00040354, // 22 - , D3DRS_ZFUNC
0x00040340, 0x0004033c, // 24 - D3DRS_ALPHAREF, D3DRS_ALPHAFUNC
0x00040310, 0x00040304, // 26 - D3DRS_DITHERENABLE, D3DRS_ALPHABLENDENABLE
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 28
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 30
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 32
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 34
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 36
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 38
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 40
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 42
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 44
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 46
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 48
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 50
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 52
0x00040374, 0x00040378, // 54 - D3DRS_STENCILZFAIL, D3DRS_STENCILPASS
0x00040364, 0x00040368, // 56 - D3DRS_STENCILFUNC, D3DRS_STENCILREF
0x0004036c, 0x00040360, // 58 - D3DRS_STENCILMASK, D3DRS_STENCILWRITEMASK
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 60
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 62
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 64
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 66
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 68
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 70
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 72
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 74
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 76
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 78
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 80
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 82
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 84
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 86
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 88
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 90
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 92
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 94
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 96
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 98
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 100
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 102
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 104
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 106
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 108
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 110
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 112
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 114
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 116
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 118
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 120
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 122
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 124
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 126
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 128
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 130
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 132
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 134
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 136
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 138
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 140
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 142
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 144
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 146
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 148
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 150
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 152
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 154
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 156
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 158
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 160
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 162
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 164
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 166
0x00040358, X_D3DRSSE_UNK, // 168 - D3DRS_COLORWRITEENABLE
X_D3DRSSE_UNK, 0x00040350, // 170
X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 172
};
void XTL::EmuUnswizzleBox
(
CONST PVOID pSrcBuff,

View File

@ -35,7 +35,6 @@
// simple render state encoding lookup table
#define X_D3DRSSE_UNK 0x7fffffff
extern CONST DWORD EmuD3DRenderStateSimpleEncoded[174];
typedef void(*FormatToARGBRow)(const uint8_t* src, uint8_t* dst_argb, int width);
@ -156,10 +155,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; // Maps Xbox D3DBLEND_CONSTANTCOLOR
case 0x8002:return D3DBLEND_INVBLENDFACTOR; // Maps Xbox D3DBLEND_INVCONSTANTCOLOR
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,476 @@ extern uint32_t g_BuildVersion;
#include "core\hle\Intercept.hpp" // For g_SymbolAddresses
void VerifyAndFixEmuDeferredRenderStateOffset()
{
// 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;
}
verifiedRenderStateOffset = true;
DWORD CullModeOffset = g_SymbolAddresses["D3DRS_CULLMODE"];
// 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_PRESENTATIONINTERVAL; RenderState++) {
uint8_t index = RenderState - XTL::X_D3DRS_FOGENABLE;
DWORD Value = XTL::EmuD3DDeferredRenderState[index];
// Convert from Xbox Data Formats to PC
switch (RenderState) {
case XTL::X_D3DRS_FOGENABLE:
case XTL::X_D3DRS_FOGTABLEMODE:
case XTL::X_D3DRS_FOGSTART:
case XTL::X_D3DRS_FOGEND:
case XTL::X_D3DRS_FOGDENSITY:
case XTL::X_D3DRS_RANGEFOGENABLE:
case XTL::X_D3DRS_LIGHTING:
case XTL::X_D3DRS_SPECULARENABLE:
case XTL::X_D3DRS_LOCALVIEWER:
case XTL::X_D3DRS_COLORVERTEX:
case XTL::X_D3DRS_SPECULARMATERIALSOURCE:
case XTL::X_D3DRS_DIFFUSEMATERIALSOURCE:
case XTL::X_D3DRS_AMBIENTMATERIALSOURCE:
case XTL::X_D3DRS_EMISSIVEMATERIALSOURCE:
case XTL::X_D3DRS_AMBIENT:
case XTL::X_D3DRS_POINTSIZE:
case XTL::X_D3DRS_POINTSIZE_MIN:
case XTL::X_D3DRS_POINTSPRITEENABLE:
case XTL::X_D3DRS_POINTSCALEENABLE:
case XTL::X_D3DRS_POINTSCALE_A:
case XTL::X_D3DRS_POINTSCALE_B:
case XTL::X_D3DRS_POINTSCALE_C:
case XTL::X_D3DRS_POINTSIZE_MAX:
case XTL::X_D3DRS_PATCHEDGESTYLE:
case XTL::X_D3DRS_PATCHSEGMENTS:
// These render states require no conversion, so we can use them as-is
break;
case XTL::X_D3DRS_BACKSPECULARMATERIALSOURCE:
case XTL::X_D3DRS_BACKDIFFUSEMATERIALSOURCE:
case XTL::X_D3DRS_BACKAMBIENTMATERIALSOURCE:
case XTL::X_D3DRS_BACKEMISSIVEMATERIALSOURCE:
case XTL::X_D3DRS_BACKAMBIENT:
case XTL::X_D3DRS_SWAPFILTER:
case XTL::X_D3DRS_PRESENTATIONINTERVAL:
// These render states are unsupported by the host, so we skip them entirely
continue;
case XTL::X_D3DRS_WRAP0:
case XTL::X_D3DRS_WRAP1:
case XTL::X_D3DRS_WRAP2:
case XTL::X_D3DRS_WRAP3: {
DWORD OldValue = Value;
Value = 0;
Value |= (OldValue & 0x00000010) ? D3DWRAPCOORD_0 : 0;
Value |= (OldValue & 0x00001000) ? D3DWRAPCOORD_1 : 0;
Value |= (OldValue & 0x00100000) ? D3DWRAPCOORD_2 : 0;
Value |= (OldValue & 0x01000000) ? D3DWRAPCOORD_3 : 0;
} break;
default:
EmuLog(LOG_LEVEL::WARNING, "Unimplemented Deferred Render State: %s", XTL::DxbxRenderStateInfo[RenderState].S);
continue;
}
if (XTL::DxbxRenderStateInfo[RenderState].PC == 0) {
continue;
}
g_pD3DDevice->SetRenderState(XTL::DxbxRenderStateInfo[RenderState].PC, Value);
}
}
}
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;
}
// All Remaining values 10-21 (D3DTSS_ADDRESSU to D3DTSS_ALPHAKILL) become 0-11
return State - 10;
}
// On later XDKs, the mapping is identical to our representation
return State;
}
DWORD Map3911ToCxbxD3DTOP(DWORD Value)
{
switch (Value) {
case 1: return XTL::X_D3DTOP_DISABLE;
case 2: return XTL::X_D3DTOP_SELECTARG1;
case 3: return XTL::X_D3DTOP_SELECTARG2;
case 4: return XTL::X_D3DTOP_MODULATE;
case 5: return XTL::X_D3DTOP_MODULATE2X;
case 6: return XTL::X_D3DTOP_MODULATE4X;
case 7: return XTL::X_D3DTOP_ADD;
case 8: return XTL::X_D3DTOP_ADDSIGNED;
case 9: return XTL::X_D3DTOP_ADDSIGNED2X;
case 10: return XTL::X_D3DTOP_SUBTRACT;
case 11: return XTL::X_D3DTOP_ADDSMOOTH;
case 12: return XTL::X_D3DTOP_BLENDDIFFUSEALPHA;
case 13: return XTL::X_D3DTOP_BLENDTEXTUREALPHA;
case 14: return XTL::X_D3DTOP_BLENDFACTORALPHA;
case 15: return XTL::X_D3DTOP_BLENDTEXTUREALPHAPM;
case 16: return XTL::X_D3DTOP_BLENDCURRENTALPHA;
case 17: return XTL::X_D3DTOP_PREMODULATE;
case 18: return XTL::X_D3DTOP_MODULATEALPHA_ADDCOLOR;
case 19: return XTL::X_D3DTOP_MODULATECOLOR_ADDALPHA;
case 20: return XTL::X_D3DTOP_MODULATEINVALPHA_ADDCOLOR;
case 21: return XTL::X_D3DTOP_MODULATEINVCOLOR_ADDALPHA;
case 22: return XTL::X_D3DTOP_BUMPENVMAP;
case 23: return XTL::X_D3DTOP_BUMPENVMAPLUMINANCE;
case 24: return XTL::X_D3DTOP_DOTPRODUCT3;
case 25: return XTL::X_D3DTOP_MULTIPLYADD;
case 26: return XTL::X_D3DTOP_LERP;
}
EmuLog(LOG_LEVEL::WARNING, "Unknown X_D3DTOP Value");
return Value;
}
DWORD TranslateXDKSpecificD3DTOP(DWORD Value)
{
// TODO: Determine when exactly these values changed
// So far, 4134 is the earliest version we've seen using these mappings
// But this may change
if (g_BuildVersion >= 4134) {
// For these XDKs, the mapping has been confirmed to match our internal mapping
return Value;
}
return Map3911ToCxbxD3DTOP(Value);
}
void UpdateDeferredTextureStates()
{
// Iterate through all deferred texture states/stages
// Track if we need to overwrite state 0 with 3 because of Point Sprites
// The Xbox NV2A uses only Stage 3 for point-sprites, so we emulate this
// by mapping Stage 3 to Stage 0, and disabling all stages > 0
bool pointSpriteOverride = false;
if (XTL::EmuD3DDeferredRenderState[XTL::X_D3DRS_POINTSPRITEENABLE - XTL::X_D3DRS_FOGENABLE] == TRUE) {
pointSpriteOverride = true;
}
for (int XboxStage = 0; XboxStage < XTL::X_D3DTS_STAGECOUNT; XboxStage++) {
// If point sprites are enabled, we need to overwrite our existing state 0 with State 3 also
DWORD HostStage = (pointSpriteOverride && XboxStage == 3) ? 0 : XboxStage;
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[(XboxStage * XTL::X_D3DTS_STAGESIZE) + StateIndex];
// 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 XboxState = GetDeferredTextureStateFromIndex(StateIndex);
switch (XboxState) {
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;
}
// These states match the PC counterpart IDs
g_pD3DDevice->SetSamplerState(HostStage, (XTL::D3DSAMPLERSTATETYPE)(XboxState + 1), 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(HostStage, (XTL::D3DSAMPLERSTATETYPE)(XboxState + 2), Value);
break;
case XTL::X_D3DTSS_MIPMAPLODBIAS:
g_pD3DDevice->SetSamplerState(HostStage, XTL::D3DSAMP_MIPMAPLODBIAS, Value);
break;
case XTL::X_D3DTSS_MAXMIPLEVEL:
g_pD3DDevice->SetSamplerState(HostStage, XTL::D3DSAMP_MAXMIPLEVEL, Value);
break;
case XTL::X_D3DTSS_MAXANISOTROPY:
g_pD3DDevice->SetSamplerState(HostStage, 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:
switch (TranslateXDKSpecificD3DTOP(Value)) {
case XTL::X_D3DTOP_DISABLE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_DISABLE);
break;
case XTL::X_D3DTOP_SELECTARG1:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SELECTARG1);
break;
case XTL::X_D3DTOP_SELECTARG2:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SELECTARG2);
break;
case XTL::X_D3DTOP_MODULATE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE);
break;
case XTL::X_D3DTOP_MODULATE2X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE2X);
break;
case XTL::X_D3DTOP_MODULATE4X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATE4X);
break;
case XTL::X_D3DTOP_ADD:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADD);
break;
case XTL::X_D3DTOP_ADDSIGNED:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSIGNED);
break;
case XTL::X_D3DTOP_ADDSIGNED2X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSIGNED2X);
break;
case XTL::X_D3DTOP_SUBTRACT:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_SUBTRACT);
break;
case XTL::X_D3DTOP_ADDSMOOTH:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_ADDSMOOTH);
break;
case XTL::X_D3DTOP_BLENDDIFFUSEALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDDIFFUSEALPHA);
break;
case XTL::X_D3DTOP_BLENDCURRENTALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDCURRENTALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDTEXTUREALPHA);
break;
case XTL::X_D3DTOP_BLENDFACTORALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDFACTORALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHAPM:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BLENDTEXTUREALPHAPM);
break;
case XTL::X_D3DTOP_PREMODULATE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_PREMODULATE);
break;
case XTL::X_D3DTOP_MODULATEALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATECOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATECOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_MODULATEINVALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEINVALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATEINVCOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MODULATEINVCOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_DOTPRODUCT3:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_DOTPRODUCT3);
break;
case XTL::X_D3DTOP_MULTIPLYADD:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_MULTIPLYADD);
break;
case XTL::X_D3DTOP_LERP:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_LERP);
break;
case XTL::X_D3DTOP_BUMPENVMAP:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLOROP, XTL::D3DTOP_BUMPENVMAP);
break;
case XTL::X_D3DTOP_BUMPENVMAPLUMINANCE:
g_pD3DDevice->SetTextureStageState(HostStage, 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(HostStage, XTL::D3DTSS_COLORARG0, Value);
break;
case XTL::X_D3DTSS_COLORARG1:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_COLORARG1, Value);
break;
case XTL::X_D3DTSS_COLORARG2:
g_pD3DDevice->SetTextureStageState(HostStage, 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) {
switch (TranslateXDKSpecificD3DTOP(Value)) {
case XTL::X_D3DTOP_DISABLE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_DISABLE);
break;
case XTL::X_D3DTOP_SELECTARG1:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_SELECTARG1);
break;
case XTL::X_D3DTOP_SELECTARG2:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_SELECTARG2);
break;
case XTL::X_D3DTOP_MODULATE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATE);
break;
case XTL::X_D3DTOP_MODULATE2X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATE2X);
break;
case XTL::X_D3DTOP_MODULATE4X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATE4X);
break;
case XTL::X_D3DTOP_ADD:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_ADD);
break;
case XTL::X_D3DTOP_ADDSIGNED:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_ADDSIGNED);
break;
case XTL::X_D3DTOP_ADDSIGNED2X:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_ADDSIGNED2X);
break;
case XTL::X_D3DTOP_SUBTRACT:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_SUBTRACT);
break;
case XTL::X_D3DTOP_ADDSMOOTH:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_ADDSMOOTH);
break;
case XTL::X_D3DTOP_BLENDDIFFUSEALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDDIFFUSEALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDTEXTUREALPHA);
break;
case XTL::X_D3DTOP_BLENDFACTORALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDFACTORALPHA);
break;
case XTL::X_D3DTOP_BLENDTEXTUREALPHAPM:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDTEXTUREALPHAPM);
break;
case XTL::X_D3DTOP_BLENDCURRENTALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BLENDCURRENTALPHA);
break;
case XTL::X_D3DTOP_PREMODULATE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_PREMODULATE);
break;
case XTL::X_D3DTOP_MODULATEALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATEALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATECOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATECOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_MODULATEINVALPHA_ADDCOLOR:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATEINVALPHA_ADDCOLOR);
break;
case XTL::X_D3DTOP_MODULATEINVCOLOR_ADDALPHA:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MODULATEINVCOLOR_ADDALPHA);
break;
case XTL::X_D3DTOP_DOTPRODUCT3:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_DOTPRODUCT3);
break;
case XTL::X_D3DTOP_MULTIPLYADD:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_MULTIPLYADD);
break;
case XTL::X_D3DTOP_LERP:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_LERP);
break;
case XTL::X_D3DTOP_BUMPENVMAP:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BUMPENVMAP);
break;
case XTL::X_D3DTOP_BUMPENVMAPLUMINANCE:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAOP, XTL::D3DTOP_BUMPENVMAPLUMINANCE);
break;
default:
EmuLog(LOG_LEVEL::WARNING, "Unsupported D3DTSS_ALPHAOP Value (%d)", Value);
break;
}
}
break;
case XTL::X_D3DTSS_ALPHAARG0:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAARG0, Value);
break;
case XTL::X_D3DTSS_ALPHAARG1:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAARG1, Value);
break;
case XTL::X_D3DTSS_ALPHAARG2:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_ALPHAARG2, Value);
break;
case XTL::X_D3DTSS_RESULTARG:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_RESULTARG, Value);
break;
case XTL::X_D3DTSS_TEXTURETRANSFORMFLAGS:
g_pD3DDevice->SetTextureStageState(HostStage, XTL::D3DTSS_TEXTURETRANSFORMFLAGS, Value);
break;
default:
EmuLog(LOG_LEVEL::WARNING, "Unkown Xbox D3DTSS Value: %d", XboxState);
break;
}
}
// Make sure we only do this once
if (pointSpriteOverride && XboxStage == 3) {
pointSpriteOverride = false;
XboxStage--;
}
}
if (XTL::EmuD3DDeferredRenderState[XTL::X_D3DRS_POINTSPRITEENABLE - XTL::X_D3DRS_FOGENABLE] == TRUE) {
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);
// no need to actually copy here, since it was handled in the loop above
}
}
// ******************************************************************
// * patch: UpdateDeferredStates
// ******************************************************************
void XTL::EmuUpdateDeferredStates()
{
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;
}
}
}
// 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;
// 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];
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(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]);
}
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);
}
}
//**/
}
// 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];
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, D3DTSS_COLOROP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
// 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;
// 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);
}
}
}
}
}
VerifyAndFixEmuDeferredRenderStateOffset();
UpdateDeferredRenderStates();
UpdateDeferredTextureStates();
}