diff --git a/gl.cpp b/gl.cpp index 5776011..aec911d 100644 --- a/gl.cpp +++ b/gl.cpp @@ -366,6 +366,303 @@ XBool jmp_glXMakeContextCurrent(XDisplay *display, GLXDrawable draw, GLXDrawable // End of GLX +// Start of GPU fixes +bool bBadVendor = false; +const std::vector> shaderPatches +{ + // Fragment + {"!!NVfp4.0", "!!ARBfp1.0"}, + {"ATTRIB fragment_texcoord[] = { fragment.texcoord[0..1] };", ""}, + {"ATTRIB fragment_texcoord[] = { fragment.texcoord[0..0] };", ""}, + {"ATTRIB fragment_texcoord[] = { fragment.texcoord[0..7] };", ""}, + {"ATTRIB fragment_texcoord[] = { fragment.texcoord[0..3] };", ""}, + {"ATTRIB fragment_attrib[] = { fragment.attrib[0..19] };", ""}, + {"ATTRIB fragment_attrib[] = { fragment.attrib[0..18] };", ""}, + + // Vertex + {"!!NVvp4.0", "!!ARBvp1.0"}, + {"ATTRIB vertex_attrib[] = { vertex.attrib[0..15] };", ""}, + {"ATTRIB vertex_attrib[] = { vertex.attrib[0..3] };", ""}, + {"ATTRIB vertex_attrib[] = { vertex.attrib[0..8] };", ""}, + {"ATTRIB vertex_attrib[] = { vertex.attrib[0..9] };", ""}, + {"ATTRIB vertex_attrib[] = { vertex.attrib[0..0] };", ""}, + {"OUTPUT result_texcoord[] = { result.texcoord[0..7] };", ""}, + {"OUTPUT result_texcoord[] = { result.texcoord[0..0] };", ""}, + {"OUTPUT result_texcoord[] = { result.texcoord[0..3] };", ""}, + {"OUTPUT result_texcoord[] = { result.texcoord[0..1] };", ""}, + {"OUTPUT result_attrib[] = { result.attrib[0..18] };", ""}, // ?? + {"OUTPUT result_attrib[] = { result.attrib[0..19] };", ""}, + + // Add our own TEMP + {"#vendor NVIDIA Corporation", "#vendor NVIDIA Corporation\nTEMP lineMT;"}, + + // weird attrib stuff that should be invalid? + {"DP3.F R1.x, fragment.attrib[17], fragment.attrib[17];", ""}, + {"DP3.F R0.z, fragment.attrib[18], fragment.attrib[18];", ""}, + {"MUL.F R1.xyz, R1.x, fragment.attrib[17];", ""}, + {"MUL.F R1.xyz, R0.z, fragment.attrib[18];", ""}, + {"TXP.F R2.x, fragment.attrib[18], texture[6], SHADOW2D;", ""}, + {"TXP.F R0.x, fragment.attrib[17], texture[5], SHADOW2D;", ""}, + {"DIV.F R0.w, fragment.attrib[18].z, fragment.attrib[18].w;", ""}, + {"DIV.F R0.z, fragment.attrib[17], fragment.attrib[17].w;", ""}, + {"TXP.F R0.x, fragment.attrib[19], texture[7], SHADOW2D;", ""}, + {"DIV.F R3.x, fragment.attrib[19].z, fragment.attrib[19].w;", ""}, + {"TXP.F R2.x, fragment.attrib[18], texture[7], SHADOW2D;", ""}, + {"TXP.F R0.x, fragment.attrib[17], texture[6], SHADOW2D;", ""}, + {"TXP.F R0.x, fragment.attrib[19], texture[8], SHADOW2D;", ""}, + {"DIV.F R0.z, fragment.attrib[19], fragment.attrib[19].w;", ""}, + {"TXP.F R2.x, fragment.attrib[18], texture[5], SHADOW2D;", ""}, + {"TXP.F R0.x, fragment.attrib[17], texture[4], SHADOW2D;", ""}, + {"TXP.F R0.x, fragment.attrib[19], texture[6], SHADOW2D;", ""}, + {"MAD.F result.attrib[17].xyz, vertex.attrib[15].z, c[6], R0;", ""}, + {"MAD.F result.attrib[18].xyz, vertex.attrib[14].z, c[6], R1;", ""}, + {"MAD.F result.attrib[17], R1.w, c[19], R0;", ""}, + {"MAD.F result.attrib[18], R1.w, c[23], R2;", ""}, + {"MAD.F result.attrib[19], R1.w, c[27], R2;", ""}, + + // MOV.SAT + {"MOV.F.SAT R0.z, R0.y;", "MAX lineMT, R0.y, 0.0;\nMIN R0.z, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.x, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.w, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.y, R2;", "MAX lineMT, R2, 0.0;\nMIN R2.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.z, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN R0.z, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.xy, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.xy, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.xyz, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.xyz, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1, R1;", "MAX lineMT, R1, 0.0;\nMIN R1, lineMT, 1.0;"}, + {"MOV.F.SAT oCol2.w, R0;", "MAX lineMT, R0, 0.0;\nMIN oCol2.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.z, R0;", "MAX lineMT, R0, 0.0;\nMIN R0.z, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.y, R1.x;", "MAX lineMT, R1.x, 0.0;\nMIN R1.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.x, R1;", "MAX lineMT, R1, 0.0;\nMIN R1.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.x, R0.w;", "MAX lineMT, R0.w, 0.0;\nMIN R0.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.z, R2.x;", "MAX lineMT, R2.x, 0.0;\nMIN R0.z, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.x, R2.w;", "MAX lineMT, R2.w, 0.0;\nMIN R1.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT oCol, R0;", "MAX lineMT, R0, 0.0;\nMIN oCol, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.w, R2;", "MAX lineMT, R2, 0.0;\nMIN R2.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.w, R1;", "MAX lineMT, R1, 0.0;\nMIN R1.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.y, R2.x;", "MAX lineMT, R2.x, 0.0;\nMIN R2.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.x, R2;", "MAX lineMT, R2, 0.0;\nMIN R2.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R1.w;", "MAX lineMT, R1.w, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R3.x, R1;", "MAX lineMT, R1, 0.0;\nMIN R3.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.x, R0.z;", "MAX lineMT, R0.z, 0.0;\nMIN R1.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.x, R0.y;", "MAX lineMT, R0.y, 0.0;\nMIN R1.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R2.w;", "MAX lineMT, R2.w, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.y, R2.w;", "MAX lineMT, R2.w, 0.0;\nMIN R1.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R3.x, R3;", "MAX lineMT, R3, 0.0;\nMIN R3.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R3.x;", "MAX lineMT, R3.x, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R1.x;", "MAX lineMT, R1.x, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.y, R1;", "MAX lineMT, R1, 0.0;\nMIN R1.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R3.x, R0.w;", "MAX lineMT, R0.w, 0.0;\nMIN R3.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0, R1;", "MAX lineMT, R1, 0.0;\nMIN R0, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT oCol1.w, R1;", "MAX lineMT, R1, 0.0;\nMIN oCol1.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT oCol2.w, R1;", "MAX lineMT, R1, 0.0;\nMIN oCol2.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.z, R2;", "MAX lineMT, R2, 0.0;\nMIN R2.z, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.xy, R3;", "MAX lineMT, R3, 0.0;\nMIN R0.xy, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.y, R0.w;", "MAX lineMT, R0.w, 0.0;\nMIN R0.y, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.x, R2.w;", "MAX lineMT, R2.w, 0.0;\nMIN R2.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.x, R3.w;", "MAX lineMT, R3.w, 0.0;\nMIN R2.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[7].w, R0.y;", "MAX lineMT, R0.y, 0.0;\nMIN result.texcoord[7].w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.x, R1;", "MAX lineMT, R1, 0.0;\nMIN R0.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.w, R1;", "MAX lineMT, R1, 0.0;\nMIN R0.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[7].w, R1;", "MAX lineMT, R1, 0.0;\nMIN result.texcoord[7].w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.w, R1.x;", "MAX lineMT, R1.x, 0.0;\nMIN R0.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[7].w, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN result.texcoord[7].w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[1], R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN result.texcoord[1], lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.x, R0.y;", "MAX lineMT, R0.y, 0.0;\nMIN R0.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.w, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN R0.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R4.x, R1;", "MAX lineMT, R1, 0.0;\nMIN R4.x, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R2.w, R2.x;", "MAX lineMT, R2.x, 0.0;\nMIN R2.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.w, R1.x;", "MAX lineMT, R1.x, 0.0;\nMIN R1.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[5].w, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN result.texcoord[5].w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R0.w, R0.y;", "MAX lineMT, R0.y, 0.0;\nMIN R0.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[1].xyz, R1.x;", "MAX lineMT, R1.x, 0.0;\nMIN result.texcoord[1].xyz, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT result.texcoord[1].w, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN result.texcoord[1].w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MOV.F.SAT R1.w, R0.x;", "MAX lineMT, R0.x, 0.0;\nMIN R1.w, lineMT, 1.0;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + + // Common instructions + {"MOV.F", "MOV"}, + {"MUL.F", "MUL"}, + {"ADD.F", "ADD"}, + {"TEX.F", "TEX"}, + {"MAD.F", "MAD"}, + {"MIN.F", "MIN"}, + {"MAX.F", "MAX"}, + {"RCP.F", "RCP"}, + {"DP3.F", "DP3"}, + {"DP4.F", "DP4"}, + {"RSQ.F", "RSQ"}, + {"POW.F", "POW"}, + {"SLT.F", "SLT"}, + {"FRC.F", "FRC"}, + {"LIT.F", "LIT"}, + {"SGE.F", "SGE"}, + {"TXP.F", "TXP"}, + {"LG2.F", "LG2"}, + {"MOV.S", "MOV"}, + {"ADD.S", "ADD"}, + + // Absolute value + {"FRC R0, |R0|;", "ABS lineMT, R0;\nFRC R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"FRC R0.z, |R0.x|;", "ABS lineMT.z, R0.x;\nFRC R0.z, lineMT.z;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"FRC R0.y, |R0.z|;", "ABS lineMT.y, R0.z;\nFRC R0.y, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"FRC R0.xy, |R0|;", "ABS lineMT, R0;\nFRC R0.xy, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MUL R0.z, R0, |R0.y|;", "ABS lineMT.z, R0.y;\nMUL R0.z, R0, lineMT.z;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MUL R1, R0, |R1|;", "ABS lineMT, R1;\nMUL R1, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MUL R0.w, R0.y, |c[4].x|;", "ABS lineMT.x, c[4].x;\nMUL R0.w, R0.y, lineMT.x;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MUL R0.zw, R0.xyxy, |R0|;", "ABS lineMT, R0;\nMUL R0.zw, R0.xyxy, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MUL R0, R0, |R1|;", "ABS lineMT, R1;\nMUL R0, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"MAD R0.xy, fragment.texcoord[4], {-0.5, 0.5}, |{-0.5, 0.5}.x|;", "ABS lineMT.x, {-0.5, 0.5}.x;\nMAD R0.xy, fragment.texcoord[4], {-0.5, 0.5}, lineMT.x;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + + // DP2 + {"DP2.F R0.z, R0, R0;", "MUL lineMT.x, R0.x, R0.x;\nMUL lineMT.y, R0.y, R0.y;\nADD R0.z, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DP2.F R0.w, R0, R0;", "MUL lineMT.x, R0.x, R0.x;\nMUL lineMT.y, R0.y, R0.y;\nADD R0.w, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DP2.F R0.y, R0.zwzw, c[1];", "MUL lineMT.x, R0.z, c[1].z;MUL lineMT.y, R0.w, c[1].w;\nADD R0.y, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DP2.F R0.x, R0.zwzw, c[0];", "MUL lineMT.x, R0.z, c[0].z;MUL lineMT.y, R0.w, c[0].w;\nADD R0.x, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DP2.F R2.x, R0, c[0];", "MUL lineMT.x, R0.x, c[0].x;\nMUL lineMT.y, R0.y, c[0].y;\nADD R2.x, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DP2.F R2.y, R0, c[1];", "MUL lineMT.x, R0.x, c[1].x;\nMUL lineMT.y, R0.y, c[1].y;\nADD R2.y, lineMT.x, lineMT.y;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + + // Division + {"DIV.F R0.y, R0, c[0].x;", "RCP lineMT, c[0].x;\nMUL R0.y, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.w, c[0].x, R0.x;", "RCP lineMT, R0.x;\nMUL R0.w, c[0].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.w, c[0].x, R1.w;", "RCP lineMT, R1.w;\nMUL R1.w, c[0].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.x, R0, R0.y;", "RCP lineMT, R0.y;\nMUL R0.x, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.w, c[0].x, R0.w;", "RCP lineMT, R0.w;\nMUL R0.w, c[0].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.xyz, R0, c[0].z;", "RCP lineMT, c[0].z;\nMUL R0.xyz, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.xyz, R1, c[0].z;", "RCP lineMT, c[0].z;\nMUL R1.xyz, R1, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.z, {-5}.x, R2.z;", "RCP lineMT, R2.z;\nMUL R1.z, {-5}.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, {-9}.x, R2.z;", "RCP lineMT, R2.z;\nMUL R2.w, {-9}.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, {-4}.x, R2.z;", "RCP lineMT, R2.z;\nMUL R2.w, {-4}.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, {-2}.x, R2.z;", "RCP lineMT, R2.z;\nMUL R2.w, {-2}.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F oCol, R0, R2.x;", "RCP lineMT, R2.x;\nMUL oCol, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.x, R0, R0.y;", "RCP lineMT, R0.y;\nMUL R1.x, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, R1.x, R1.y;", "RCP lineMT, R1.y;\nMUL R2.w, R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, R0.x, R0.y;", "RCP lineMT, R0.y;\nMUL R2.w, R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.x, R0, R0.y;", "RCP lineMT, R0.y;\nMUL R2.x, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.w, R0.x, R0.y;", "RCP lineMT, R0.y;\nMUL R1.w, R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.w, R2.x, R2.y;", "RCP lineMT, R2.y;\nMUL R3.w, R2.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.x, R0.y, R0.x;", "RCP lineMT, R0.x;\nMUL R1.x, R0.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.w, R1.x, R0.w;", "RCP lineMT, R0.w;\nMUL R0.w, R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.x, R2, R2.y;", "RCP lineMT, R2.y;\nMUL R3.x, R2, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.w, R2, R3.x;", "RCP lineMT, R3.x;\nMUL R2.w, R2, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.z, c[1].x, R0.y;", "RCP lineMT, R0.y;\nMUL R0.z, c[1].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.y, R0.x, R0.y;", "RCP lineMT, R0.y;\nMUL R0.y, R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.z, c[2].x, R0.y;", "RCP lineMT, R0.y;\nMUL R0.z, c[2].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.y, c[1].x, R2.x;", "RCP lineMT, R2.x;\nMUL R2.y, c[1].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.z, c[1].x, R2.y;", "RCP lineMT, R2.y;\nMUL R2.z, c[1].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.z, c[1].x, R1.y;", "RCP lineMT, R1.y;\nMUL R1.z, c[1].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.y, c[2].x, R2.x;", "RCP lineMT, R2.x;\nMUL R2.y, c[2].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R2.z, c[2].x, R2.y;", "RCP lineMT, R2.y;\nMUL R2.z, c[2].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.z, c[2].x, R1.y;", "RCP lineMT, R1.y;\nMUL R1.z, c[2].x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.x, R1, R1.y;", "RCP lineMT, R1.y;\nMUL R1.x, R1, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R1.w, R1, R2.x;", "RCP lineMT, R2.x;\nMUL R1.w, R1, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.y, R0, R0.z;", "RCP lineMT, R0.z;\nMUL R0.y, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.x, c[8], R0.y;", "RCP lineMT, R0.y;\nMUL R0.x, c[8], lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.z, R0.x, c[4].x;", "RCP lineMT, c[4].x;\nMUL R0.z, R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.x, R0, c[4].x;", "RCP lineMT, c[4].x;\nMUL R0.x, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.y, R0, c[4].y;", "RCP lineMT, c[4].y;\nMUL R0.y, R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.x, {0.88}, R3.x;", "RCP lineMT, R3.x;\nMUL R3.x, {0.88}, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.x, R3, c[7].x;", "RCP lineMT, c[7].x;\nMUL R3.x, R3, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.x, c[7].y, R3.x;", "RCP lineMT, R3.x;\nMUL R3.x, c[7].y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R3.x, R3, {0}.x;", "RCP lineMT, {0}.x;\nMUL R3.x, R3, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"DIV.F R0.w, fragment.attrib[18].z, fragment.attrib[18].w;", "RCP lineMT, fragment.attrib[18].w;\nMUL R0.w, fragment.attrib[18].w.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};" }, + //{"DIV.F R0.z, fragment.attrib[17], fragment.attrib[17].w;", "RCP lineMT, fragment.attrib[17].w;\nMUL R0.z, fragment.attrib[17].w, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};" }, + {"DIV.F R0.x, fragment.texcoord[3].z, fragment.texcoord[3].w;", "RCP lineMT, fragment.texcoord[3].w;\nMUL R0.x, fragment.texcoord[3].z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};" }, + {"DIV.F R0.y, fragment.texcoord[4].z, fragment.texcoord[4].w;", "RCP lineMT, fragment.texcoord[4].w;\nMUL R0.y, fragment.texcoord[4].z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};" }, + //{"DIV.F R0.z, fragment.attrib[19], fragment.attrib[19].w;", "RCP lineMT, fragment.attrib[19].w;\nMUL R0.z, fragment.attrib[19], lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};" }, + + // Truncate + {"TRUNC.U R1.x, R1;", "MOV lineMT, R1;\nFLR R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R0.z, R0;", "MOV lineMT, R0;\nFLR R0.z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R0.x, R0;", "MOV lineMT, R0;\nFLR R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R2.x, R2;", "MOV lineMT, R2;\nFLR R2.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R0.y, R0;", "MOV lineMT, R0;\nFLR R0.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R2.w, R2;", "MOV lineMT, R2;\nFLR R2.w, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.x, R1;", "MOV lineMT, R1;\nFLR R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.z, R0.x;", "MOV lineMT, R0.x;\nFLR R0.z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.x, R1.y;", "MOV lineMT, R1.y;\nFLR R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.y, R0;", "MOV lineMT, R0;\nFLR R0.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.z, R0.y;", "MOV lineMT, R0.y;\nFLR R0.z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.z, R0;", "MOV lineMT, R0;\nFLR R0.z, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R1.x, R1;", "MOV lineMT, R1;\nFLR R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.x, R0;", "MOV lineMT, R0;\nFLR R0.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R1.x, R0.z;", "MOV lineMT, R0.z;\nFLR R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R1.y, R0.z;", "MOV lineMT, R0.z;\nFLR R1.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R1.y, R1.x;", "MOV lineMT, R1.x;\nFLR R1.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R1.x, R0.y;", "MOV lineMT, R0.y;\nFLR R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.F R0.y, R0.z;", "MOV lineMT, R0.z;\nFLR R0.y, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R1, R1;", "MOV lineMT, R1;\nFLR R1, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R0, R0;", "MOV lineMT, R0;\nFLR R0, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R1, R0;", "MOV lineMT, R0;\nFLR R1, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"TRUNC.U R1.x, R3;", "MOV lineMT, R3;\nFLR R1.x, lineMT;\nMOV lineMT, {0.0, 0.0, 0.0, 0.0};"}, + {"I2F", "MOV"}, + + // More stubs + {"TRUNC.U.CC HC.x, R1.z;", "#TRUNC.U.CC HC.x, R1.z;"}, + {"TRUNC.U.CC HC.x, R4.y;", "#TRUNC.U.CC HC.x, R4.y;"}, + {"TRUNC.U.CC HC.x, R4;", "#TRUNC.U.CC HC.x, R4;"}, + {"TRUNC.U.CC HC.x, R0.w;", "#TRUNC.U.CC HC.x, R0.w;"}, + {"TRUNC.U.CC HC.x, R0.z;", "#TRUNC.U.CC HC.x, R0.z;"}, + {"TRUNC.U.CC HC.x, R0.y;", "#TRUNC.U.CC HC.x, R0.y;"}, + {"TRUNC.U.CC HC.x, R0;", "#TRUNC.U.CC HC.x, R0;"}, + {"TRUNC.U.CC HC.x, R3;", "#TRUNC.U.CC HC.x, R3;"}, + {"SEQ.F", "#SEQ.F"}, + {"SEQ.U", "#SEQ.U"}, + {"REP.S", "#REP.S"}, + {"SLE.F", "#SLE.F"}, + {"MOV.U.CC", "#MOV.U.CC"}, + {"ENDREP;", "#ENDREP;"}, + {"BRK (GT.x);", "#BRK (GT.x);"}, + {"IF NE.x;", "#IF NE.x;"}, + {"ELSE;", "#ELSE;"}, + {"ENDIF;", "#ENDIF;"}, + {"MOV R0(NE.x)", "#MOV R0(NE.x)"}, + {"MOV R0.x(NE)", "#MOV R0.x(NE)"}, + {"MOV R0.xy(NE.x)", "#MOV R0.xy(NE.x)"}, + {"MOV R1(NE.x), -R0;", "#MOV R1(NE.x), -R0;"}, +}; + +void jmp_glGenFencesNV(GLsizei n, GLuint* fences) +{ + *fences = reinterpret_cast(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); +} + +void jmp_glDeleteFencesNV(GLsizei n, const GLuint* fences) +{ + glDeleteSync(reinterpret_cast(*fences)); +} + +void jmp_glSetFenceNV(GLuint fence, GLenum condition) +{ + glDeleteSync(reinterpret_cast(fence)); + fence = reinterpret_cast(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); +} + +GLboolean jmp_glTestFenceNV(GLuint fence) +{ + GLint result = 0; + glGetSynciv(reinterpret_cast(fence), GL_SYNC_STATUS, sizeof(result), nullptr, &result); + return (result == GL_SIGNALED) ? GL_TRUE : GL_FALSE; +} + +void jmp_glFinishFenceNV(GLuint fence) +{ + //glWaitSync(reinterpret_cast(fence), 0, GL_TIMEOUT_IGNORED); + glClientWaitSync(reinterpret_cast(fence), GL_SYNC_FLUSH_COMMANDS_BIT, 1000000000UL); +} + +void jmp_glDepthRangedNV(GLdouble n, GLdouble f) +{ + glDepthRange(n, f); +} + +void jmp_glClearDepthdNV(double d) +{ + glClearDepth(d); +} + +// End of GPU fixes + std::unordered_map GL_FUNCS_STUB = { {"glXGetProcAddress", (void *)jmp_glXGetProcAddress}, {"glXGetVideoSyncSGI", (void *)jmp_glXGetVideoSyncSGI}, @@ -404,6 +701,24 @@ std::unordered_map GL_FUNCS_STUB = { void *gl_resolve(const char *name) { + if(bBadVendor) + { + if (strcmp("glGenFencesNV", name) == 0) + return (void *)jmp_glGenFencesNV; + else if (strcmp("glDeleteFencesNV", name) == 0) + return (void *)jmp_glDeleteFencesNV; + else if (strcmp("glSetFenceNV", name) == 0) + return (void *)jmp_glSetFenceNV; + else if (strcmp("glTestFenceNV", name) == 0) + return (void *)jmp_glTestFenceNV; + else if (strcmp("glFinishFenceNV", name) == 0) + return (void *)jmp_glFinishFenceNV; + else if (strcmp("glDepthRangedNV", name) == 0) + return (void *)jmp_glDepthRangedNV; + else if (strcmp("glClearDepthdNV", name) == 0) + return (void *)jmp_glClearDepthdNV; + } + for (auto &it : GL_FUNCS_STUB) { if (strcmp(it.first, name) == 0) @@ -474,6 +789,16 @@ void gl_init(void *hWnd_) return; } + // Get and check if vendor is not nvidia + std::string vendor = reinterpret_cast(glGetString(GL_VENDOR)); + size_t pos = vendor.find("NVIDIA"); + + if(pos == std::string::npos) + { + bBadVendor = true; + printf("Non-NVIDIA GPU detected, enabling fixes...\n"); + } + // Successfully loaded OpenGL printf("Loaded OpenGL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); } \ No newline at end of file diff --git a/gl.h b/gl.h index 16d8f82..01cb855 100644 --- a/gl.h +++ b/gl.h @@ -1,4 +1,28 @@ #pragma once +#include +#include + +extern bool bBadVendor; +extern const std::vector> shaderPatches; + +typedef struct _CGcontext *CGcontext; +typedef struct _CGprogram *CGprogram; +typedef enum +{ + CG_SOURCE = 4112, + CG_OBJECT = 4113 +} CGenum; + +typedef enum +{ + CG_PROFILE_ARBVP1 = 6150, + CG_PROFILE_FP40 = 6151, + CG_PROFILE_ARBFP1 = 7000, + CG_PROFILE_VP40 = 7001, + CG_PROFILE_GP5FP = 7017, + CG_PROFILE_GP5VP = 7018 + +} CGprofile; void *gl_resolve(const char *name); diff --git a/main.cpp b/main.cpp index dc22b6c..ec96a98 100644 --- a/main.cpp +++ b/main.cpp @@ -117,6 +117,66 @@ void jmp_std_string_assign(void *a1, void *a2) old_std_string_assign(a1, a2); } +CGprogram(__cdecl *old_cgCreateProgram)(CGcontext context, + CGenum program_type, + const char *program, + CGprofile profile, + const char *entry, + const char **args); + +CGprogram jmp_cgCreateProgram(CGcontext context, + CGenum program_type, + const char *program, + CGprofile profile, + const char *entry, + const char **args) +{ + switch (profile) + { + case CG_PROFILE_VP40: + case CG_PROFILE_GP5VP: + profile = CG_PROFILE_ARBVP1; + break; + + case CG_PROFILE_FP40: + case CG_PROFILE_GP5FP: + profile = CG_PROFILE_ARBFP1; + + default: + break; + } + + std::string prog = program; + + for (const auto& sp : shaderPatches) + { + size_t pos = 0; + while ((pos = prog.find(sp.first, pos)) != std::string::npos) + { + prog.replace(pos, sp.first.length(), sp.second); + pos += sp.second.length(); + } + } + + return old_cgCreateProgram(context, program_type, prog.c_str(), profile, entry, args); +} + +void(__cdecl *old_glEnable)(GLenum cap); +void jmp_glEnable(GLenum cap) +{ + if(cap == GL_STENCIL_TEST_TWO_SIDE_EXT && bBadVendor) + cap = GL_STENCIL_TEST; + old_glEnable(cap); +} + +void(__cdecl *old_glDisable)(GLenum cap); +void jmp_glDisable(GLenum cap) +{ + if(cap == GL_STENCIL_TEST_TWO_SIDE_EXT && bBadVendor) + cap = GL_STENCIL_TEST; + old_glDisable(cap); +} + extern "C" { DllExport void OnInitialize(int version, void **func_tables) @@ -241,6 +301,13 @@ extern "C" if (config.yac) yac_init(); + if (bBadVendor) + { + Line::Hook((void *)0x0805A3C8, (void *)jmp_cgCreateProgram, (void **)&old_cgCreateProgram); + Line::Hook((void *)0x080587D8, (void *)jmp_glEnable, (void **)&old_glEnable); + Line::Hook((void *)0x08059B48, (void *)jmp_glDisable, (void **)&old_glDisable); + } + void *lib_gs = dlopen("gspatch.dll", RTLD_NOW); if (!lib_gs) printf("can't load gspatch.dll\n");