├── .gitignore ├── BinaryDecompiler ├── BinaryDecompiler.vcxproj ├── BinaryDecompiler.vcxproj.filters ├── BinaryDecompiler.vcxproj.user ├── decode.cpp ├── decodeDX9.cpp ├── include │ ├── hlslcc.h │ ├── hlslcc.hpp │ └── pstdint.h ├── internal_includes │ ├── debug.h │ ├── decode.h │ ├── languages.h │ ├── reflect.h │ ├── shaderLimits.h │ ├── structs.h │ ├── tokens.h │ └── tokensDX9.h └── reflect.cpp ├── D3D_Shaders ├── Assembler.cpp ├── D3D_Shaders.vcxproj ├── D3D_Shaders.vcxproj.filters ├── D3D_Shaders.vcxproj.user ├── Shaders.cpp ├── SignatureParser.cpp ├── stdafx.h └── targetver.h ├── HLSLDecompiler ├── DecompileHLSL.cpp ├── DecompileHLSL.h └── cmd_Decompiler │ ├── ReadMe.txt │ ├── aaa.dxbc │ ├── aaa.hlsl │ ├── aaa.txt │ ├── cmd_Decompiler.cpp │ ├── cmd_Decompiler.vcxproj │ ├── cmd_Decompiler.vcxproj.filters │ ├── cmd_Decompiler.vcxproj.user │ ├── crc32c.cpp │ ├── crc32c.h │ ├── generated-constants.cpp │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── LICENSE ├── README.md ├── StereovisionHacks.sdf ├── StereovisionHacks.sln ├── StereovisionHacks.v12.suo ├── hlsl_decompiler_wrapper.bat ├── log.h ├── shader.h ├── util.h ├── util_min.h └── version.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | x32/ 3 | x64/ 4 | Debug/ 5 | Release/ -------------------------------------------------------------------------------- /BinaryDecompiler/BinaryDecompiler.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Zip Release 22 | Win32 23 | 24 | 25 | Zip Release 26 | x64 27 | 28 | 29 | 30 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4} 31 | Win32Proj 32 | BinaryDecompiler 33 | 10.0 34 | 35 | 36 | 37 | StaticLibrary 38 | true 39 | v142 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | StaticLibrary 57 | false 58 | v142 59 | true 60 | Unicode 61 | 62 | 63 | StaticLibrary 64 | false 65 | v142 66 | true 67 | Unicode 68 | 69 | 70 | StaticLibrary 71 | false 72 | v142 73 | true 74 | Unicode 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | $(ProjectDir)include;$(VC_IncludePath) 100 | $(SolutionDir)\x32\$(Configuration)\ 101 | $(ProjectDir)x32\$(Configuration)\ 102 | 103 | 104 | $(ProjectDir)include;$(VC_IncludePath) 105 | $(SolutionDir)x64\$(Configuration)\ 106 | $(ProjectDir)x64\$(Configuration)\ 107 | 108 | 109 | $(ProjectDir)include;$(VC_IncludePath) 110 | $(SolutionDir)x32\$(Configuration)\ 111 | $(ProjectDir)x32\$(Configuration)\ 112 | 113 | 114 | $(ProjectDir)include;$(VC_IncludePath) 115 | $(SolutionDir)x64\$(Configuration)\ 116 | $(ProjectDir)x64\$(Configuration)\ 117 | 118 | 119 | $(ProjectDir)include;$(VC_IncludePath) 120 | $(SolutionDir)x32\$(Configuration)\ 121 | $(ProjectDir)x32\$(Configuration)\ 122 | 123 | 124 | $(ProjectDir)include;$(VC_IncludePath) 125 | $(SolutionDir)x64\$(Configuration)\ 126 | $(ProjectDir)x64\$(Configuration)\ 127 | 128 | 129 | 130 | Level3 131 | Disabled 132 | Async 133 | true 134 | MultiThreadedDebug 135 | $(SolutionDir) 136 | 137 | 138 | Windows 139 | true 140 | 141 | 142 | 143 | 144 | Level3 145 | Disabled 146 | MultiThreadedDebug 147 | Async 148 | true 149 | $(SolutionDir) 150 | 151 | 152 | Windows 153 | true 154 | 155 | 156 | 157 | 158 | Level3 159 | MaxSpeed 160 | true 161 | NDEBUG; 162 | Async 163 | false 164 | MultiThreaded 165 | $(SolutionDir) 166 | 167 | 168 | Windows 169 | true 170 | true 171 | true 172 | 173 | 174 | 175 | 176 | Level3 177 | MaxSpeed 178 | true 179 | NDEBUG; 180 | Async 181 | false 182 | MultiThreaded 183 | $(SolutionDir) 184 | 185 | 186 | Windows 187 | true 188 | true 189 | true 190 | 191 | 192 | 193 | 194 | Level3 195 | MaxSpeed 196 | true 197 | NDEBUG; 198 | MultiThreaded 199 | Async 200 | false 201 | $(SolutionDir) 202 | 203 | 204 | Windows 205 | true 206 | true 207 | true 208 | 209 | 210 | 211 | 212 | Level3 213 | MaxSpeed 214 | true 215 | NDEBUG; 216 | MultiThreaded 217 | Async 218 | false 219 | $(SolutionDir) 220 | 221 | 222 | Windows 223 | true 224 | true 225 | true 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | -------------------------------------------------------------------------------- /BinaryDecompiler/BinaryDecompiler.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /BinaryDecompiler/BinaryDecompiler.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /BinaryDecompiler/include/hlslcc.h: -------------------------------------------------------------------------------- 1 | #ifndef HLSLCC_H_ 2 | #define HLSLCC_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined (_WIN32) && defined(HLSLCC_DYNLIB) 9 | #define HLSLCC_APIENTRY __stdcall 10 | #if defined(libHLSLcc_EXPORTS) 11 | #define HLSLCC_API __declspec(dllexport) 12 | #else 13 | #define HLSLCC_API __declspec(dllimport) 14 | #endif 15 | #else 16 | #define HLSLCC_APIENTRY 17 | #define HLSLCC_API 18 | #endif 19 | 20 | #include 21 | 22 | typedef enum 23 | { 24 | LANG_DEFAULT,// Depends on the HLSL shader model. 25 | LANG_ES_100, 26 | LANG_ES_300, 27 | LANG_120, 28 | LANG_130, 29 | LANG_140, 30 | LANG_150, 31 | LANG_330, 32 | LANG_400, 33 | LANG_410, 34 | LANG_420, 35 | LANG_430, 36 | LANG_440, 37 | } GLLang; 38 | 39 | enum {MAX_SHADER_VEC4_OUTPUT = 512}; 40 | enum {MAX_SHADER_VEC4_INPUT = 512}; 41 | enum {MAX_TEXTURES = 128}; 42 | enum {MAX_FORK_PHASES = 2}; 43 | enum {MAX_FUNCTION_BODIES = 1024}; 44 | enum {MAX_CLASS_TYPES = 1024}; 45 | enum {MAX_FUNCTION_POINTERS = 128}; 46 | 47 | //Reflection 48 | #define MAX_REFLECT_STRING_LENGTH 512 49 | #define MAX_SHADER_VARS 256 50 | #define MAX_CBUFFERS 256 51 | #define MAX_UAV 256 52 | #define MAX_FUNCTION_TABLES 256 53 | #define MAX_RESOURCE_BINDINGS 256 54 | 55 | typedef enum SPECIAL_NAME 56 | { 57 | NAME_UNDEFINED = 0, 58 | NAME_POSITION = 1, 59 | NAME_CLIP_DISTANCE = 2, 60 | NAME_CULL_DISTANCE = 3, 61 | NAME_RENDER_TARGET_ARRAY_INDEX = 4, 62 | NAME_VIEWPORT_ARRAY_INDEX = 5, 63 | NAME_VERTEX_ID = 6, 64 | NAME_PRIMITIVE_ID = 7, 65 | NAME_INSTANCE_ID = 8, 66 | NAME_IS_FRONT_FACE = 9, 67 | NAME_SAMPLE_INDEX = 10, 68 | // The following are added for D3D11 69 | NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11, 70 | NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12, 71 | NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13, 72 | NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14, 73 | NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15, 74 | NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16, 75 | NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17, 76 | NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18, 77 | NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19, 78 | NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20, 79 | NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21, 80 | NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22, 81 | } SPECIAL_NAME; 82 | 83 | 84 | typedef enum { 85 | INOUT_COMPONENT_UNKNOWN = 0, 86 | INOUT_COMPONENT_UINT32 = 1, 87 | INOUT_COMPONENT_SINT32 = 2, 88 | INOUT_COMPONENT_FLOAT32 = 3 89 | } INOUT_COMPONENT_TYPE; 90 | 91 | typedef enum MIN_PRECISION { 92 | MIN_PRECISION_DEFAULT = 0, 93 | MIN_PRECISION_FLOAT_16 = 1, 94 | MIN_PRECISION_FLOAT_2_8 = 2, 95 | MIN_PRECISION_RESERVED = 3, 96 | MIN_PRECISION_SINT_16 = 4, 97 | MIN_PRECISION_UINT_16 = 5, 98 | MIN_PRECISION_ANY_16 = 0xf0, 99 | MIN_PRECISION_ANY_10 = 0xf1 100 | } MIN_PRECISION; 101 | 102 | struct InOutSignature 103 | { 104 | std::string SemanticName; 105 | uint32_t ui32SemanticIndex; 106 | SPECIAL_NAME eSystemValueType; 107 | INOUT_COMPONENT_TYPE eComponentType; 108 | uint32_t ui32Register; 109 | uint32_t ui32Mask; 110 | uint32_t ui32ReadWriteMask; 111 | 112 | uint32_t ui32Stream; 113 | MIN_PRECISION eMinPrec; 114 | }; 115 | 116 | typedef enum ResourceType_TAG 117 | { 118 | RTYPE_CBUFFER,//0 119 | RTYPE_TBUFFER,//1 120 | RTYPE_TEXTURE,//2 121 | RTYPE_SAMPLER,//3 122 | RTYPE_UAV_RWTYPED,//4 123 | RTYPE_STRUCTURED,//5 124 | RTYPE_UAV_RWSTRUCTURED,//6 125 | RTYPE_BYTEADDRESS,//7 126 | RTYPE_UAV_RWBYTEADDRESS,//8 127 | RTYPE_UAV_APPEND_STRUCTURED,//9 128 | RTYPE_UAV_CONSUME_STRUCTURED,//10 129 | RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11 130 | } ResourceType; 131 | 132 | typedef enum ResourceGroup_TAG { 133 | RGROUP_CBUFFER, 134 | RGROUP_TEXTURE, 135 | RGROUP_SAMPLER, 136 | RGROUP_UAV, 137 | RGROUP_COUNT, 138 | } ResourceGroup; 139 | 140 | typedef enum REFLECT_RESOURCE_DIMENSION 141 | { 142 | REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0, 143 | REFLECT_RESOURCE_DIMENSION_BUFFER = 1, 144 | REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2, 145 | REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3, 146 | REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4, 147 | REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5, 148 | REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6, 149 | REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7, 150 | REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8, 151 | REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9, 152 | REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, 153 | REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, 154 | } REFLECT_RESOURCE_DIMENSION; 155 | 156 | typedef struct ResourceBinding_TAG 157 | { 158 | std::string Name; 159 | ResourceType eType; 160 | uint32_t ui32BindPoint; 161 | uint32_t ui32BindCount; 162 | uint32_t ui32Flags; 163 | REFLECT_RESOURCE_DIMENSION eDimension; 164 | uint32_t ui32ReturnType; 165 | uint32_t ui32NumSamples; 166 | } ResourceBinding; 167 | 168 | typedef enum _SHADER_VARIABLE_TYPE { 169 | SVT_VOID = 0, 170 | SVT_BOOL = 1, 171 | SVT_INT = 2, 172 | SVT_FLOAT = 3, 173 | SVT_STRING = 4, 174 | SVT_TEXTURE = 5, 175 | SVT_TEXTURE1D = 6, 176 | SVT_TEXTURE2D = 7, 177 | SVT_TEXTURE3D = 8, 178 | SVT_TEXTURECUBE = 9, 179 | SVT_SAMPLER = 10, 180 | SVT_PIXELSHADER = 15, 181 | SVT_VERTEXSHADER = 16, 182 | SVT_UINT = 19, 183 | SVT_UINT8 = 20, 184 | SVT_GEOMETRYSHADER = 21, 185 | SVT_RASTERIZER = 22, 186 | SVT_DEPTHSTENCIL = 23, 187 | SVT_BLEND = 24, 188 | SVT_BUFFER = 25, 189 | SVT_CBUFFER = 26, 190 | SVT_TBUFFER = 27, 191 | SVT_TEXTURE1DARRAY = 28, 192 | SVT_TEXTURE2DARRAY = 29, 193 | SVT_RENDERTARGETVIEW = 30, 194 | SVT_DEPTHSTENCILVIEW = 31, 195 | SVT_TEXTURE2DMS = 32, 196 | SVT_TEXTURE2DMSARRAY = 33, 197 | SVT_TEXTURECUBEARRAY = 34, 198 | SVT_HULLSHADER = 35, 199 | SVT_DOMAINSHADER = 36, 200 | SVT_INTERFACE_POINTER = 37, 201 | SVT_COMPUTESHADER = 38, 202 | SVT_DOUBLE = 39, 203 | SVT_RWTEXTURE1D = 40, 204 | SVT_RWTEXTURE1DARRAY = 41, 205 | SVT_RWTEXTURE2D = 42, 206 | SVT_RWTEXTURE2DARRAY = 43, 207 | SVT_RWTEXTURE3D = 44, 208 | SVT_RWBUFFER = 45, 209 | SVT_BYTEADDRESS_BUFFER = 46, 210 | SVT_RWBYTEADDRESS_BUFFER = 47, 211 | SVT_STRUCTURED_BUFFER = 48, 212 | SVT_RWSTRUCTURED_BUFFER = 49, 213 | SVT_APPEND_STRUCTURED_BUFFER = 50, 214 | SVT_CONSUME_STRUCTURED_BUFFER = 51, 215 | 216 | SVT_FORCE_DWORD = 0x7fffffff 217 | } SHADER_VARIABLE_TYPE; 218 | 219 | typedef enum _SHADER_VARIABLE_CLASS { 220 | SVC_SCALAR = 0, 221 | SVC_VECTOR = ( SVC_SCALAR + 1 ), 222 | SVC_MATRIX_ROWS = ( SVC_VECTOR + 1 ), 223 | SVC_MATRIX_COLUMNS = ( SVC_MATRIX_ROWS + 1 ), 224 | SVC_OBJECT = ( SVC_MATRIX_COLUMNS + 1 ), 225 | SVC_STRUCT = ( SVC_OBJECT + 1 ), 226 | SVC_INTERFACE_CLASS = ( SVC_STRUCT + 1 ), 227 | SVC_INTERFACE_POINTER = ( SVC_INTERFACE_CLASS + 1 ), 228 | SVC_FORCE_DWORD = 0x7fffffff 229 | } SHADER_VARIABLE_CLASS; 230 | 231 | struct ShaderVarType { 232 | SHADER_VARIABLE_CLASS Class; 233 | SHADER_VARIABLE_TYPE Type; 234 | uint32_t Rows; 235 | uint32_t Columns; 236 | uint32_t Elements; 237 | uint32_t MemberCount; 238 | uint32_t Offset; 239 | std::string Name; 240 | 241 | uint32_t ParentCount; 242 | ShaderVarType *Parent; 243 | //Includes all parent names. 244 | std::string FullName; 245 | 246 | ShaderVarType *Members; 247 | 248 | ShaderVarType() : 249 | Members(NULL) 250 | {} 251 | 252 | ~ShaderVarType() 253 | { 254 | delete [] Members; 255 | } 256 | }; 257 | 258 | struct ShaderVar 259 | { 260 | std::string Name; 261 | bool haveDefaultValue; 262 | std::vector pui32DefaultValues; 263 | //Offset/Size in bytes. 264 | uint32_t ui32StartOffset; 265 | uint32_t ui32Size; 266 | 267 | ShaderVarType sType; 268 | }; 269 | 270 | struct ConstantBuffer 271 | { 272 | std::string Name; 273 | 274 | std::vector asVars; 275 | 276 | uint32_t ui32TotalSizeInBytes; 277 | 278 | int iUnsized; 279 | }; 280 | 281 | struct ClassType 282 | { 283 | std::string Name; 284 | uint16_t ui16ID; 285 | uint16_t ui16ConstBufStride; 286 | uint16_t ui16Texture; 287 | uint16_t ui16Sampler; 288 | }; 289 | 290 | typedef struct ClassInstance_TAG 291 | { 292 | std::string Name; 293 | uint16_t ui16ID; 294 | uint16_t ui16ConstBuf; 295 | uint16_t ui16ConstBufOffset; 296 | uint16_t ui16Texture; 297 | uint16_t ui16Sampler; 298 | } ClassInstance; 299 | 300 | enum TESSELLATOR_PARTITIONING 301 | { 302 | TESSELLATOR_PARTITIONING_UNDEFINED = 0, 303 | TESSELLATOR_PARTITIONING_INTEGER = 1, 304 | TESSELLATOR_PARTITIONING_POW2 = 2, 305 | TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3, 306 | TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4 307 | }; 308 | 309 | typedef enum TESSELLATOR_OUTPUT_PRIMITIVE 310 | { 311 | TESSELLATOR_OUTPUT_UNDEFINED = 0, 312 | TESSELLATOR_OUTPUT_POINT = 1, 313 | TESSELLATOR_OUTPUT_LINE = 2, 314 | TESSELLATOR_OUTPUT_TRIANGLE_CW = 3, 315 | TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4 316 | } TESSELLATOR_OUTPUT_PRIMITIVE; 317 | 318 | struct ShaderInfo 319 | { 320 | uint32_t ui32MajorVersion; 321 | uint32_t ui32MinorVersion; 322 | 323 | uint32_t ui32NumInputSignatures; 324 | InOutSignature* psInputSignatures; 325 | 326 | uint32_t ui32NumOutputSignatures; 327 | InOutSignature* psOutputSignatures; 328 | 329 | uint32_t ui32NumPatchConstantSignatures; 330 | InOutSignature* psPatchConstantSignatures; 331 | 332 | uint32_t ui32NumResourceBindings; 333 | ResourceBinding* psResourceBindings; 334 | 335 | uint32_t ui32NumConstantBuffers; 336 | ConstantBuffer* psConstantBuffers; 337 | ConstantBuffer* psThisPointerConstBuffer; 338 | 339 | uint32_t ui32NumClassTypes; 340 | ClassType* psClassTypes; 341 | 342 | uint32_t ui32NumClassInstances; 343 | ClassInstance* psClassInstances; 344 | 345 | //Func table ID to class name ID. 346 | std::map aui32TableIDToTypeID; 347 | 348 | std::map aui32ResourceMap[RGROUP_COUNT]; 349 | 350 | TESSELLATOR_PARTITIONING eTessPartitioning; 351 | TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; 352 | 353 | ShaderInfo() : 354 | ui32MajorVersion(0), 355 | ui32MinorVersion(0), 356 | psInputSignatures(0), 357 | ui32NumInputSignatures(0), 358 | psOutputSignatures(0), 359 | ui32NumOutputSignatures(0), 360 | psPatchConstantSignatures(0), 361 | ui32NumPatchConstantSignatures(0), 362 | psResourceBindings(0), 363 | ui32NumResourceBindings(0), 364 | ui32NumConstantBuffers(0), 365 | psConstantBuffers(0), 366 | psThisPointerConstBuffer(0), 367 | psClassTypes(0), 368 | ui32NumClassTypes(0), 369 | psClassInstances(0), 370 | ui32NumClassInstances(0), 371 | aui32TableIDToTypeID(), 372 | aui32ResourceMap() 373 | { 374 | } 375 | }; 376 | 377 | typedef enum INTERPOLATION_MODE 378 | { 379 | INTERPOLATION_UNDEFINED = 0, 380 | INTERPOLATION_CONSTANT = 1, 381 | INTERPOLATION_LINEAR = 2, 382 | INTERPOLATION_LINEAR_CENTROID = 3, 383 | INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, 384 | INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, 385 | INTERPOLATION_LINEAR_SAMPLE = 6, 386 | INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, 387 | } INTERPOLATION_MODE; 388 | 389 | #endif 390 | 391 | -------------------------------------------------------------------------------- /BinaryDecompiler/include/hlslcc.hpp: -------------------------------------------------------------------------------- 1 | 2 | extern "C" { 3 | #include "hlslcc.h" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H_ 2 | #define DEBUG_H_ 3 | 4 | #ifdef _DEBUG 5 | #include "assert.h" 6 | #define ASSERT(expr) CustomAssert(expr) 7 | static void CustomAssert(int expression) 8 | { 9 | if(!expression) 10 | { 11 | assert(0); 12 | } 13 | } 14 | #else 15 | #define ASSERT(expr) 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/decode.h: -------------------------------------------------------------------------------- 1 | #ifndef DECODE_H 2 | #define DECODE_H 3 | 4 | #include "structs.h" 5 | 6 | Shader* DecodeDXBC(uint32_t* data); 7 | 8 | //You don't need to call this directly because DecodeDXBC 9 | //will call DecodeDX9BC if the shader looks 10 | //like it is SM1/2/3. 11 | Shader* DecodeDX9BC(const uint32_t* pui32Tokens); 12 | 13 | void UpdateOperandReferences(Shader* psShader, Instruction* psInst); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/languages.h: -------------------------------------------------------------------------------- 1 | #ifndef LANGUAGES_H 2 | #define LANGUAGES_H 3 | 4 | #include "hlslcc.h" 5 | 6 | static int InOutSupported(const GLLang eLang) 7 | { 8 | if(eLang == LANG_ES_100 || eLang == LANG_120) 9 | { 10 | return 0; 11 | } 12 | return 1; 13 | } 14 | 15 | static int WriteToFragData(const GLLang eLang) 16 | { 17 | if(eLang == LANG_ES_100 || eLang == LANG_120) 18 | { 19 | return 1; 20 | } 21 | return 0; 22 | } 23 | 24 | static int ShaderBitEncodingSupported(const GLLang eLang) 25 | { 26 | if(eLang != LANG_ES_300 && eLang < LANG_330) 27 | { 28 | return 0; 29 | } 30 | return 1; 31 | } 32 | 33 | static int HaveOverloadedTextureFuncs(const GLLang eLang) 34 | { 35 | if(eLang == LANG_ES_100 || eLang == LANG_120) 36 | { 37 | return 0; 38 | } 39 | return 1; 40 | } 41 | 42 | //Only enable for ES. 43 | //Not present in 120, ignored in other desktop languages. 44 | static int HavePrecisionQualifers(const GLLang eLang) 45 | { 46 | if(eLang == LANG_ES_100 || eLang == LANG_ES_300) 47 | { 48 | return 1; 49 | } 50 | return 0; 51 | } 52 | 53 | //Only on vertex inputs and pixel outputs. 54 | static int HaveLimitedInOutLocationQualifier(const GLLang eLang) 55 | { 56 | if(eLang >= LANG_330 || eLang == LANG_ES_300) 57 | { 58 | return 1; 59 | } 60 | return 0; 61 | } 62 | 63 | static int HaveInOutLocationQualifier(const GLLang eLang) 64 | { 65 | if(eLang >= LANG_410) 66 | { 67 | return 1; 68 | } 69 | return 0; 70 | } 71 | 72 | //layout(binding = X) uniform {uniformA; uniformB;} 73 | //layout(location = X) uniform uniform_name; 74 | static int HaveUniformBindingsAndLocations(const GLLang eLang) 75 | { 76 | #if defined(WORK_IN_PROGRESS) 77 | if(eLang >= LANG_430) 78 | { 79 | return 1; 80 | } 81 | #endif 82 | return 0; 83 | } 84 | 85 | static int DualSourceBlendSupported(const GLLang eLang) 86 | { 87 | if(eLang >= LANG_330) 88 | { 89 | return 1; 90 | } 91 | return 0; 92 | } 93 | 94 | static int SubroutinesSupported(const GLLang eLang) 95 | { 96 | if(eLang >= LANG_400) 97 | { 98 | return 1; 99 | } 100 | return 0; 101 | } 102 | 103 | //Before 430, flat/smooth/centroid/noperspective must match 104 | //between fragment and its previous stage. 105 | //HLSL bytecode only tells us the interpolation in pixel shader. 106 | static int PixelInterpDependency(const GLLang eLang) 107 | { 108 | if(eLang < LANG_430) 109 | { 110 | return 1; 111 | } 112 | return 0; 113 | } 114 | 115 | static int HaveImageLoadStore(const GLLang eLang) 116 | { 117 | if(eLang >= LANG_420 || eLang == LANG_ES_310) 118 | { 119 | return 1; 120 | } 121 | return 0; 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/reflect.h: -------------------------------------------------------------------------------- 1 | #ifndef REFLECT_H 2 | #define REFLECT_H 3 | 4 | #include "hlslcc.h" 5 | 6 | ResourceGroup ResourceTypeToResourceGroup(ResourceType); 7 | 8 | int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding); 9 | 10 | void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf); 11 | 12 | int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); 13 | 14 | uint32_t ShaderVarSize(ShaderVarType* psType, uint32_t* singularSize); 15 | 16 | int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, 17 | const uint32_t* pui32Swizzle, 18 | ConstantBuffer* psCBuf, 19 | ShaderVarType** ppsShaderVar, 20 | int32_t* pi32Index, 21 | int32_t* pi32Rebase); 22 | 23 | typedef struct 24 | { 25 | uint32_t* pui32Inputs; 26 | uint32_t* pui32Outputs; 27 | uint32_t* pui32Resources; 28 | uint32_t* pui32Interfaces; 29 | uint32_t* pui32Inputs11; 30 | uint32_t* pui32Outputs11; 31 | uint32_t* pui32OutputsWithStreams; 32 | uint32_t* pui32PatchConstants; 33 | } ReflectionChunks; 34 | 35 | void LoadShaderInfo(const uint32_t ui32MajorVersion, 36 | const uint32_t ui32MinorVersion, 37 | const ReflectionChunks* psChunks, 38 | ShaderInfo* psInfo); 39 | 40 | void LoadD3D9ConstantTable(const char* data, 41 | ShaderInfo* psInfo); 42 | 43 | void FreeShaderInfo(ShaderInfo* psShaderInfo); 44 | 45 | #if 0 46 | //--- Utility functions --- 47 | 48 | //Returns 0 if not found, 1 otherwise. 49 | int GetResourceFromName(const char* name, ShaderInfo* psShaderInfo, ResourceBinding* psBinding); 50 | 51 | //These call into OpenGL and modify the uniforms of the currently bound program. 52 | void SetResourceValueF(ResourceBinding* psBinding, float* value); 53 | void SetResourceValueI(ResourceBinding* psBinding, int* value); 54 | void SetResourceValueStr(ResourceBinding* psBinding, char* value); //Used for interfaces/subroutines. Also for constant buffers? 55 | 56 | void CreateUniformBufferObjectFromResource(ResourceBinding* psBinding, uint32_t* ui32GLHandle); 57 | //------------------------ 58 | #endif 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/shaderLimits.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef HLSLCC_SHADER_LIMITS_H 3 | #define HLSLCC_SHADER_LIMITS_H 4 | 5 | enum {MAX_SHADER_VEC4_OUTPUT = 512}; 6 | enum {MAX_SHADER_VEC4_INPUT = 512}; 7 | enum {MAX_TEXTURES = 128}; 8 | enum {MAX_FUNCTION_BODIES = 1024}; 9 | enum {MAX_CLASS_TYPES = 1024}; 10 | enum {MAX_FUNCTION_POINTERS = 128}; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/structs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "hlslcc.h" 7 | 8 | #include "internal_includes/tokens.h" 9 | #include "internal_includes/reflect.h" 10 | 11 | enum{ MAX_SUB_OPERANDS = 3}; 12 | 13 | struct Operand 14 | { 15 | int iExtended; 16 | OPERAND_TYPE eType; 17 | OPERAND_MODIFIER eModifier; 18 | OPERAND_MIN_PRECISION eMinPrecision; 19 | int iIndexDims; 20 | int indexRepresentation[4]; 21 | int writeMask; 22 | int iGSInput; 23 | int iWriteMaskEnabled; 24 | 25 | int iNumComponents; 26 | 27 | OPERAND_4_COMPONENT_SELECTION_MODE eSelMode; 28 | uint32_t ui32CompMask; 29 | uint32_t ui32Swizzle; 30 | uint32_t aui32Swizzle[4]; 31 | 32 | uint32_t aui32ArraySizes[3]; 33 | uint32_t ui32RegisterNumber; 34 | //If eType is OPERAND_TYPE_IMMEDIATE32 35 | float afImmediates[4]; 36 | //If eType is OPERAND_TYPE_IMMEDIATE64 37 | double adImmediates[4]; 38 | 39 | int iIntegerImmediate; 40 | 41 | SPECIAL_NAME eSpecialName; 42 | std::string specialName; 43 | 44 | OPERAND_INDEX_REPRESENTATION eIndexRep[3]; 45 | 46 | Operand* psSubOperand[MAX_SUB_OPERANDS]; 47 | 48 | //One type for each component. 49 | SHADER_VARIABLE_TYPE aeDataType[4]; 50 | #ifdef _DEBUG 51 | uint64_t id; 52 | #endif 53 | }; 54 | 55 | struct Instruction 56 | { 57 | OPCODE_TYPE eOpcode; 58 | INSTRUCTION_TEST_BOOLEAN eBooleanTestType; 59 | COMPARISON_DX9 eDX9TestType; 60 | uint32_t ui32SyncFlags; 61 | uint32_t ui32NumOperands; 62 | uint32_t ui32FirstSrc; 63 | Operand asOperands[6]; 64 | uint32_t bSaturate; 65 | uint32_t ui32FuncIndexWithinInterface; 66 | RESINFO_RETURN_TYPE eResInfoReturnType; 67 | 68 | int bAddressOffset; 69 | int iUAddrOffset; 70 | int iVAddrOffset; 71 | int iWAddrOffset; 72 | RESOURCE_RETURN_TYPE xType, yType, zType, wType; 73 | RESOURCE_DIMENSION eResDim; 74 | 75 | #ifdef _DEBUG 76 | uint64_t id; 77 | #endif 78 | }; 79 | 80 | enum{ MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE = 1024}; 81 | 82 | struct ICBVec4 { 83 | uint32_t a; 84 | uint32_t b; 85 | uint32_t c; 86 | uint32_t d; 87 | }; 88 | 89 | struct Declaration 90 | { 91 | OPCODE_TYPE eOpcode; 92 | 93 | uint32_t ui32NumOperands; 94 | 95 | Operand asOperands[2]; 96 | 97 | ICBVec4 asImmediateConstBuffer[MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE]; 98 | //The declaration can set one of these 99 | //values depending on the opcode. 100 | union { 101 | uint32_t ui32GlobalFlags; 102 | uint32_t ui32NumTemps; 103 | RESOURCE_DIMENSION eResourceDimension; 104 | INTERPOLATION_MODE eInterpolation; 105 | PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology; 106 | PRIMITIVE eInputPrimitive; 107 | uint32_t ui32MaxOutputVertexCount; 108 | TESSELLATOR_DOMAIN eTessDomain; 109 | TESSELLATOR_PARTITIONING eTessPartitioning; 110 | TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; 111 | uint32_t aui32WorkGroupSize[3]; 112 | //Fork phase index followed by the instance count. 113 | uint32_t aui32HullPhaseInstanceInfo[2]; 114 | float fMaxTessFactor; 115 | uint32_t ui32IndexRange; 116 | uint32_t ui32GSInstanceCount; 117 | 118 | struct Interface_TAG 119 | { 120 | uint32_t ui32InterfaceID; 121 | uint32_t ui32NumFuncTables; 122 | uint32_t ui32ArraySize; 123 | } interface; 124 | } value; 125 | 126 | struct UAV_TAG 127 | { 128 | uint32_t ui32GloballyCoherentAccess; 129 | uint32_t ui32BufferSize; 130 | uint8_t bCounter; 131 | RESOURCE_RETURN_TYPE Type; 132 | } sUAV; 133 | 134 | struct TGSM 135 | { 136 | uint32_t ui32Stride; 137 | uint32_t ui32Count; 138 | } sTGSM; 139 | 140 | uint32_t ui32TableLength; 141 | 142 | uint32_t ui32IsShadowTex; 143 | 144 | }; 145 | 146 | static const uint32_t MAIN_PHASE = 0; 147 | static const uint32_t HS_GLOBAL_DECL = 1; 148 | static const uint32_t HS_CTRL_POINT_PHASE = 2; 149 | static const uint32_t HS_FORK_PHASE = 3; 150 | static const uint32_t HS_JOIN_PHASE = 4; 151 | enum{ NUM_PHASES = 5}; 152 | 153 | struct ShaderPhase 154 | { 155 | //How many instances of this phase type are there? 156 | uint32_t ui32InstanceCount; 157 | 158 | std::vector> ppsDecl; 159 | 160 | std::vector> ppsInst; 161 | 162 | ShaderPhase() : 163 | ui32InstanceCount(0) 164 | { 165 | // 3DMigoto backport: Ensure we always have at least one "instance" 166 | ppsDecl.resize(1); 167 | ppsInst.resize(1); 168 | } 169 | }; 170 | 171 | struct Shader 172 | { 173 | uint32_t ui32MajorVersion; 174 | uint32_t ui32MinorVersion; 175 | SHADER_TYPE eShaderType; 176 | 177 | GLLang eTargetLanguage; 178 | 179 | int fp64; 180 | 181 | //DWORDs in program code, including version and length tokens. 182 | uint32_t ui32ShaderLength; 183 | 184 | //Instruction* functions;//non-main subroutines 185 | 186 | std::map aui32FuncTableToFuncPointer; 187 | std::map aui32FuncBodyToFuncTable; 188 | 189 | struct FuncTable { 190 | std::map aui32FuncBodies; 191 | }; 192 | std::map funcTable; 193 | 194 | struct FuncPointer { 195 | std::map aui32FuncTables; 196 | uint32_t ui32NumBodiesPerTable; 197 | }; 198 | std::map funcPointer; 199 | 200 | std::vector ui32NextClassFuncName; 201 | 202 | const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream. 203 | 204 | ShaderPhase asPhase[NUM_PHASES]; 205 | 206 | ShaderInfo *sInfo; 207 | 208 | std::vector abScalarInput; 209 | 210 | std::map aIndexedOutput; 211 | 212 | std::map aIndexedInput; 213 | std::map aIndexedInputParents; 214 | 215 | std::vector aeResourceDims; 216 | 217 | std::vector aiInputDeclaredSize; 218 | 219 | std::vector aiOutputDeclared; 220 | 221 | //Does not track built-in inputs. 222 | std::map abInputReferencedByInstruction; 223 | 224 | //int aiOpcodeUsed[NUM_OPCODES]; 225 | 226 | bool dx9Shader; // 3DMIGOTO ADDITION 227 | uint32_t ui32CurrentVertexOutputStream; 228 | 229 | Shader() : 230 | ui32MajorVersion(0), 231 | ui32MinorVersion(0), 232 | ui32ShaderLength(0), 233 | pui32FirstToken(0), 234 | asPhase(), 235 | aui32FuncTableToFuncPointer(), 236 | aui32FuncBodyToFuncTable(), 237 | funcTable(), 238 | funcPointer(), 239 | ui32NextClassFuncName(), 240 | abScalarInput(), 241 | aIndexedOutput(), 242 | aIndexedInput(), 243 | aIndexedInputParents(), 244 | aeResourceDims(), 245 | aiInputDeclaredSize(), 246 | aiOutputDeclared(), 247 | abInputReferencedByInstruction(), 248 | dx9Shader(false) 249 | { 250 | sInfo = new ShaderInfo(); 251 | } 252 | 253 | ~Shader() 254 | { 255 | delete sInfo; 256 | sInfo = 0; 257 | } 258 | }; 259 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/tokens.h: -------------------------------------------------------------------------------- 1 | #ifndef TOKENS_H 2 | #define TOKENS_H 3 | 4 | #include "hlslcc.h" 5 | 6 | typedef enum 7 | { 8 | INVALID_SHADER = -1, 9 | PIXEL_SHADER, 10 | VERTEX_SHADER, 11 | GEOMETRY_SHADER, 12 | HULL_SHADER, 13 | DOMAIN_SHADER, 14 | COMPUTE_SHADER, 15 | } SHADER_TYPE; 16 | 17 | static SHADER_TYPE DecodeShaderType(uint32_t ui32Token) 18 | { 19 | return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16); 20 | } 21 | 22 | static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token) 23 | { 24 | return (ui32Token & 0x000000f0) >> 4; 25 | } 26 | 27 | static uint32_t DecodeProgramMinorVersion(uint32_t ui32Token) 28 | { 29 | return (ui32Token & 0x0000000f); 30 | } 31 | 32 | static uint32_t DecodeInstructionLength(uint32_t ui32Token) 33 | { 34 | return (ui32Token & 0x7f000000) >> 24; 35 | } 36 | 37 | static uint32_t DecodeIsOpcodeExtended(uint32_t ui32Token) 38 | { 39 | return (ui32Token & 0x80000000) >> 31; 40 | } 41 | 42 | typedef enum EXTENDED_OPCODE_TYPE 43 | { 44 | EXTENDED_OPCODE_EMPTY = 0, 45 | EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, 46 | EXTENDED_OPCODE_RESOURCE_DIM = 2, 47 | EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, 48 | } EXTENDED_OPCODE_TYPE; 49 | 50 | static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token) 51 | { 52 | return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f); 53 | } 54 | 55 | typedef enum RESOURCE_RETURN_TYPE 56 | { 57 | RETURN_TYPE_UNORM = 1, 58 | RETURN_TYPE_SNORM = 2, 59 | RETURN_TYPE_SINT = 3, 60 | RETURN_TYPE_UINT = 4, 61 | RETURN_TYPE_FLOAT = 5, 62 | RETURN_TYPE_MIXED = 6, 63 | RETURN_TYPE_DOUBLE = 7, 64 | RETURN_TYPE_CONTINUED = 8, 65 | RETURN_TYPE_UNUSED = 9, 66 | } RESOURCE_RETURN_TYPE; 67 | 68 | static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) 69 | { 70 | return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF); 71 | } 72 | 73 | static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) 74 | { 75 | return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF); 76 | } 77 | 78 | typedef enum 79 | { 80 | //For DX9 81 | OPCODE_POW = -6, 82 | OPCODE_DP2ADD = -5, 83 | OPCODE_LRP = -4, 84 | OPCODE_ENDREP = -3, 85 | OPCODE_REP = -2, 86 | OPCODE_SPECIAL_DCL_IMMCONST = -1, 87 | 88 | OPCODE_ADD, 89 | OPCODE_AND, 90 | OPCODE_BREAK, 91 | OPCODE_BREAKC, 92 | OPCODE_CALL, 93 | OPCODE_CALLC, 94 | OPCODE_CASE, 95 | OPCODE_CONTINUE, 96 | OPCODE_CONTINUEC, 97 | OPCODE_CUT, 98 | OPCODE_DEFAULT, 99 | OPCODE_DERIV_RTX, 100 | OPCODE_DERIV_RTY, 101 | OPCODE_DISCARD, 102 | OPCODE_DIV, 103 | OPCODE_DP2, 104 | OPCODE_DP3, 105 | OPCODE_DP4, 106 | OPCODE_ELSE, 107 | OPCODE_EMIT, 108 | OPCODE_EMITTHENCUT, 109 | OPCODE_ENDIF, 110 | OPCODE_ENDLOOP, 111 | OPCODE_ENDSWITCH, 112 | OPCODE_EQ, 113 | OPCODE_EXP, 114 | OPCODE_FRC, 115 | OPCODE_FTOI, 116 | OPCODE_FTOU, 117 | OPCODE_GE, 118 | OPCODE_IADD, 119 | OPCODE_IF, 120 | OPCODE_IEQ, 121 | OPCODE_IGE, 122 | OPCODE_ILT, 123 | OPCODE_IMAD, 124 | OPCODE_IMAX, 125 | OPCODE_IMIN, 126 | OPCODE_IMUL, 127 | OPCODE_INE, 128 | OPCODE_INEG, 129 | OPCODE_ISHL, 130 | OPCODE_ISHR, 131 | OPCODE_ITOF, 132 | OPCODE_LABEL, 133 | OPCODE_LD, 134 | OPCODE_LD_MS, 135 | OPCODE_LOG, 136 | OPCODE_LOOP, 137 | OPCODE_LT, 138 | OPCODE_MAD, 139 | OPCODE_MIN, 140 | OPCODE_MAX, 141 | OPCODE_CUSTOMDATA, 142 | OPCODE_MOV, 143 | OPCODE_MOVC, 144 | OPCODE_MUL, 145 | OPCODE_NE, 146 | OPCODE_NOP, 147 | OPCODE_NOT, 148 | OPCODE_OR, 149 | OPCODE_RESINFO, 150 | OPCODE_RET, 151 | OPCODE_RETC, 152 | OPCODE_ROUND_NE, 153 | OPCODE_ROUND_NI, 154 | OPCODE_ROUND_PI, 155 | OPCODE_ROUND_Z, 156 | OPCODE_RSQ, 157 | OPCODE_SAMPLE, 158 | OPCODE_SAMPLE_C, 159 | OPCODE_SAMPLE_C_LZ, 160 | OPCODE_SAMPLE_L, 161 | OPCODE_SAMPLE_D, 162 | OPCODE_SAMPLE_B, 163 | OPCODE_SQRT, 164 | OPCODE_SWITCH, 165 | OPCODE_SINCOS, 166 | OPCODE_UDIV, 167 | OPCODE_ULT, 168 | OPCODE_UGE, 169 | OPCODE_UMUL, 170 | OPCODE_UMAD, 171 | OPCODE_UMAX, 172 | OPCODE_UMIN, 173 | OPCODE_USHR, 174 | OPCODE_UTOF, 175 | OPCODE_XOR, 176 | OPCODE_DCL_RESOURCE, // DCL* opcodes have 177 | OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats. 178 | OPCODE_DCL_SAMPLER, 179 | OPCODE_DCL_INDEX_RANGE, 180 | OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, 181 | OPCODE_DCL_GS_INPUT_PRIMITIVE, 182 | OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, 183 | OPCODE_DCL_INPUT, 184 | OPCODE_DCL_INPUT_SGV, 185 | OPCODE_DCL_INPUT_SIV, 186 | OPCODE_DCL_INPUT_PS, 187 | OPCODE_DCL_INPUT_PS_SGV, 188 | OPCODE_DCL_INPUT_PS_SIV, 189 | OPCODE_DCL_OUTPUT, 190 | OPCODE_DCL_OUTPUT_SGV, 191 | OPCODE_DCL_OUTPUT_SIV, 192 | OPCODE_DCL_TEMPS, 193 | OPCODE_DCL_INDEXABLE_TEMP, 194 | OPCODE_DCL_GLOBAL_FLAGS, 195 | 196 | // ----------------------------------------------- 197 | 198 | OPCODE_RESERVED_10, 199 | 200 | // ---------- DX 10.1 op codes--------------------- 201 | 202 | OPCODE_LOD, 203 | OPCODE_GATHER4, 204 | OPCODE_SAMPLE_POS, 205 | OPCODE_SAMPLE_INFO, 206 | 207 | // ----------------------------------------------- 208 | 209 | // This should be 10.1's version of NUM_OPCODES 210 | OPCODE_RESERVED_10_1, 211 | 212 | // ---------- DX 11 op codes--------------------- 213 | OPCODE_HS_DECLS, // token marks beginning of HS sub-shader 214 | OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader 215 | OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader 216 | OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader 217 | 218 | OPCODE_EMIT_STREAM, 219 | OPCODE_CUT_STREAM, 220 | OPCODE_EMITTHENCUT_STREAM, 221 | OPCODE_INTERFACE_CALL, 222 | 223 | OPCODE_BUFINFO, 224 | OPCODE_DERIV_RTX_COARSE, 225 | OPCODE_DERIV_RTX_FINE, 226 | OPCODE_DERIV_RTY_COARSE, 227 | OPCODE_DERIV_RTY_FINE, 228 | OPCODE_GATHER4_C, 229 | OPCODE_GATHER4_PO, 230 | OPCODE_GATHER4_PO_C, 231 | OPCODE_RCP, 232 | OPCODE_F32TOF16, 233 | OPCODE_F16TOF32, 234 | OPCODE_UADDC, 235 | OPCODE_USUBB, 236 | OPCODE_COUNTBITS, 237 | OPCODE_FIRSTBIT_HI, 238 | OPCODE_FIRSTBIT_LO, 239 | OPCODE_FIRSTBIT_SHI, 240 | OPCODE_UBFE, 241 | OPCODE_IBFE, 242 | OPCODE_BFI, 243 | OPCODE_BFREV, 244 | OPCODE_SWAPC, 245 | 246 | OPCODE_DCL_STREAM, 247 | OPCODE_DCL_FUNCTION_BODY, 248 | OPCODE_DCL_FUNCTION_TABLE, 249 | OPCODE_DCL_INTERFACE, 250 | 251 | OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, 252 | OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, 253 | OPCODE_DCL_TESS_DOMAIN, 254 | OPCODE_DCL_TESS_PARTITIONING, 255 | OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, 256 | OPCODE_DCL_HS_MAX_TESSFACTOR, 257 | OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, 258 | OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, 259 | 260 | OPCODE_DCL_THREAD_GROUP, 261 | OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, 262 | OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, 263 | OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, 264 | OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, 265 | OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, 266 | OPCODE_DCL_RESOURCE_RAW, 267 | OPCODE_DCL_RESOURCE_STRUCTURED, 268 | OPCODE_LD_UAV_TYPED, 269 | OPCODE_STORE_UAV_TYPED, 270 | OPCODE_LD_RAW, 271 | OPCODE_STORE_RAW, 272 | OPCODE_LD_STRUCTURED, 273 | OPCODE_STORE_STRUCTURED, 274 | OPCODE_ATOMIC_AND, 275 | OPCODE_ATOMIC_OR, 276 | OPCODE_ATOMIC_XOR, 277 | OPCODE_ATOMIC_CMP_STORE, 278 | OPCODE_ATOMIC_IADD, 279 | OPCODE_ATOMIC_IMAX, 280 | OPCODE_ATOMIC_IMIN, 281 | OPCODE_ATOMIC_UMAX, 282 | OPCODE_ATOMIC_UMIN, 283 | OPCODE_IMM_ATOMIC_ALLOC, 284 | OPCODE_IMM_ATOMIC_CONSUME, 285 | OPCODE_IMM_ATOMIC_IADD, 286 | OPCODE_IMM_ATOMIC_AND, 287 | OPCODE_IMM_ATOMIC_OR, 288 | OPCODE_IMM_ATOMIC_XOR, 289 | OPCODE_IMM_ATOMIC_EXCH, 290 | OPCODE_IMM_ATOMIC_CMP_EXCH, 291 | OPCODE_IMM_ATOMIC_IMAX, 292 | OPCODE_IMM_ATOMIC_IMIN, 293 | OPCODE_IMM_ATOMIC_UMAX, 294 | OPCODE_IMM_ATOMIC_UMIN, 295 | OPCODE_SYNC, 296 | 297 | OPCODE_DADD, 298 | OPCODE_DMAX, 299 | OPCODE_DMIN, 300 | OPCODE_DMUL, 301 | OPCODE_DEQ, 302 | OPCODE_DGE, 303 | OPCODE_DLT, 304 | OPCODE_DNE, 305 | OPCODE_DMOV, 306 | OPCODE_DMOVC, 307 | OPCODE_DTOF, 308 | OPCODE_FTOD, 309 | 310 | OPCODE_EVAL_SNAPPED, 311 | OPCODE_EVAL_SAMPLE_INDEX, 312 | OPCODE_EVAL_CENTROID, 313 | 314 | OPCODE_DCL_GS_INSTANCE_COUNT, 315 | 316 | OPCODE_ABORT, 317 | OPCODE_DEBUG_BREAK, 318 | 319 | // ----------------------------------------------- 320 | 321 | // This marks the end of D3D11.0 opcodes 322 | OPCODE_RESERVED_11, 323 | 324 | OPCODE_DDIV, 325 | OPCODE_DFMA, 326 | OPCODE_DRCP, 327 | 328 | OPCODE_MSAD, 329 | 330 | OPCODE_DTOI, 331 | OPCODE_DTOU, 332 | OPCODE_ITOD, 333 | OPCODE_UTOD, 334 | 335 | // ----------------------------------------------- 336 | 337 | // This marks the end of D3D11.1 opcodes 338 | OPCODE_RESERVED_11_1, 339 | 340 | NUM_OPCODES, 341 | OPCODE_INVAILD = NUM_OPCODES, 342 | } OPCODE_TYPE; 343 | 344 | static OPCODE_TYPE DecodeOpcodeType(uint32_t ui32Token) 345 | { 346 | return (OPCODE_TYPE)(ui32Token & 0x00007ff); 347 | } 348 | 349 | typedef enum 350 | { 351 | INDEX_0D, 352 | INDEX_1D, 353 | INDEX_2D, 354 | INDEX_3D, 355 | } OPERAND_INDEX_DIMENSION; 356 | 357 | static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token) 358 | { 359 | return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20); 360 | } 361 | 362 | typedef enum OPERAND_TYPE 363 | { 364 | OPERAND_TYPE_SPECIAL_FRONTFACE = -11, // 3DMIGOTO ADDITION (should this be upstreamed?) 365 | OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10, 366 | OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9, 367 | OPERAND_TYPE_SPECIAL_TEXCOORD = -8, 368 | OPERAND_TYPE_SPECIAL_POSITION = -7, 369 | OPERAND_TYPE_SPECIAL_FOG = -6, 370 | OPERAND_TYPE_SPECIAL_POINTSIZE = -5, 371 | OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR = -4, 372 | OPERAND_TYPE_SPECIAL_OUTBASECOLOUR = -3, 373 | OPERAND_TYPE_SPECIAL_ADDRESS = -2, 374 | OPERAND_TYPE_SPECIAL_IMMCONST = -1, 375 | OPERAND_TYPE_TEMP = 0, // Temporary Register File 376 | OPERAND_TYPE_INPUT = 1, // General Input Register File 377 | OPERAND_TYPE_OUTPUT = 2, // General Output Register File 378 | OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable) 379 | OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s) 380 | // If for example, operand token bits 381 | // [01:00]==OPERAND_4_COMPONENT, 382 | // this means that the operand type: 383 | // OPERAND_TYPE_IMMEDIATE32 384 | // results in 4 additional 32bit 385 | // DWORDS present for the operand. 386 | OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO 387 | OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state 388 | OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture) 389 | OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer 390 | OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer 391 | OPERAND_TYPE_LABEL = 10, // Label 392 | OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID 393 | OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth 394 | OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations 395 | // Below Are operands new in DX 10.1 396 | OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources 397 | OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar) 398 | // Below Are operands new in DX 11 399 | OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource 400 | OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition 401 | OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class 402 | OPERAND_TYPE_INTERFACE = 19, // Reference to an interface 403 | OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function 404 | OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function 405 | OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is 406 | OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID 407 | OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID 408 | OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them) 409 | OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them) 410 | OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them) 411 | OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point 412 | OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer 413 | OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u# 414 | OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g# 415 | OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID 416 | OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID 417 | OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group 418 | OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input 419 | OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value. 420 | OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID 421 | OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth 422 | OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth 423 | OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter 424 | } OPERAND_TYPE; 425 | 426 | static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token) 427 | { 428 | return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12); 429 | } 430 | 431 | static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token) 432 | { 433 | return (SPECIAL_NAME)(ui32Token & 0x0000ffff); 434 | } 435 | 436 | typedef enum OPERAND_INDEX_REPRESENTATION 437 | { 438 | OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD 439 | OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs 440 | // (HI32:LO32) 441 | OPERAND_INDEX_RELATIVE = 2, // Extra operand 442 | OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by 443 | // extra operand 444 | OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS 445 | // (HI32:LO32) followed 446 | // by extra operand 447 | } OPERAND_INDEX_REPRESENTATION; 448 | 449 | static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token) 450 | { 451 | return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3))); 452 | } 453 | 454 | typedef enum OPERAND_NUM_COMPONENTS 455 | { 456 | OPERAND_0_COMPONENT = 0, 457 | OPERAND_1_COMPONENT = 1, 458 | OPERAND_4_COMPONENT = 2, 459 | OPERAND_N_COMPONENT = 3 // unused for now 460 | } OPERAND_NUM_COMPONENTS; 461 | 462 | static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token) 463 | { 464 | return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003); 465 | } 466 | 467 | typedef enum OPERAND_4_COMPONENT_SELECTION_MODE 468 | { 469 | OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components 470 | OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components 471 | OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components 472 | } OPERAND_4_COMPONENT_SELECTION_MODE; 473 | 474 | static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token) 475 | { 476 | return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2); 477 | } 478 | 479 | #define OPERAND_4_COMPONENT_MASK_X 0x00000001 480 | #define OPERAND_4_COMPONENT_MASK_Y 0x00000002 481 | #define OPERAND_4_COMPONENT_MASK_Z 0x00000004 482 | #define OPERAND_4_COMPONENT_MASK_W 0x00000008 483 | #define OPERAND_4_COMPONENT_MASK_R OPERAND_4_COMPONENT_MASK_X 484 | #define OPERAND_4_COMPONENT_MASK_G OPERAND_4_COMPONENT_MASK_Y 485 | #define OPERAND_4_COMPONENT_MASK_B OPERAND_4_COMPONENT_MASK_Z 486 | #define OPERAND_4_COMPONENT_MASK_A OPERAND_4_COMPONENT_MASK_W 487 | #define OPERAND_4_COMPONENT_MASK_ALL 0x0000000f 488 | 489 | static uint32_t DecodeOperand4CompMask(uint32_t ui32Token) 490 | { 491 | return (uint32_t)((ui32Token & 0x000000f0) >> 4); 492 | } 493 | 494 | static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token) 495 | { 496 | return (uint32_t)((ui32Token & 0x00000ff0) >> 4); 497 | } 498 | 499 | static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token) 500 | { 501 | return (uint32_t)((ui32Token & 0x00000030) >> 4); 502 | } 503 | 504 | #define OPERAND_4_COMPONENT_X 0 505 | #define OPERAND_4_COMPONENT_Y 1 506 | #define OPERAND_4_COMPONENT_Z 2 507 | #define OPERAND_4_COMPONENT_W 3 508 | 509 | static uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/); 510 | 511 | static uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X<<2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6))); 512 | static uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6))); 513 | static uint32_t ZZZZ_SWIZZLE = (((OPERAND_4_COMPONENT_Z) | (OPERAND_4_COMPONENT_Z<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_Z << 6))); 514 | static uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMPONENT_W<<2) | (OPERAND_4_COMPONENT_W << 4) | (OPERAND_4_COMPONENT_W << 6))); 515 | 516 | static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp) 517 | { 518 | return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3); 519 | } 520 | 521 | typedef enum RESOURCE_DIMENSION 522 | { 523 | RESOURCE_DIMENSION_UNKNOWN = 0, 524 | RESOURCE_DIMENSION_BUFFER = 1, 525 | RESOURCE_DIMENSION_TEXTURE1D = 2, 526 | RESOURCE_DIMENSION_TEXTURE2D = 3, 527 | RESOURCE_DIMENSION_TEXTURE2DMS = 4, 528 | RESOURCE_DIMENSION_TEXTURE3D = 5, 529 | RESOURCE_DIMENSION_TEXTURECUBE = 6, 530 | RESOURCE_DIMENSION_TEXTURE1DARRAY = 7, 531 | RESOURCE_DIMENSION_TEXTURE2DARRAY = 8, 532 | RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 9, 533 | RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, 534 | RESOURCE_DIMENSION_RAW_BUFFER = 11, 535 | RESOURCE_DIMENSION_STRUCTURED_BUFFER = 12, 536 | } RESOURCE_DIMENSION; 537 | 538 | static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token) 539 | { 540 | return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11); 541 | } 542 | 543 | static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token) 544 | { 545 | return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6); 546 | } 547 | 548 | typedef enum INSTRUCTION_TEST_BOOLEAN 549 | { 550 | INSTRUCTION_TEST_ZERO = 0, 551 | INSTRUCTION_TEST_NONZERO = 1 552 | } INSTRUCTION_TEST_BOOLEAN; 553 | 554 | static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token) 555 | { 556 | return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18); 557 | } 558 | 559 | static uint32_t DecodeIsOperandExtended(uint32_t ui32Token) 560 | { 561 | return (ui32Token & 0x80000000) >> 31; 562 | } 563 | 564 | typedef enum EXTENDED_OPERAND_TYPE 565 | { 566 | EXTENDED_OPERAND_EMPTY = 0, 567 | EXTENDED_OPERAND_MODIFIER = 1, 568 | } EXTENDED_OPERAND_TYPE; 569 | 570 | static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token) 571 | { 572 | return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f); 573 | } 574 | 575 | typedef enum OPERAND_MODIFIER 576 | { 577 | OPERAND_MODIFIER_NONE = 0, 578 | OPERAND_MODIFIER_NEG = 1, 579 | OPERAND_MODIFIER_ABS = 2, 580 | OPERAND_MODIFIER_ABSNEG = 3, 581 | } OPERAND_MODIFIER; 582 | 583 | static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token) 584 | { 585 | return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6); 586 | } 587 | 588 | static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11); 589 | static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12); 590 | static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13); 591 | static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14); 592 | static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15); 593 | static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16); 594 | static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17); 595 | static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18); 596 | 597 | static uint32_t DecodeGlobalFlags(uint32_t ui32Token) 598 | { 599 | return (uint32_t)(ui32Token & 0x00fff800); 600 | } 601 | 602 | static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token) 603 | { 604 | return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11); 605 | } 606 | 607 | 608 | typedef enum PRIMITIVE_TOPOLOGY 609 | { 610 | PRIMITIVE_TOPOLOGY_UNDEFINED = 0, 611 | PRIMITIVE_TOPOLOGY_POINTLIST = 1, 612 | PRIMITIVE_TOPOLOGY_LINELIST = 2, 613 | PRIMITIVE_TOPOLOGY_LINESTRIP = 3, 614 | PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4, 615 | PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5, 616 | // 6 is reserved for legacy triangle fans 617 | // Adjacency values should be equal to (0x8 & non-adjacency): 618 | PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10, 619 | PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11, 620 | PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12, 621 | PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13, 622 | } PRIMITIVE_TOPOLOGY; 623 | 624 | static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token) 625 | { 626 | return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11); 627 | } 628 | 629 | typedef enum PRIMITIVE 630 | { 631 | PRIMITIVE_UNDEFINED = 0, 632 | PRIMITIVE_POINT = 1, 633 | PRIMITIVE_LINE = 2, 634 | PRIMITIVE_TRIANGLE = 3, 635 | // Adjacency values should be equal to (0x4 & non-adjacency): 636 | PRIMITIVE_LINE_ADJ = 6, 637 | PRIMITIVE_TRIANGLE_ADJ = 7, 638 | PRIMITIVE_1_CONTROL_POINT_PATCH = 8, 639 | PRIMITIVE_2_CONTROL_POINT_PATCH = 9, 640 | PRIMITIVE_3_CONTROL_POINT_PATCH = 10, 641 | PRIMITIVE_4_CONTROL_POINT_PATCH = 11, 642 | PRIMITIVE_5_CONTROL_POINT_PATCH = 12, 643 | PRIMITIVE_6_CONTROL_POINT_PATCH = 13, 644 | PRIMITIVE_7_CONTROL_POINT_PATCH = 14, 645 | PRIMITIVE_8_CONTROL_POINT_PATCH = 15, 646 | PRIMITIVE_9_CONTROL_POINT_PATCH = 16, 647 | PRIMITIVE_10_CONTROL_POINT_PATCH = 17, 648 | PRIMITIVE_11_CONTROL_POINT_PATCH = 18, 649 | PRIMITIVE_12_CONTROL_POINT_PATCH = 19, 650 | PRIMITIVE_13_CONTROL_POINT_PATCH = 20, 651 | PRIMITIVE_14_CONTROL_POINT_PATCH = 21, 652 | PRIMITIVE_15_CONTROL_POINT_PATCH = 22, 653 | PRIMITIVE_16_CONTROL_POINT_PATCH = 23, 654 | PRIMITIVE_17_CONTROL_POINT_PATCH = 24, 655 | PRIMITIVE_18_CONTROL_POINT_PATCH = 25, 656 | PRIMITIVE_19_CONTROL_POINT_PATCH = 26, 657 | PRIMITIVE_20_CONTROL_POINT_PATCH = 27, 658 | PRIMITIVE_21_CONTROL_POINT_PATCH = 28, 659 | PRIMITIVE_22_CONTROL_POINT_PATCH = 29, 660 | PRIMITIVE_23_CONTROL_POINT_PATCH = 30, 661 | PRIMITIVE_24_CONTROL_POINT_PATCH = 31, 662 | PRIMITIVE_25_CONTROL_POINT_PATCH = 32, 663 | PRIMITIVE_26_CONTROL_POINT_PATCH = 33, 664 | PRIMITIVE_27_CONTROL_POINT_PATCH = 34, 665 | PRIMITIVE_28_CONTROL_POINT_PATCH = 35, 666 | PRIMITIVE_29_CONTROL_POINT_PATCH = 36, 667 | PRIMITIVE_30_CONTROL_POINT_PATCH = 37, 668 | PRIMITIVE_31_CONTROL_POINT_PATCH = 38, 669 | PRIMITIVE_32_CONTROL_POINT_PATCH = 39, 670 | } PRIMITIVE; 671 | 672 | static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token) 673 | { 674 | return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11); 675 | } 676 | 677 | static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token) 678 | { 679 | return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11); 680 | } 681 | 682 | typedef enum TESSELLATOR_DOMAIN 683 | { 684 | TESSELLATOR_DOMAIN_UNDEFINED = 0, 685 | TESSELLATOR_DOMAIN_ISOLINE = 1, 686 | TESSELLATOR_DOMAIN_TRI = 2, 687 | TESSELLATOR_DOMAIN_QUAD = 3 688 | } TESSELLATOR_DOMAIN; 689 | 690 | static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token) 691 | { 692 | return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11); 693 | } 694 | 695 | static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token) 696 | { 697 | return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11); 698 | } 699 | 700 | static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800; 701 | static const uint32_t SYNC_THREAD_GROUP_SHARED_MEMORY = 0x00001000; 702 | static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP = 0x00002000; 703 | static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000; 704 | 705 | static uint32_t DecodeSyncFlags(uint32_t ui32Token) 706 | { 707 | return ui32Token & 0x00007800; 708 | } 709 | 710 | // The number of types that implement this interface 711 | static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token) 712 | { 713 | return (uint32_t)((ui32Token & 0x0000ffff) >> 0); 714 | } 715 | 716 | // The number of interfaces that are defined in this array. 717 | static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token) 718 | { 719 | return (uint32_t)((ui32Token & 0xffff0000) >> 16); 720 | } 721 | 722 | typedef enum CUSTOMDATA_CLASS 723 | { 724 | CUSTOMDATA_COMMENT = 0, 725 | CUSTOMDATA_DEBUGINFO, 726 | CUSTOMDATA_OPAQUE, 727 | CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, 728 | CUSTOMDATA_SHADER_MESSAGE, 729 | } CUSTOMDATA_CLASS; 730 | 731 | static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token) 732 | { 733 | return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11); 734 | } 735 | 736 | static uint32_t DecodeInstructionSaturate(uint32_t ui32Token) 737 | { 738 | return (ui32Token & 0x00002000) ? 1 : 0; 739 | } 740 | 741 | typedef enum OPERAND_MIN_PRECISION 742 | { 743 | OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision 744 | // for the shader model 745 | OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float 746 | OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float 747 | OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer 748 | OPERAND_MIN_PRECISION_UINT_16 = 5, // Min 16 bit/comp. unsigned integer 749 | } OPERAND_MIN_PRECISION; 750 | 751 | static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token) 752 | { 753 | return (ui32Token & 0x0001C000) >> 14; 754 | } 755 | 756 | static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token) 757 | { 758 | return ((ui32Token & 0x0001f800) >> 11); 759 | } 760 | 761 | typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD 762 | { 763 | IMMEDIATE_ADDRESS_OFFSET_U = 0, 764 | IMMEDIATE_ADDRESS_OFFSET_V = 1, 765 | IMMEDIATE_ADDRESS_OFFSET_W = 2, 766 | } IMMEDIATE_ADDRESS_OFFSET_COORD; 767 | 768 | 769 | #define IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&3)) 770 | #define IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord)))); 775 | } 776 | 777 | // UAV access scope flags 778 | static const uint32_t GLOBALLY_COHERENT_ACCESS = 0x00010000; 779 | static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token) 780 | { 781 | return ui32Token & 0x00010000; 782 | } 783 | 784 | 785 | typedef enum RESINFO_RETURN_TYPE 786 | { 787 | RESINFO_INSTRUCTION_RETURN_FLOAT = 0, 788 | RESINFO_INSTRUCTION_RETURN_RCPFLOAT = 1, 789 | RESINFO_INSTRUCTION_RETURN_UINT = 2 790 | } RESINFO_RETURN_TYPE; 791 | 792 | static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token) 793 | { 794 | return (RESINFO_RETURN_TYPE)((ui32Token & 0x00001800) >> 11); 795 | } 796 | 797 | #include "tokensDX9.h" 798 | 799 | #endif 800 | -------------------------------------------------------------------------------- /BinaryDecompiler/internal_includes/tokensDX9.h: -------------------------------------------------------------------------------- 1 | 2 | static const uint32_t D3D9SHADER_TYPE_VERTEX = 0xFFFE0000; 3 | static const uint32_t D3D9SHADER_TYPE_PIXEL = 0xFFFF0000; 4 | 5 | static SHADER_TYPE DecodeShaderTypeDX9(const uint32_t ui32Token) 6 | { 7 | uint32_t ui32Type = ui32Token & 0xFFFF0000; 8 | if(ui32Type == D3D9SHADER_TYPE_VERTEX) 9 | return VERTEX_SHADER; 10 | 11 | if(ui32Type == D3D9SHADER_TYPE_PIXEL) 12 | return PIXEL_SHADER; 13 | 14 | return INVALID_SHADER; 15 | } 16 | 17 | static uint32_t DecodeProgramMajorVersionDX9(const uint32_t ui32Token) 18 | { 19 | return ((ui32Token)>>8)&0xFF; 20 | } 21 | 22 | static uint32_t DecodeProgramMinorVersionDX9(const uint32_t ui32Token) 23 | { 24 | return ui32Token & 0xFF; 25 | } 26 | 27 | typedef enum 28 | { 29 | OPCODE_DX9_NOP = 0, 30 | OPCODE_DX9_MOV , 31 | OPCODE_DX9_ADD , 32 | OPCODE_DX9_SUB , 33 | OPCODE_DX9_MAD , 34 | OPCODE_DX9_MUL , 35 | OPCODE_DX9_RCP , 36 | OPCODE_DX9_RSQ , 37 | OPCODE_DX9_DP3 , 38 | OPCODE_DX9_DP4 , 39 | OPCODE_DX9_MIN , 40 | OPCODE_DX9_MAX , 41 | OPCODE_DX9_SLT , 42 | OPCODE_DX9_SGE , 43 | OPCODE_DX9_EXP , 44 | OPCODE_DX9_LOG , 45 | OPCODE_DX9_LIT , 46 | OPCODE_DX9_DST , 47 | OPCODE_DX9_LRP , 48 | OPCODE_DX9_FRC , 49 | OPCODE_DX9_M4x4 , 50 | OPCODE_DX9_M4x3 , 51 | OPCODE_DX9_M3x4 , 52 | OPCODE_DX9_M3x3 , 53 | OPCODE_DX9_M3x2 , 54 | OPCODE_DX9_CALL , 55 | OPCODE_DX9_CALLNZ , 56 | OPCODE_DX9_LOOP , 57 | OPCODE_DX9_RET , 58 | OPCODE_DX9_ENDLOOP , 59 | OPCODE_DX9_LABEL , 60 | OPCODE_DX9_DCL , 61 | OPCODE_DX9_POW , 62 | OPCODE_DX9_CRS , 63 | OPCODE_DX9_SGN , 64 | OPCODE_DX9_ABS , 65 | OPCODE_DX9_NRM , 66 | OPCODE_DX9_SINCOS , 67 | OPCODE_DX9_REP , 68 | OPCODE_DX9_ENDREP , 69 | OPCODE_DX9_IF , 70 | OPCODE_DX9_IFC , 71 | OPCODE_DX9_ELSE , 72 | OPCODE_DX9_ENDIF , 73 | OPCODE_DX9_BREAK , 74 | OPCODE_DX9_BREAKC , 75 | OPCODE_DX9_MOVA , 76 | OPCODE_DX9_DEFB , 77 | OPCODE_DX9_DEFI , 78 | 79 | OPCODE_DX9_TEXCOORD = 64, 80 | OPCODE_DX9_TEXKILL , 81 | OPCODE_DX9_TEX , 82 | OPCODE_DX9_TEXBEM , 83 | OPCODE_DX9_TEXBEML , 84 | OPCODE_DX9_TEXREG2AR , 85 | OPCODE_DX9_TEXREG2GB , 86 | OPCODE_DX9_TEXM3x2PAD , 87 | OPCODE_DX9_TEXM3x2TEX , 88 | OPCODE_DX9_TEXM3x3PAD , 89 | OPCODE_DX9_TEXM3x3TEX , 90 | OPCODE_DX9_RESERVED0 , 91 | OPCODE_DX9_TEXM3x3SPEC , 92 | OPCODE_DX9_TEXM3x3VSPEC , 93 | OPCODE_DX9_EXPP , 94 | OPCODE_DX9_LOGP , 95 | OPCODE_DX9_CND , 96 | OPCODE_DX9_DEF , 97 | OPCODE_DX9_TEXREG2RGB , 98 | OPCODE_DX9_TEXDP3TEX , 99 | OPCODE_DX9_TEXM3x2DEPTH , 100 | OPCODE_DX9_TEXDP3 , 101 | OPCODE_DX9_TEXM3x3 , 102 | OPCODE_DX9_TEXDEPTH , 103 | OPCODE_DX9_CMP , 104 | OPCODE_DX9_BEM , 105 | OPCODE_DX9_DP2ADD , 106 | OPCODE_DX9_DSX , 107 | OPCODE_DX9_DSY , 108 | OPCODE_DX9_TEXLDD , 109 | OPCODE_DX9_SETP , 110 | OPCODE_DX9_TEXLDL , 111 | OPCODE_DX9_BREAKP , 112 | 113 | OPCODE_DX9_PHASE = 0xFFFD, 114 | OPCODE_DX9_COMMENT = 0xFFFE, 115 | OPCODE_DX9_END = 0xFFFF, 116 | 117 | OPCODE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum 118 | } OPCODE_TYPE_DX9; 119 | 120 | static OPCODE_TYPE_DX9 DecodeOpcodeTypeDX9(const uint32_t ui32Token) 121 | { 122 | return (OPCODE_TYPE_DX9)(ui32Token & 0x0000FFFF); 123 | } 124 | 125 | static uint32_t DecodeInstructionLengthDX9(const uint32_t ui32Token) 126 | { 127 | return (ui32Token & 0x0F000000)>>24; 128 | } 129 | 130 | static uint32_t DecodeCommentLengthDX9(const uint32_t ui32Token) 131 | { 132 | return (ui32Token & 0x7FFF0000)>>16; 133 | } 134 | 135 | static uint32_t DecodeOperandRegisterNumberDX9(const uint32_t ui32Token) 136 | { 137 | return ui32Token & 0x000007FF; 138 | } 139 | 140 | typedef enum 141 | { 142 | OPERAND_TYPE_DX9_TEMP = 0, // Temporary Register File 143 | OPERAND_TYPE_DX9_INPUT = 1, // Input Register File 144 | OPERAND_TYPE_DX9_CONST = 2, // Constant Register File 145 | OPERAND_TYPE_DX9_ADDR = 3, // Address Register (VS) 146 | OPERAND_TYPE_DX9_TEXTURE = 3, // Texture Register File (PS) 147 | OPERAND_TYPE_DX9_RASTOUT = 4, // Rasterizer Register File 148 | OPERAND_TYPE_DX9_ATTROUT = 5, // Attribute Output Register File 149 | OPERAND_TYPE_DX9_TEXCRDOUT = 6, // Texture Coordinate Output Register File 150 | OPERAND_TYPE_DX9_OUTPUT = 6, // Output register file for VS3.0+ 151 | OPERAND_TYPE_DX9_CONSTINT = 7, // Constant Integer Vector Register File 152 | OPERAND_TYPE_DX9_COLOROUT = 8, // Color Output Register File 153 | OPERAND_TYPE_DX9_DEPTHOUT = 9, // Depth Output Register File 154 | OPERAND_TYPE_DX9_SAMPLER = 10, // Sampler State Register File 155 | OPERAND_TYPE_DX9_CONST2 = 11, // Constant Register File 2048 - 4095 156 | OPERAND_TYPE_DX9_CONST3 = 12, // Constant Register File 4096 - 6143 157 | OPERAND_TYPE_DX9_CONST4 = 13, // Constant Register File 6144 - 8191 158 | OPERAND_TYPE_DX9_CONSTBOOL = 14, // Constant Boolean register file 159 | OPERAND_TYPE_DX9_LOOP = 15, // Loop counter register file 160 | OPERAND_TYPE_DX9_TEMPFLOAT16 = 16, // 16-bit float temp register file 161 | OPERAND_TYPE_DX9_MISCTYPE = 17, // Miscellaneous (single) registers. 162 | OPERAND_TYPE_DX9_LABEL = 18, // Label 163 | OPERAND_TYPE_DX9_PREDICATE = 19, // Predicate register 164 | OPERAND_TYPE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum 165 | } OPERAND_TYPE_DX9; 166 | 167 | static OPERAND_TYPE_DX9 DecodeOperandTypeDX9(const uint32_t ui32Token) 168 | { 169 | return (OPERAND_TYPE_DX9)(((ui32Token & 0x70000000) >> 28) | 170 | ((ui32Token & 0x00001800) >> 8)); 171 | } 172 | 173 | static uint32_t CreateOperandTokenDX9(const uint32_t ui32RegNum, const OPERAND_TYPE_DX9 eType) 174 | { 175 | uint32_t ui32Token = ui32RegNum; 176 | ui32Token |= (eType <<28) & 0x70000000; 177 | ui32Token |= (eType <<8) & 0x00001800; 178 | return ui32Token; 179 | } 180 | 181 | typedef enum { 182 | DECLUSAGE_POSITION = 0, 183 | DECLUSAGE_BLENDWEIGHT = 1, 184 | DECLUSAGE_BLENDINDICES = 2, 185 | DECLUSAGE_NORMAL = 3, 186 | DECLUSAGE_PSIZE = 4, 187 | DECLUSAGE_TEXCOORD = 5, 188 | DECLUSAGE_TANGENT = 6, 189 | DECLUSAGE_BINORMAL = 7, 190 | DECLUSAGE_TESSFACTOR = 8, 191 | DECLUSAGE_POSITIONT = 9, 192 | DECLUSAGE_COLOR = 10, 193 | DECLUSAGE_FOG = 11, 194 | DECLUSAGE_DEPTH = 12, 195 | DECLUSAGE_SAMPLE = 13 196 | } DECLUSAGE_DX9; 197 | 198 | static DECLUSAGE_DX9 DecodeUsageDX9(const uint32_t ui32Token) 199 | { 200 | return (DECLUSAGE_DX9) (ui32Token & 0x0000000f); 201 | } 202 | 203 | static uint32_t DecodeUsageIndexDX9(const uint32_t ui32Token) 204 | { 205 | return (ui32Token & 0x000f0000)>>16; 206 | } 207 | 208 | static uint32_t DecodeOperandIsRelativeAddressModeDX9(const uint32_t ui32Token) 209 | { 210 | return ui32Token & (1<<13); 211 | } 212 | 213 | static const uint32_t DX9_SWIZZLE_SHIFT = 16; 214 | #define NO_SWIZZLE_DX9 ((0<>16); 299 | } 300 | -------------------------------------------------------------------------------- /D3D_Shaders/D3D_Shaders.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED} 23 | Win32Proj 24 | D3D_Shaders 25 | 10.0 26 | 27 | 28 | 29 | StaticLibrary 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | true 37 | v142 38 | Unicode 39 | 40 | 41 | Application 42 | false 43 | v142 44 | true 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | true 72 | $(SolutionDir);$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 73 | $(OutDir);$(LibraryPath) 74 | .lib 75 | $(SolutionDir)\x32\$(Configuration)\ 76 | 77 | 78 | true 79 | $(SolutionDir);$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 80 | $(OutDir);$(LibraryPath) 81 | 82 | 83 | false 84 | $(SolutionDir);$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) 85 | $(OutDir);$(LibraryPath) 86 | 87 | 88 | false 89 | $(SolutionDir);$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 90 | $(OutDir);$(LibraryPath) 91 | 92 | 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 99 | MultiThreadedDebug 100 | 101 | 102 | Console 103 | true 104 | D3dcompiler.lib;%(AdditionalDependencies) 105 | $(OutDir)$(TargetName)$(TargetExt) 106 | 107 | 108 | 109 | 110 | 111 | 112 | Level3 113 | Disabled 114 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 115 | MultiThreadedDebug 116 | 117 | 118 | Console 119 | true 120 | D3dcompiler.lib;%(AdditionalDependencies) 121 | $(OutDir)D3D_Shaders.exe 122 | 123 | 124 | 125 | 126 | Level3 127 | 128 | 129 | MaxSpeed 130 | true 131 | true 132 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 133 | MultiThreaded 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | D3dcompiler.lib;%(AdditionalDependencies) 141 | 142 | 143 | 144 | 145 | $(OutDir)$(TargetName)$(TargetExt) 146 | 147 | 148 | 149 | 150 | Level3 151 | 152 | 153 | MaxSpeed 154 | true 155 | true 156 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 157 | MultiThreaded 158 | 159 | 160 | Console 161 | true 162 | true 163 | true 164 | D3dcompiler.lib;%(AdditionalDependencies) 165 | 166 | 167 | 168 | 169 | $(OutDir)$(TargetName)$(TargetExt) 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /D3D_Shaders/D3D_Shaders.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /D3D_Shaders/D3D_Shaders.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /D3D_Shaders/Shaders.cpp: -------------------------------------------------------------------------------- 1 | // Shaders.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | FILE *LogFile = NULL; 14 | bool gLogDebug = false; 15 | 16 | static vector enumerateFiles(string pathName, string filter = "") { 17 | vector files; 18 | WIN32_FIND_DATAA FindFileData; 19 | HANDLE hFind; 20 | string sName = pathName; 21 | sName.append(filter); 22 | hFind = FindFirstFileA(sName.c_str(), &FindFileData); 23 | if (hFind != INVALID_HANDLE_VALUE) { 24 | string fName = pathName; 25 | fName.append(FindFileData.cFileName); 26 | files.push_back(fName); 27 | while (FindNextFileA(hFind, &FindFileData)) { 28 | fName = pathName; 29 | fName.append(FindFileData.cFileName); 30 | files.push_back(fName); 31 | } 32 | FindClose(hFind); 33 | } 34 | return files; 35 | } 36 | 37 | static vector readFile(string fileName) { 38 | vector buffer; 39 | FILE* f; 40 | fopen_s(&f, fileName.c_str(), "rb"); 41 | if (f != NULL) { 42 | fseek(f, 0L, SEEK_END); 43 | int fileSize = ftell(f); 44 | buffer.resize(fileSize); 45 | fseek(f, 0L, SEEK_SET); 46 | size_t numRead = fread(buffer.data(), 1, buffer.size(), f); 47 | fclose(f); 48 | } 49 | return buffer; 50 | } 51 | 52 | int _tmain(int argc, _TCHAR* argv[]) 53 | { 54 | int shaderNo = 1; 55 | vector gameNames; 56 | string pathName; 57 | vector files; 58 | FILE* f; 59 | char cwd[MAX_PATH]; 60 | char gamebuffer[10000]; 61 | 62 | if (!_getcwd(cwd, MAX_PATH)) 63 | return 1; 64 | vector lines; 65 | fopen_s(&f, "gamelist.txt", "rb"); 66 | if (f) { 67 | size_t fr = ::fread(gamebuffer, 1, 10000, f); 68 | fclose(f); 69 | lines = stringToLines(gamebuffer, fr); 70 | } 71 | 72 | if (lines.size() > 0) { 73 | for (auto i = lines.begin(); i != lines.end(); i++) { 74 | gameNames.push_back(*i); 75 | } 76 | } else { 77 | gameNames.push_back(cwd); 78 | } 79 | for (DWORD i = 0; i < gameNames.size(); i++) { 80 | string gameName = gameNames[i]; 81 | cout << gameName << ":" << endl; 82 | 83 | int progress = 0; 84 | pathName = gameName; 85 | pathName.append("\\ShaderCache\\"); 86 | files = enumerateFiles(pathName, "????????????????-??.bin"); 87 | if (files.size() > 0) { 88 | cout << "bin->asm: "; 89 | for (DWORD i = 0; i < files.size(); i++) { 90 | string fileName = files[i]; 91 | 92 | vector ASM; 93 | disassembler(&readFile(fileName), &ASM, NULL); 94 | 95 | fileName.erase(fileName.size() - 3, 3); 96 | fileName.append("txt"); 97 | FILE* f; 98 | fopen_s(&f, fileName.c_str(), "wb"); 99 | fwrite(ASM.data(), 1, ASM.size(), f); 100 | fclose(f); 101 | 102 | int newProgress = (int)(50.0 * i / files.size()); 103 | if (newProgress > progress) { 104 | cout << "."; 105 | progress++; 106 | } 107 | } 108 | } 109 | cout << endl; 110 | 111 | progress = 0; 112 | pathName = gameName; 113 | pathName.append("\\ShaderCache\\"); 114 | files = enumerateFiles(pathName, "????????????????-??.txt"); 115 | if (files.size() > 0) { 116 | cout << "asm->cbo: "; 117 | for (DWORD i = 0; i < files.size(); i++) { 118 | string fileName = files[i]; 119 | 120 | auto ASM = readFile(fileName); 121 | fileName.erase(fileName.size() - 3, 3); 122 | fileName.append("bin"); 123 | auto BIN = readFile(fileName); 124 | 125 | auto CBO = assembler((vector*)&ASM, BIN); 126 | 127 | fileName.erase(fileName.size() - 3, 3); 128 | fileName.append("cbo"); 129 | FILE* f; 130 | fopen_s(&f, fileName.c_str(), "wb"); 131 | if (f) { 132 | fwrite(CBO.data(), 1, CBO.size(), f); 133 | fclose(f); 134 | } 135 | 136 | int newProgress = (int)(50.0 * i / files.size()); 137 | if (newProgress > progress) { 138 | cout << "."; 139 | progress++; 140 | } 141 | } 142 | } 143 | cout << endl; 144 | 145 | progress = 0; 146 | pathName = gameNames[i]; 147 | pathName.append("\\Mark\\"); 148 | files = enumerateFiles(pathName, "*.bin"); 149 | if (files.size() > 0) { 150 | cout << "bin->asm validate: "; 151 | for (DWORD i = 0; i < files.size(); i++) { 152 | string fileName = files[i]; 153 | 154 | vector ASM; 155 | disassembler(&readFile(fileName), &ASM, NULL); 156 | 157 | fileName.erase(fileName.size() - 3, 3); 158 | fileName.append("txt"); 159 | FILE* f; 160 | fopen_s(&f, fileName.c_str(), "wb"); 161 | if (f) { 162 | fwrite(ASM.data(), 1, ASM.size(), f); 163 | fclose(f); 164 | } 165 | 166 | int newProgress = (int)(50.0 * i / files.size()); 167 | if (newProgress > progress) { 168 | cout << "."; 169 | progress++; 170 | } 171 | } 172 | } 173 | cout << endl; 174 | 175 | writeLUT(); 176 | } 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /D3D_Shaders/SignatureParser.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "log.h" 4 | #include "shader.h" 5 | 6 | #define SFI_RAW_STRUCT_BUF (1LL<<1) 7 | #define SFI_MIN_PRECISION (1LL<<4) 8 | 9 | // Force the use of SHader EXtended bytecode when certain features are in use, 10 | // such as partial or double precision. This is likely incomplete. 11 | #define SFI_FORCE_SHEX (SFI_RAW_STRUCT_BUF | SFI_MIN_PRECISION) 12 | 13 | // VS2013 BUG WORKAROUND: Make sure this class has a unique type name! 14 | class AsmSignatureParseError : public exception {} parseError; 15 | 16 | static string next_line(string *shader, size_t *pos) 17 | { 18 | size_t start_pos = *pos; 19 | size_t end_pos; 20 | 21 | // Skip preceeding whitespace: 22 | start_pos = shader->find_first_not_of(" \t\r", start_pos); 23 | 24 | // Blank line at end of file: 25 | if (start_pos == shader->npos) { 26 | *pos = shader->npos; 27 | return ""; 28 | } 29 | 30 | // Find newline, update parent pointer: 31 | *pos = shader->find('\n', start_pos); 32 | 33 | // Skip trailing whitespace (will pad it later during parsing, but 34 | // can't rely on whitespace here so still strip it): 35 | end_pos = shader->find_last_not_of(" \t\n\r", *pos) + 1; 36 | 37 | if (*pos != shader->npos) 38 | (*pos)++; // Brackets are important 39 | 40 | return shader->substr(start_pos, end_pos - start_pos); 41 | } 42 | 43 | struct format_type { 44 | uint32_t format; 45 | uint32_t min_precision; 46 | char *name; 47 | }; 48 | 49 | static struct format_type format_names[] = { 50 | {0, 0, "unknown" }, 51 | {1, 0, "uint" }, 52 | {1, 5, "min16u" }, // min16uint 53 | {2, 0, "int" }, 54 | {2, 4, "min16i" }, // min16int *AND* min12int as of d3dcompiler47.dll 55 | {3, 0, "float" }, 56 | {3, 1, "min16f" }, // min16float 57 | {3, 2, "min2_8f" }, // min10float 58 | }; 59 | 60 | static void parse_format(char *format, uint32_t *format_number, uint32_t *min_precision) 61 | { 62 | uint32_t i; 63 | 64 | for (i = 0; i < ARRAYSIZE(format_names); i++) { 65 | if (!strcmp(format, format_names[i].name)) { 66 | *format_number = format_names[i].format; 67 | *min_precision = format_names[i].min_precision; 68 | return; 69 | } 70 | } 71 | 72 | throw parseError; 73 | } 74 | 75 | struct svt { 76 | uint32_t val; 77 | char *short_name; 78 | }; 79 | 80 | static struct svt system_value_abbreviations[] = { 81 | { 0, "NONE", }, // TEXCOORDs, input position to VS 82 | { 0, "TARGET", }, // SV_Target 83 | 84 | { 1, "POS", }, // SV_Position 85 | { 2, "CLIPDST", }, // SV_ClipDistance 86 | { 3, "CULLDST", }, // SV_CullDistance 87 | { 4, "RTINDEX", }, // SV_RenderTargetArrayIndex 88 | { 5, "VPINDEX", }, // SV_ViewportArrayIndex 89 | { 6, "VERTID", }, // SV_VertexID 90 | { 7, "PRIMID", }, // SV_PrimitiveID, register = " primID" 91 | { 8, "INSTID", }, // SV_InstanceID 92 | { 9, "FFACE", }, // SV_IsFrontFace 93 | { 10, "SAMPLE", }, // SV_SampleIndex 94 | 95 | // Tesselation domain/hull shaders. XXX: These numbers don't match up 96 | // with BinaryDecompiler, but I got them myself, so I am 100% certain 97 | // they are right, but perhaps I am missing something (Update - now 98 | // pretty sure the values in BinaryDecompiler are those used in the 99 | // bytecode, whereas these values are used in the signatures): 100 | { 11, "QUADEDGE", }, // SV_TessFactor with [domain("quad")] 101 | { 12, "QUADINT", }, // SV_InsideTessFactor with [domain("quad")] 102 | { 13, "TRIEDGE", }, // SV_TessFactor with [domain("tri")] 103 | { 14, "TRIINT", }, // SV_InsideTessFactor with [domain("tri")] 104 | { 15, "LINEDET", }, 105 | { 16, "LINEDEN", }, 106 | 107 | // System values using SPRs (special purpose registers). These only 108 | // ever seem to show up in the output signature - any used as inputs is 109 | // not in the input signature, and uses a 'v' prefix instead of 'o'. 110 | // Mask = "N/A" (0x1) 111 | // Register = "oSomething" (0xffffffff) 112 | // Used = "YES" (0xe) / "NO" (0x0) 113 | { 0, "DEPTH" }, // SV_Depth, oDepth 114 | { 0, "COVERAGE", }, // SV_Coverage, oMask 115 | { 0, "DEPTHGE" }, // SV_DepthGreaterEqual, oDepthGE 116 | { 0, "DEPTHLE" }, // SV_DepthLessEqual, oDepthLE 117 | 118 | // Only available in DX12 / shader model 5.1 / d3dcompiler47.dll: 119 | { 0, "STENCILREF" }, // SV_StencilRef, oStencilRef 120 | { 0, "INNERCOV" }, // SV_InnerCoverage, not sure what register is listed as - "special"? 121 | 122 | // Some other semantics which don't appear here (e.g. SV_GSInstanceID, 123 | // any of the compute shader thread IDs) are not present in these 124 | // sections. 125 | }; 126 | 127 | static uint32_t parse_system_value(char *sv) 128 | { 129 | uint32_t i; 130 | 131 | for (i = 0; i < ARRAYSIZE(system_value_abbreviations); i++) { 132 | if (!strcmp(sv, system_value_abbreviations[i].short_name)) 133 | return system_value_abbreviations[i].val; 134 | } 135 | 136 | throw parseError; 137 | } 138 | 139 | static uint8_t parse_mask(char mask[8], bool invert) 140 | { 141 | uint8_t xor_val = (invert ? 0xf : 0); 142 | uint8_t ret = 0; 143 | int i; 144 | 145 | // This allows for more flexible processing rather than just limiting 146 | // it to what the disassembler generates 147 | 148 | for (i = 0; i < 8 && mask[i]; i++) { 149 | switch (mask[i]) { 150 | case 'x': 151 | ret |= 0x1; 152 | break; 153 | case 'y': 154 | ret |= 0x2; 155 | break; 156 | case 'z': 157 | ret |= 0x4; 158 | break; 159 | case 'w': 160 | ret |= 0x8; 161 | break; 162 | case ' ': 163 | break; 164 | // Special matches for semantics using special purpose registers: 165 | case 'Y': // YES 166 | return 0x1 ^ xor_val; 167 | case 'N': // NO or N/A - wait for next character 168 | break; 169 | case 'O': // NO 170 | return 0x0 ^ xor_val; 171 | case '/': // N/A 172 | return 0x1 ^ xor_val; 173 | default: 174 | throw parseError; 175 | } 176 | } 177 | return ret ^ xor_val; 178 | } 179 | 180 | static uint32_t pad(uint32_t size, uint32_t multiple) 181 | { 182 | return (multiple - size % multiple) % multiple; 183 | } 184 | 185 | static void* serialise_signature_section(char *section24, char *section28, char *section32, int entry_size, 186 | vector *entries, uint32_t name_len) 187 | { 188 | void *section; 189 | uint32_t section_size, padding, alloc_size, name_off; 190 | char *name_ptr = NULL; 191 | void *padding_ptr = NULL; 192 | struct section_header *section_header = NULL; 193 | struct sgn_header *sgn_header = NULL; 194 | sgn_entry_serialiased *entryn = NULL; 195 | sg5_entry_serialiased *entry5 = NULL; 196 | sg1_entry_serialiased *entry1 = NULL; 197 | 198 | // Geometry shader 5 never uses OSGN, bump to OSG5: 199 | if (entry_size == 24 && section24 == NULL) 200 | entry_size = 28; 201 | 202 | // Only OSG5 exists in version 5, so bump ISG & PSG to version 5.1: 203 | if (entry_size == 28 && section28 == NULL) 204 | entry_size = 32; 205 | 206 | // Calculate various offsets and sizes: 207 | name_off = (uint32_t)(sizeof(struct sgn_header) + (entry_size * entries->size())); 208 | section_size = name_off + name_len; 209 | padding = pad(section_size, 4); 210 | alloc_size = section_size + sizeof(struct section_header) + padding; 211 | 212 | LogDebug("name_off: %u, name_len: %u, section_size: %u, padding: %u, alloc_size: %u\n", 213 | name_off, name_len, section_size, padding, alloc_size); 214 | 215 | // Allocate entire section, including room for section header and padding: 216 | section = malloc(alloc_size); 217 | if (!section) { 218 | LogInfo("Out of memory\n"); 219 | return NULL; 220 | } 221 | 222 | // Pointers to useful data structures and offsets in the buffer: 223 | section_header = (struct section_header*)section; 224 | sgn_header = (struct sgn_header*)((char*)section_header + sizeof(struct section_header)); 225 | padding_ptr = (void*)((char*)sgn_header + section_size); 226 | // Only one of these will be used as the base address depending on the 227 | // structure version, but pointers to the older versions will also be 228 | // updated during the iteration: 229 | entryn = (struct sgn_entry_serialiased*)((char*)sgn_header + sizeof(struct sgn_header)); 230 | entry5 = (struct sg5_entry_serialiased*)entryn; 231 | entry1 = (struct sg1_entry_serialiased*)entryn; 232 | 233 | LogDebug("section: 0x%p, section_header: 0x%p, sgn_header: 0x%p, padding_ptr: 0x%p, entry: 0x%p\n", 234 | section, (char*)section_header, sgn_header, padding_ptr, entryn); 235 | 236 | switch (entry_size) { 237 | case 24: 238 | memcpy(§ion_header->signature, section24, 4); 239 | break; 240 | case 28: 241 | memcpy(§ion_header->signature, section28, 4); 242 | break; 243 | case 32: 244 | memcpy(§ion_header->signature, section32, 4); 245 | break; 246 | default: 247 | throw parseError; 248 | } 249 | section_header->size = section_size + padding; 250 | 251 | sgn_header->num_entries = (uint32_t)entries->size(); 252 | sgn_header->unknown = sizeof(struct sgn_header); // Not confirmed, but seems likely. Always 8 253 | 254 | // Fill out entries: 255 | for (struct sgn_entry_unserialised const &unserialised : *entries) { 256 | switch (entry_size) { 257 | case 32: 258 | entry1->min_precision = unserialised.min_precision; 259 | entry5 = &entry1->sg5; 260 | entry1++; 261 | // Fall through 262 | case 28: 263 | entry5->stream = unserialised.stream; 264 | entryn = &entry5->sgn; 265 | entry5++; 266 | // Fall through 267 | case 24: 268 | entryn->name_offset = name_off + unserialised.name_offset; 269 | name_ptr = (char*)sgn_header + entryn->name_offset; 270 | memcpy(name_ptr, unserialised.name.c_str(), unserialised.name.size() + 1); 271 | memcpy(&entryn->common, &unserialised.common, sizeof(struct sgn_entry_common)); 272 | entryn++; 273 | } 274 | } 275 | 276 | memset(padding_ptr, 0xab, padding); 277 | 278 | return section; 279 | } 280 | 281 | static void* parse_signature_section(char *section24, char *section28, char *section32, string *shader, size_t *pos, bool invert_used, uint64_t sfi) 282 | { 283 | string line; 284 | size_t old_pos = *pos; 285 | int numRead; 286 | uint32_t name_off = 0; 287 | int entry_size = 24; // We use the size, because in MS's usual wisdom version 1 is higher than version 5 :facepalm: 288 | char semantic_name[64]; // Semantic names are limited to 63 characters in fxc 289 | char semantic_name2[64]; 290 | char system_value[16]; // More than long enough for even "STENCILREF" 291 | char reg[16]; // More than long enough for even "oStencilRef" 292 | char mask[8], used[8]; // We read 7 characters - check the reason below 293 | char format[16]; // Long enough for even "unknown" 294 | vector entries; 295 | struct sgn_entry_unserialised entry; 296 | 297 | // If minimum precision formats are in use we bump the section versions: 298 | if (sfi & SFI_MIN_PRECISION) 299 | entry_size = max(entry_size, 32); 300 | 301 | while (*pos != shader->npos) { 302 | line = next_line(shader, pos); 303 | 304 | LogDebug("%s\n", line.c_str()); 305 | 306 | if (line == "//" 307 | || line == "// Name Index Mask Register SysValue Format Used" 308 | || line == "// -------------------- ----- ------ -------- -------- ------- ------") { 309 | continue; 310 | } 311 | 312 | if (line == "// no Input" 313 | || line == "// no Output" 314 | || line == "// no Patch Constant") { 315 | // Empty section, but we still need to manufacture it 316 | break; 317 | } 318 | 319 | // Mask and Used can be empty or have spaces in them, so using 320 | // %s would not match them correctly. Instead, match exactly 7 321 | // characters, which will include some preceeding whitespace 322 | // that parse_mask will skip over. But, since we may have 323 | // stripped trailing whitespace, explicitly pad the string to 324 | // make sure Usage has 7 characters to match, and make sure 325 | // they are initialised to ' ': 326 | memset(mask, ' ', 8); 327 | memset(used, ' ', 8); 328 | 329 | numRead = sscanf_s((line + " ").c_str(), 330 | "// %s %d%7c %s %s %s%7c", 331 | semantic_name, (unsigned)ARRAYSIZE(semantic_name), 332 | &entry.common.semantic_index, 333 | mask, (unsigned)ARRAYSIZE(mask), 334 | ®, (unsigned)ARRAYSIZE(reg), 335 | system_value, (unsigned)ARRAYSIZE(system_value), 336 | format, (unsigned)ARRAYSIZE(format), 337 | used, (unsigned)ARRAYSIZE(used)); 338 | 339 | if (numRead != 7) { 340 | // I really would love to throw parseError here to 341 | // catch typos, but since this is in a comment I can't 342 | // be certain that this is part of the signature 343 | // declaration, so I have to assume this is the end of 344 | // the section :( 345 | break; 346 | } 347 | 348 | // Try parsing the semantic name with streams, and bump the 349 | // section version if sucessful: 350 | numRead = sscanf_s(semantic_name, "m%u:%s", 351 | &entry.stream, 352 | semantic_name2, (unsigned)ARRAYSIZE(semantic_name2)); 353 | if (numRead == 2) { 354 | entry_size = max(entry_size, 28); 355 | entry.name = semantic_name2; 356 | } else { 357 | entry.stream = 0; 358 | entry.name = semantic_name; 359 | } 360 | 361 | // Parse the format. If it is one of the minimum precision 362 | // formats, bump the section version (this is probably 363 | // redundant now that we bump the version based on SFI): 364 | parse_format(format, &entry.common.format, &entry.min_precision); 365 | if (entry.min_precision) 366 | entry_size = max(entry_size, 32); 367 | 368 | // Try parsing register as a decimal number. If it is not, it 369 | // is a special purpose register, in which case we store -1: 370 | if (numRead = sscanf_s(reg, "%d", &entry.common.reg) == 0) 371 | entry.common.reg = 0xffffffff; 372 | 373 | entry.common.system_value = parse_system_value(system_value); 374 | entry.common.mask = parse_mask(mask, false); 375 | entry.common.used = parse_mask(used, invert_used); 376 | entry.common.zero = 0; 377 | 378 | // Check if a previous entry used the same semantic name 379 | for (struct sgn_entry_unserialised const &prev_entry : entries) { 380 | if (prev_entry.name == entry.name) { 381 | entry.name_offset = prev_entry.name_offset; 382 | // Why do so few languages have a for else 383 | // construct? It is incredibly useful, yet 384 | // pretty much only Python has it! Using a 385 | // regular for loop I can fake it by checking 386 | // the final value of the iterator, but here 387 | // I'm using for each and the iterator will be 388 | // out of scope, so I'd have to use another 389 | // "found" variable instead. Screw it, I'm 390 | // using goto to pretend I have it here too: 391 | goto name_already_used; 392 | } 393 | } // else { ;-) 394 | entry.name_offset = name_off; 395 | name_off += (uint32_t)entry.name.size() + 1; 396 | // } 397 | name_already_used: 398 | 399 | LogDebug("Stream: %i, Name: %s, Index: %i, Mask: 0x%x, Register: %i, SysValue: %i, Format: %i, Used: 0x%x, Precision: %i\n", 400 | entry.stream, entry.name.c_str(), 401 | entry.common.semantic_index, entry.common.mask, 402 | entry.common.reg, entry.common.system_value, 403 | entry.common.format, entry.common.used, 404 | entry.min_precision); 405 | 406 | entries.push_back(entry); 407 | old_pos = *pos; 408 | } 409 | // Wind the pos pointer back to the start of the line in case it is 410 | // another section that the caller will need to parse: 411 | *pos = old_pos; 412 | 413 | return serialise_signature_section(section24, section28, section32, entry_size, &entries, name_off); 414 | } 415 | 416 | static void* serialise_subshader_feature_info_section(uint64_t flags) 417 | { 418 | void *section; 419 | struct section_header *section_header = NULL; 420 | const uint32_t section_size = 8; 421 | const uint32_t alloc_size = sizeof(struct section_header) + section_size; 422 | uint64_t *flags_ptr = NULL; 423 | 424 | if (!flags) 425 | return NULL; 426 | 427 | // Allocate entire section, including room for section header and padding: 428 | section = malloc(alloc_size); 429 | if (!section) { 430 | LogInfo("Out of memory\n"); 431 | return NULL; 432 | } 433 | 434 | // Pointers to useful data structures and offsets in the buffer: 435 | section_header = (struct section_header*)section; 436 | memcpy(section_header->signature, "SFI0", 4); 437 | section_header->size = section_size; 438 | 439 | flags_ptr = (uint64_t *)((char*)section_header + sizeof(struct section_header)); 440 | *flags_ptr = flags; 441 | 442 | return section; 443 | } 444 | 445 | struct gf_sfi { 446 | uint64_t sfi; 447 | int len; 448 | char *gf; 449 | }; 450 | 451 | static struct gf_sfi global_flag_sfi_map[] = { 452 | { 1LL<<0, 29, "enableDoublePrecisionFloatOps" }, 453 | { SFI_RAW_STRUCT_BUF, 29, "enableRawAndStructuredBuffers" }, // Confirmed 454 | { SFI_MIN_PRECISION, 22, "enableMinimumPrecision" }, 455 | { 1LL<<5, 26, "enable11_1DoubleExtensions" }, 456 | { 1LL<<6, 26, "enable11_1ShaderExtensions" }, 457 | 458 | // Does not map to SFI: 459 | // "refactoringAllowed" 460 | // "forceEarlyDepthStencil" 461 | // "skipOptimization" 462 | // "allResourcesBound" 463 | }; 464 | 465 | static char *subshader_feature_comments[] = { 466 | // d3dcompiler_46: 467 | "Double-precision floating point", 468 | //"Early depth-stencil", // d3dcompiler46/47 produces this output for [force, but it does *NOT* map to an SFI flag 469 | "Raw and Structured buffers", // DirectXShaderCompiler lists this in this position instead, which matches the globalFlag mapping 470 | "UAVs at every shader stage", 471 | "64 UAV slots", 472 | "Minimum-precision data types", 473 | "Double-precision extensions for 11.1", 474 | "Shader extensions for 11.1", 475 | "Comparison filtering for feature level 9", 476 | // d3dcompiler_47: 477 | "Tiled resources", 478 | "PS Output Stencil Ref", 479 | "PS Inner Coverage", 480 | "Typed UAV Load Additional Formats", 481 | "Raster Ordered UAVs", 482 | "SV_RenderTargetArrayIndex or SV_ViewportArrayIndex from any shader feeding rasterizer", 483 | // DX12 DirectXShaderCompiler (tools/clang/tools/dxcompiler/dxcdisassembler.cpp) 484 | "Wave level operations", 485 | "64-Bit integer", 486 | "View Instancing", 487 | "Barycentrics", 488 | "Use native low precision", 489 | "Shading Rate" 490 | }; 491 | 492 | // Parses the globalFlags in the bytecode to derive Subshader Feature Info. 493 | // This is incomplete, as some of the SFI flags are not in globalFlags, but 494 | // must be found from the "shader requires" comment block instead. 495 | uint64_t parse_global_flags_to_sfi(string *shader) 496 | { 497 | uint64_t sfi = 0LL; 498 | string line; 499 | size_t pos = 0, gf_pos = 16; 500 | int i; 501 | 502 | while (pos != shader->npos) { 503 | line = next_line(shader, &pos); 504 | if (!strncmp(line.c_str(), "dcl_globalFlags ", 16)) { 505 | LogDebug("%s\n", line.c_str()); 506 | while (gf_pos != string::npos) { 507 | for (i = 0; i < ARRAYSIZE(global_flag_sfi_map); i++) { 508 | if (!line.compare(gf_pos, global_flag_sfi_map[i].len, global_flag_sfi_map[i].gf)) { 509 | LogDebug("Mapped %s to Subshader Feature 0x%llx\n", 510 | global_flag_sfi_map[i].gf, global_flag_sfi_map[i].sfi); 511 | sfi |= global_flag_sfi_map[i].sfi; 512 | gf_pos += global_flag_sfi_map[i].len; 513 | break; 514 | } 515 | } 516 | gf_pos = line.find_first_of(" |", gf_pos); 517 | gf_pos = line.find_first_not_of(" |", gf_pos); 518 | } 519 | return sfi; 520 | } 521 | } 522 | return 0; 523 | } 524 | 525 | // Parses the SFI comment block. This is not complete, as some of the flags 526 | // come from globalFlags instead of / as well as this. 527 | static uint64_t parse_subshader_feature_info_comment(string *shader, size_t *pos, uint64_t flags) 528 | { 529 | string line; 530 | size_t old_pos = *pos; 531 | uint32_t i; 532 | 533 | while (*pos != shader->npos) { 534 | line = next_line(shader, pos); 535 | 536 | LogDebug("%s\n", line.c_str()); 537 | 538 | for (i = 0; i < ARRAYSIZE(subshader_feature_comments); i++) { 539 | if (!strcmp(line.c_str() + 9, subshader_feature_comments[i])) { 540 | LogDebug("Matched Subshader Feature Comment 0x%llx\n", 1LL << i); 541 | flags |= 1LL << i; 542 | break; 543 | } 544 | } 545 | if (i == ARRAYSIZE(subshader_feature_comments)) 546 | break; 547 | } 548 | 549 | // Wind the pos pointer back to the start of the line in case it is 550 | // another section that the caller will need to parse: 551 | *pos = old_pos; 552 | 553 | return flags; 554 | } 555 | 556 | static void* manufacture_empty_section(char *section_name) 557 | { 558 | void *section; 559 | 560 | LogInfo("Manufacturing placeholder %s section...\n", section_name); 561 | 562 | section = malloc(8); 563 | if (!section) { 564 | LogInfo("Out of memory\n"); 565 | return NULL; 566 | } 567 | 568 | memcpy(section, section_name, 4); 569 | memset((char*)section + 4, 0, 4); 570 | 571 | return section; 572 | } 573 | 574 | static bool is_hull_shader(string *shader, size_t start_pos) { 575 | string line; 576 | size_t pos = start_pos; 577 | 578 | while (pos != shader->npos) { 579 | line = next_line(shader, &pos); 580 | if (!strncmp(line.c_str(), "hs_4_", 5)) 581 | return true; 582 | if (!strncmp(line.c_str(), "hs_5_", 5)) 583 | return true; 584 | if (!strncmp(line.c_str() + 1, "s_4_", 4)) 585 | return false; 586 | if (!strncmp(line.c_str() + 1, "s_5_", 4)) 587 | return false; 588 | } 589 | 590 | return false; 591 | } 592 | 593 | static bool is_geometry_shader_5(string *shader, size_t start_pos) { 594 | string line; 595 | size_t pos = start_pos; 596 | 597 | while (pos != shader->npos) { 598 | line = next_line(shader, &pos); 599 | if (!strncmp(line.c_str(), "gs_5_", 5)) 600 | return true; 601 | if (!strncmp(line.c_str() + 1, "s_4_", 4)) 602 | return false; 603 | if (!strncmp(line.c_str() + 1, "s_5_", 4)) 604 | return false; 605 | } 606 | 607 | return false; 608 | } 609 | 610 | static bool parse_section(string *line, string *shader, size_t *pos, void **section, uint64_t *sfi, bool *force_shex) 611 | { 612 | *section = NULL; 613 | 614 | if (!strncmp(line->c_str() + 1, "s_4_", 4)) { 615 | if (!!(*sfi & SFI_FORCE_SHEX) || *force_shex) 616 | *section = manufacture_empty_section("SHEX"); 617 | else 618 | *section = manufacture_empty_section("SHDR"); 619 | return true; 620 | } 621 | if (!strncmp(line->c_str() + 1, "s_5_", 4)) { 622 | *section = manufacture_empty_section("SHEX"); 623 | return true; 624 | } 625 | 626 | if (!strncmp(line->c_str(), "// Patch Constant signature:", 28)) { 627 | LogInfo("Parsing Patch Constant Signature section...\n"); 628 | *section = parse_signature_section("PCSG", NULL, "PSG1", shader, pos, is_hull_shader(shader, *pos), *sfi); 629 | } else if (!strncmp(line->c_str(), "// Input signature:", 19)) { 630 | LogInfo("Parsing Input Signature section...\n"); 631 | *section = parse_signature_section("ISGN", NULL, "ISG1", shader, pos, false, *sfi); 632 | } else if (!strncmp(line->c_str(), "// Output signature:", 20)) { 633 | LogInfo("Parsing Output Signature section...\n"); 634 | char *section24 = "OSGN"; 635 | if (is_geometry_shader_5(shader, *pos)) 636 | section24 = NULL; 637 | *section = parse_signature_section(section24, "OSG5", "OSG1", shader, pos, true, *sfi); 638 | } else if (!strncmp(line->c_str(), "// Note: shader requires additional functionality:", 50)) { 639 | LogInfo("Parsing Subshader Feature Info section...\n"); 640 | *sfi = parse_subshader_feature_info_comment(shader, pos, *sfi); 641 | } else if (!strncmp(line->c_str(), "// Note: SHADER WILL ONLY WORK WITH THE DEBUG SDK LAYER ENABLED.", 64)) { 642 | *force_shex = true; 643 | } 644 | 645 | return false; 646 | } 647 | 648 | static void serialise_shader_binary(vector *sections, uint32_t all_sections_size, vector *bytecode) 649 | { 650 | struct dxbc_header *header = NULL; 651 | uint32_t *section_offset_ptr = NULL; 652 | void *section_ptr = NULL; 653 | uint32_t section_size; 654 | uint32_t shader_size; 655 | 656 | // Calculate final size of shader binary: 657 | shader_size = (uint32_t)(sizeof(struct dxbc_header) + 4 * sections->size() + all_sections_size); 658 | 659 | bytecode->resize(shader_size); 660 | 661 | // Get some useful pointers into the buffer: 662 | header = (struct dxbc_header*)bytecode->data(); 663 | section_offset_ptr = (uint32_t*)((char*)header + sizeof(struct dxbc_header)); 664 | section_ptr = (void*)(section_offset_ptr + sections->size()); 665 | 666 | memcpy(header->signature, "DXBC", 4); 667 | memset(header->hash, 0, sizeof(header->hash)); // Will be filled in by assembler 668 | header->one = 1; 669 | header->size = shader_size; 670 | header->num_sections = (uint32_t)sections->size(); 671 | 672 | for (void *section : *sections) { 673 | section_size = *((uint32_t*)section + 1) + sizeof(section_header); 674 | memcpy(section_ptr, section, section_size); 675 | *section_offset_ptr = (uint32_t)((char*)section_ptr - (char*)header); 676 | section_offset_ptr++; 677 | section_ptr = (char*)section_ptr + section_size; 678 | } 679 | } 680 | 681 | static HRESULT manufacture_shader_binary(const void *pShaderAsm, size_t AsmLength, vector *bytecode) 682 | { 683 | string shader_str((const char*)pShaderAsm, AsmLength); 684 | string line; 685 | size_t pos = 0; 686 | bool done = false; 687 | vector sections; 688 | uint32_t section_size, all_sections_size = 0; 689 | void *section; 690 | HRESULT hr = E_FAIL; 691 | uint64_t sfi = 0LL; 692 | bool force_shex = false; 693 | 694 | sfi = parse_global_flags_to_sfi(&shader_str); 695 | 696 | while (!done && pos != shader_str.npos) { 697 | line = next_line(&shader_str, &pos); 698 | //LogInfo("%s\n", line.c_str()); 699 | 700 | done = parse_section(&line, &shader_str, &pos, §ion, &sfi, &force_shex); 701 | if (section) { 702 | sections.push_back(section); 703 | section_size = *((uint32_t*)section + 1) + sizeof(section_header); 704 | all_sections_size += section_size; 705 | 706 | if (gLogDebug) { 707 | LogInfo("Constructed section size=%u:\n", section_size); 708 | for (uint32_t i = 0; i < section_size; i++) { 709 | if (i && i % 16 == 0) 710 | LogInfo("\n"); 711 | LogInfo("%02x ", ((unsigned char*)section)[i]); 712 | } 713 | LogInfo("\n"); 714 | } 715 | } 716 | } 717 | 718 | if (!done) { 719 | LogInfo("Did not find an assembly text section!\n"); 720 | goto out_free; 721 | } 722 | 723 | if (sfi) { 724 | section = serialise_subshader_feature_info_section(sfi); 725 | sections.insert(sections.begin(), section); 726 | section_size = *((uint32_t*)section + 1) + sizeof(section_header); 727 | all_sections_size += section_size; 728 | LogInfo("Inserted Subshader Feature Info section: 0x%llx\n", sfi); 729 | } 730 | 731 | serialise_shader_binary(§ions, all_sections_size, bytecode); 732 | 733 | hr = S_OK; 734 | out_free: 735 | for (void * const §ion : sections) 736 | free(section); 737 | return hr; 738 | } 739 | 740 | HRESULT AssembleFluganWithSignatureParsing(vector *assembly, vector *result_bytecode, 741 | vector *parse_errors) 742 | { 743 | vector manufactured_bytecode; 744 | HRESULT hr; 745 | 746 | // Flugan's assembler normally cheats and reuses sections from the 747 | // original binary when replacing a shader from the game, but that 748 | // restricts what modifications we can do and is not an option when 749 | // assembling a stand-alone shader. Let's parse the missing sections 750 | // ourselved and manufacture a binary shader with those section to pass 751 | // to Flugan's assembler. Later we should refactor this into the 752 | // assembler itself. 753 | 754 | hr = manufacture_shader_binary(assembly->data(), assembly->size(), &manufactured_bytecode); 755 | if (FAILED(hr)) 756 | return E_FAIL; 757 | 758 | *result_bytecode = assembler(assembly, manufactured_bytecode, parse_errors); 759 | 760 | return S_OK; 761 | } 762 | vector AssembleFluganWithOptionalSignatureParsing(vector *assembly, 763 | bool assemble_signatures, vector *orig_bytecode, 764 | vector *parse_errors) 765 | { 766 | vector new_bytecode; 767 | HRESULT hr; 768 | 769 | if (!assemble_signatures) 770 | return assembler(assembly, *orig_bytecode, parse_errors); 771 | 772 | hr = AssembleFluganWithSignatureParsing(assembly, &new_bytecode, parse_errors); 773 | if (FAILED(hr)) 774 | throw parseError; 775 | 776 | return new_bytecode; 777 | } 778 | -------------------------------------------------------------------------------- /D3D_Shaders/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | #include "stdint.h" 13 | #include "D3DCompiler.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | // VS2013 BUG WORKAROUND: Make sure this class has a unique type name! 22 | class AssemblerParseError: public exception { 23 | public: 24 | string context, desc, msg; 25 | int line_no; 26 | 27 | AssemblerParseError(string context, string desc) : 28 | context(context), 29 | desc(desc), 30 | line_no(0) 31 | { 32 | update_msg(); 33 | } 34 | 35 | void update_msg() 36 | { 37 | msg = "Assembly parse error"; 38 | if (line_no > 0) 39 | msg += string(" on line ") + to_string(line_no); 40 | msg += ", " + desc + ":\n\"" + context + "\""; 41 | } 42 | 43 | const char* what() const 44 | { 45 | return msg.c_str(); 46 | } 47 | }; 48 | 49 | struct shader_ins 50 | { 51 | union { 52 | struct { 53 | // XXX Beware that bitfield packing is not defined in 54 | // the C/C++ standards and this is relying on compiler 55 | // specific packing. This approach is not recommended. 56 | 57 | unsigned opcode : 11; 58 | unsigned _11_23 : 13; 59 | unsigned length : 7; 60 | unsigned extended : 1; 61 | }; 62 | DWORD op; 63 | }; 64 | }; 65 | struct token_operand 66 | { 67 | union { 68 | struct { 69 | // XXX Beware that bitfield packing is not defined in 70 | // the C/C++ standards and this is relying on compiler 71 | // specific packing. This approach is not recommended. 72 | 73 | unsigned comps_enum : 2; /* sm4_operands_comps */ 74 | unsigned mode : 2; /* sm4_operand_mode */ 75 | unsigned sel : 8; 76 | unsigned file : 8; /* SM_FILE */ 77 | unsigned num_indices : 2; 78 | unsigned index0_repr : 3; /* sm4_operand_index_repr */ 79 | unsigned index1_repr : 3; /* sm4_operand_index_repr */ 80 | unsigned index2_repr : 3; /* sm4_operand_index_repr */ 81 | unsigned extended : 1; 82 | }; 83 | DWORD op; 84 | }; 85 | }; 86 | 87 | vector stringToLines(const char* start, size_t size); 88 | HRESULT disassembler(vector *buffer, vector *ret, const char *comment, 89 | int hexdump = 0, bool d3dcompiler_46_compat = false, 90 | bool disassemble_undecipherable_data = false, 91 | bool patch_cb_offsets = false); 92 | HRESULT disassemblerDX9(vector *buffer, vector *ret, const char *comment); 93 | vector assembler(vector *asmFile, vector origBytecode, vector *parse_errors = NULL); 94 | vector assemblerDX9(vector *asmFile); 95 | void writeLUT(); 96 | HRESULT AssembleFluganWithSignatureParsing(vector *assembly, vector *result_bytecode, vector *parse_errors = NULL); 97 | vector AssembleFluganWithOptionalSignatureParsing(vector *assembly, bool assemble_signatures, vector *orig_bytecode, vector *parse_errors = NULL); 98 | -------------------------------------------------------------------------------- /D3D_Shaders/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /HLSLDecompiler/DecompileHLSL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // The goal with this file is too keep it as much C++ as possible. 7 | // So we avoid adding Windows specific stuff if at all possible. 8 | 9 | // Let's use these constants instead of hard coded numbers, so that we can use safe versions 10 | // of sprintf_s, sscanf_s, strcpy_s 11 | 12 | const int opcodeSize = 128; 13 | const int stringSize = 256; 14 | 15 | struct DecompilerSettings 16 | { 17 | int StereoParamsReg; 18 | int IniParamsReg; 19 | 20 | bool fixSvPosition; 21 | bool recompileVs; 22 | char ZRepair_DepthTextureReg1, ZRepair_DepthTextureReg2; 23 | std::string ZRepair_DepthTexture1, ZRepair_DepthTexture2; 24 | std::vector ZRepair_Dependencies1, ZRepair_Dependencies2; 25 | std::string ZRepair_ZPosCalc1, ZRepair_ZPosCalc2; 26 | std::string ZRepair_PositionTexture; 27 | bool ZRepair_DepthBuffer; 28 | std::vector InvTransforms; 29 | std::string ZRepair_WorldPosCalc; 30 | std::string BackProject_Vector1, BackProject_Vector2; 31 | std::string ObjectPos_ID1, ObjectPos_ID2, ObjectPos_MUL1, ObjectPos_MUL2; 32 | std::string MatrixPos_ID1, MatrixPos_MUL1; 33 | 34 | DecompilerSettings() : 35 | StereoParamsReg(-1), 36 | IniParamsReg(-1), 37 | fixSvPosition(false), 38 | recompileVs(false), 39 | ZRepair_DepthTextureReg1('\0'), 40 | ZRepair_DepthTextureReg2('\0'), 41 | ZRepair_DepthBuffer(false) 42 | {} 43 | }; 44 | 45 | struct ParseParameters 46 | { 47 | const void *bytecode; 48 | const char *decompiled; 49 | size_t decompiledSize; 50 | bool ZeroOutput; 51 | 52 | //dx9 53 | int StereoParamsVertexReg; 54 | int StereoParamsPixelReg; 55 | //dx9 56 | 57 | DecompilerSettings *G; 58 | }; 59 | 60 | const std::string DecompileBinaryHLSL(ParseParameters ¶ms, bool &patched, std::string &shaderModel, bool &errorOccurred); 61 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : cmd_Decompiler Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this cmd_Decompiler application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your cmd_Decompiler application. 9 | 10 | 11 | cmd_Decompiler.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | cmd_Decompiler.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | cmd_Decompiler.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named cmd_Decompiler.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | 42 | Created as a way to access the Decompiler via the Cmd window/console. 43 | This will allow us to test and Debug the Decompiler without needing anything except an ASM file, 44 | and will also allows us to create some unit tests of previously known good shaders. -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/aaa.dxbc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quon/HLSLDecompiler/2ac334f7bd2c82c6d7731c2651a8a1245b94237f/HLSLDecompiler/cmd_Decompiler/aaa.dxbc -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/aaa.hlsl: -------------------------------------------------------------------------------- 1 | // ---- Created with 3Dmigoto v1.3.16 on Thu Aug 12 18:26:59 2021 2 | Texture2D t1 : register(t1); 3 | 4 | Texture2D t0 : register(t0); 5 | 6 | SamplerState s1_s : register(s1); 7 | 8 | SamplerState s0_s : register(s0); 9 | 10 | cbuffer cb0 : register(b0) 11 | { 12 | float4 cb0[9]; 13 | } 14 | 15 | 16 | 17 | 18 | // 3Dmigoto declarations 19 | #define cmp - 20 | 21 | 22 | void main( 23 | float4 v0 : SV_POSITION0, 24 | float4 v1 : TEXCOORD0, 25 | float4 v2 : TEXCOORD1, 26 | float4 v3 : TEXCOORD2, 27 | out float4 o0 : SV_Target0, 28 | out float4 o1 : SV_Target1, 29 | out float oDepth : SV_Depth) 30 | { 31 | float4 r0,r1,r2; 32 | uint4 bitmask, uiDest; 33 | float4 fDest; 34 | 35 | r0.xyzw = v2.zxyw + v1.xxyy; 36 | r1.yz = r0.xw; 37 | r2.xyzw = t1.Gather(s0_s, v1.xy).wxyz; 38 | r0.w = cmp(r2.z < r2.y); 39 | r1.x = r2.z; 40 | r0.x = r2.y; 41 | r0.xyz = r0.www ? r1.xyz : r0.xyz; 42 | r0.w = cmp(r2.w < r0.x); 43 | r1.xyzw = v3.zxyw + v1.xxyy; 44 | r2.yz = r1.xw; 45 | r1.x = r2.w; 46 | r0.xyz = r0.www ? r1.xyz : r0.xyz; 47 | r0.w = cmp(r2.x < r0.x); 48 | r0.xyz = r0.www ? r2.xyz : r0.xyz; 49 | r0.w = cb0[8].x * r0.x + cb0[8].y; 50 | o0.xyzw = float4(1,1,1,1) / r0.wwww; 51 | o1.xyzw = t0.Sample(s1_s, r0.yz).xyzw; 52 | oDepth = r0.x; 53 | return; 54 | } -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/aaa.txt: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by Microsoft (R) D3D Shader Disassembler 3 | // 4 | // using 3Dmigoto command line v1.2.45 on Mon Jul 19 23:56:07 2021 5 | // 6 | // 7 | // Input signature: 8 | // 9 | // Name Index Mask Register SysValue Format Used 10 | // -------------------- ----- ------ -------- -------- ------- ------ 11 | // SV_POSITION 0 xyzw 0 POS float 12 | // TEXCOORD 0 xy 1 NONE float xy 13 | // TEXCOORD 1 xyzw 2 NONE float xyzw 14 | // TEXCOORD 2 xyzw 3 NONE float xyzw 15 | // 16 | // 17 | // Output signature: 18 | // 19 | // Name Index Mask Register SysValue Format Used 20 | // -------------------- ----- ------ -------- -------- ------- ------ 21 | // SV_Target 0 xyzw 0 TARGET float xyzw 22 | // SV_Target 1 xyzw 1 TARGET float xyzw 23 | // SV_Depth 0 N/A oDepth DEPTH float YES 24 | // 25 | ps_5_0 26 | dcl_globalFlags refactoringAllowed 27 | dcl_constantbuffer CB0[9], immediateIndexed 28 | dcl_sampler s0, mode_default 29 | dcl_sampler s1, mode_default 30 | dcl_resource_texture2d (float,float,float,float) t0 31 | dcl_resource_texture2d (float,float,float,float) t1 32 | dcl_input_ps linear v1.xy 33 | dcl_input_ps linear v2.xyzw 34 | dcl_input_ps linear v3.xyzw 35 | dcl_output o0.xyzw 36 | dcl_output o1.xyzw 37 | dcl_output oDepth 38 | dcl_temps 3 39 | add r0.xyzw, v1.xxyy, v2.zxyw 40 | mov r1.yz, r0.xxwx 41 | gather4_indexable(texture2d)(float,float,float,float) r2.xyzw, v1.xyxx, t1.wxyz, s0.x 42 | lt r0.w, r2.z, r2.y 43 | mov r1.x, r2.z 44 | mov r0.x, r2.y 45 | movc r0.xyz, r0.wwww, r1.xyzx, r0.xyzx 46 | lt r0.w, r2.w, r0.x 47 | add r1.xyzw, v1.xxyy, v3.zxyw 48 | mov r2.yz, r1.xxwx 49 | mov r1.x, r2.w 50 | movc r0.xyz, r0.wwww, r1.xyzx, r0.xyzx 51 | lt r0.w, r2.x, r0.x 52 | movc r0.xyz, r0.wwww, r2.xyzx, r0.xyzx 53 | mad r0.w, cb0[8].x, r0.x, cb0[8].y 54 | div o0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000), r0.wwww 55 | sample_indexable(texture2d)(float,float,float,float) o1.xyzw, r0.yzyy, t0.xyzw, s1 56 | mov oDepth, r0.x 57 | ret 58 | // Approximately 0 instruction slots used 59 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/cmd_Decompiler.cpp: -------------------------------------------------------------------------------- 1 | // cmd_Decompiler.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "stdafx.h" 5 | 6 | #include // console output 7 | 8 | #include 9 | #include "DecompileHLSL.h" 10 | #include "version.h" 11 | #include "log.h" 12 | #define MIGOTO_DX 11 // Selects the DX11 disassembler in util.h - the DX9 dis/assembler is not very 13 | // interesting since it is just Microsoft's - we can add it later, but low priority. 14 | // The DX9 decompiler is more interesting, which is unrelated to this flag. 15 | #include "util.h" 16 | #include "shader.h" 17 | #include "D3D_Shaders/stdafx.h" 18 | 19 | using namespace std; 20 | 21 | FILE *LogFile = stderr; // Log to stderr by default 22 | bool gLogDebug = false; 23 | 24 | static void PrintHelp(int argc, char *argv[]) 25 | { 26 | LogInfo("usage: %s [OPTION] FILE...\n\n", argv[0]); 27 | 28 | LogInfo(" -D, --decompile\n"); 29 | LogInfo("\t\t\tDecompile binary shaders with 3DMigoto's decompiler\n"); 30 | 31 | // We can do this via fxc easily enough for now, and would need to pass in the shader model: 32 | // LogInfo(" -C, --compile\n"); 33 | // LogInfo("\t\t\tCompile binary shaders with Microsoft's compiler\n"); 34 | 35 | LogInfo(" -d, --disassemble, --disassemble-flugan\n"); 36 | LogInfo("\t\t\tDisassemble binary shaders with Flugan's disassembler\n"); 37 | 38 | LogInfo(" -x, --disassemble-hexdump\n"); 39 | LogInfo("\t\t\tIntermix the disassembly with the raw hex codes (implies --disassemble-flugan)\n"); 40 | 41 | LogInfo(" --disassemble-ms\n"); 42 | LogInfo("\t\t\tDisassemble binary shaders with Microsoft's disassembler\n"); 43 | 44 | // Only applicable to the vs2017 branch / d3dcompiler_47 version: 45 | LogInfo(" -6, --disassemble-46\n"); 46 | LogInfo("\t\t\tApply backwards compatibility formatting patch to disassembler output\n"); 47 | 48 | LogInfo(" -16, --patch-cb-offsets\n"); 49 | LogInfo("\t\t\tReplace constant buffer byte offsets with indices when disassembling\n"); 50 | 51 | LogInfo(" -a, --assemble\n"); 52 | LogInfo("\t\t\tAssemble shaders with Flugan's assembler\n"); 53 | 54 | LogInfo(" --copy-reflection FILE\n"); 55 | LogInfo("\t\t\t\tCopy reflection & signature sections from FILE when assembling"); 56 | 57 | // TODO (at the moment we always force): 58 | // LogInfo(" -f, --force\n"); 59 | // LogInfo("\t\t\tOverwrite existing files\n"); 60 | 61 | // Call this validate not verify, because it's impossible to machine 62 | // verify the decompiler: 63 | LogInfo(" -V, --validate\n"); 64 | LogInfo("\t\t\tRun a validation pass after decompilation / disassembly\n"); 65 | 66 | LogInfo(" --lenient\n"); 67 | LogInfo("\t\t\tDon't fail shader validation for certain types of section mismatches\n"); 68 | 69 | LogInfo(" -S, --stop-on-failure\n"); 70 | LogInfo("\t\t\tStop processing files if an error occurs\n"); 71 | 72 | LogInfo(" -v, --verbose\n"); 73 | LogInfo("\t\t\tVerbose debugging output\n"); 74 | 75 | exit(EXIT_FAILURE); 76 | } 77 | 78 | static void PrintVersion() 79 | { 80 | LogInfo("3DMigoto cmd_Decompiler version %s\n", VER_FILE_VERSION_STR); 81 | 82 | exit(EXIT_SUCCESS); 83 | } 84 | 85 | static struct { 86 | std::vector files; 87 | bool decompile; 88 | bool decompile2; 89 | bool compile; 90 | bool disassemble_ms; 91 | bool disassemble_flugan; 92 | int disassemble_hexdump; 93 | bool disassemble_46; 94 | bool patch_cb_offsets; 95 | std::string reflection_reference; 96 | bool assemble; 97 | bool force; 98 | bool validate; 99 | bool lenient; 100 | bool stop; 101 | } args; 102 | 103 | void parse_args(int argc, char *argv[]) 104 | { 105 | bool terminated = false; 106 | char *arg; 107 | int i; 108 | 109 | // I'd prefer to use an existing library for this (e.g. that allows 110 | // these to be specified declaratively and handles --help, --usage, 111 | // abbreviations and all the other goodness that these libraries 112 | // provide), but getopt is absent on Windows and I don't particularly 113 | // want to drag in all of boost for this one thing, so for now just use 114 | // fairly simple posix style option parsing that can later be expanded 115 | // to use a full library 116 | 117 | for (i = 1; i < argc; i++) { 118 | arg = argv[i]; 119 | if (!terminated && !strncmp(arg, "-", 1)) { 120 | if (!strcmp(arg, "--help") || !strcmp(arg, "--usage")) { 121 | PrintHelp(argc, argv); // Does not return 122 | } 123 | if (!strcmp(arg, "--version")) { 124 | PrintVersion(); // Does not return 125 | } 126 | if (!strcmp(arg, "--")) { 127 | terminated = true; 128 | continue; 129 | } 130 | if (!strcmp(arg, "-D") || !strcmp(arg, "--decompile")) { 131 | args.decompile = true; 132 | continue; 133 | } 134 | if (!strcmp(arg, "-E") || !strcmp(arg, "--decompile-string")) { 135 | args.decompile2 = true; 136 | continue; 137 | } 138 | // if (!strcmp(arg, "-C") || !strcmp(arg, "--compile")) { 139 | // args.compile = true; 140 | // continue; 141 | // } 142 | if (!strcmp(arg, "-d") || !strcmp(arg, "--disassemble") || !strcmp(arg, "--disassemble-flugan")) { 143 | args.disassemble_flugan = true; 144 | continue; 145 | } 146 | if (!strcmp(arg, "-x") || !strcmp(arg, "--disassemble-hexdump")) { 147 | args.disassemble_hexdump = 1; 148 | continue; 149 | } 150 | if (!strcmp(arg, "-6") || !strcmp(arg, "--disassemble-46")) { 151 | args.disassemble_46 = true; 152 | continue; 153 | } 154 | if (!strcmp(arg, "-16") || !strcmp(arg, "--patch-cb-offsets")) { 155 | args.patch_cb_offsets = true; 156 | continue; 157 | } 158 | 159 | if (!strcmp(arg, "--copy-reflection")) { 160 | if (++i >= argc) 161 | PrintHelp(argc, argv); 162 | args.reflection_reference = argv[i]; 163 | continue; 164 | } 165 | if (!strcmp(arg, "--disassemble-ms")) { 166 | args.disassemble_ms = true; 167 | continue; 168 | } 169 | if (!strcmp(arg, "-a") || !strcmp(arg, "--assemble")) { 170 | args.assemble = true; 171 | continue; 172 | } 173 | // if (!strcmp(arg, "-f") || !strcmp(arg, "--force")) { 174 | // args.force = true; 175 | // continue; 176 | // } 177 | if (!strcmp(arg, "-V") || !strcmp(arg, "--validate")) { 178 | args.validate = true; 179 | continue; 180 | } 181 | if (!strcmp(arg, "--lenient")) { 182 | args.lenient = true; 183 | continue; 184 | } 185 | if (!strcmp(arg, "-S") || !strcmp(arg, "--stop-on-failure")) { 186 | args.stop = true; 187 | continue; 188 | } 189 | if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) { 190 | gLogDebug = true; 191 | continue; 192 | } 193 | LogInfo("Unrecognised argument: %s\n", arg); 194 | PrintHelp(argc, argv); // Does not return 195 | } 196 | args.files.push_back(arg); 197 | } 198 | 199 | if (args.decompile + args.decompile2 + args.compile 200 | + args.disassemble_ms 201 | + args.disassemble_flugan 202 | + args.disassemble_hexdump 203 | + args.disassemble_46 204 | + args.assemble < 1) { 205 | LogInfo("No action specified\n"); 206 | PrintHelp(argc, argv); // Does not return 207 | } 208 | 209 | } 210 | 211 | // Old version directly using D3DDisassemble, suffers from precision issues due 212 | // to bug in MS's disassembler that always prints floats with %f, which does 213 | // not have sufficient precision to reproduce a 32bit floating point value 214 | // exactly. Might still be useful for comparison: 215 | static HRESULT DisassembleMS(const void *pShaderBytecode, size_t BytecodeLength, string *asmText) 216 | { 217 | ID3DBlob *disassembly = nullptr; 218 | UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS; 219 | string comments = "// using 3Dmigoto command line v" + string(VER_FILE_VERSION_STR) + " on " + LogTime() + "//\n"; 220 | 221 | HRESULT hr = D3DDisassemble(pShaderBytecode, BytecodeLength, flags, comments.c_str(), &disassembly); 222 | if (FAILED(hr)) { 223 | LogInfo(" disassembly failed. Error: %x\n", hr); 224 | return hr; 225 | } 226 | 227 | // Successfully disassembled into a Blob. Let's turn it into a C++ std::string 228 | // so that we don't have a null byte as a terminator. If written to a file, 229 | // the null bytes otherwise cause Git diffs to fail. 230 | *asmText = string(static_cast(disassembly->GetBufferPointer())); 231 | 232 | disassembly->Release(); 233 | return S_OK; 234 | } 235 | 236 | static HRESULT DisassembleFlugan(const void *pShaderBytecode, size_t BytecodeLength, string *asmText, 237 | int hexdump, bool d3dcompiler_46_compat) 238 | { 239 | // FIXME: This is a bit of a waste - we convert from a vector to 240 | // a void* + size_t to a vector 241 | 242 | *asmText = BinaryToAsmText(pShaderBytecode, BytecodeLength, args.patch_cb_offsets, true, hexdump, d3dcompiler_46_compat); 243 | if (*asmText == "") 244 | return E_FAIL; 245 | 246 | return S_OK; 247 | } 248 | 249 | static int validate_section(char section[4], unsigned char *old_section, unsigned char *new_section, size_t size, struct dxbc_header *old_dxbc) 250 | { 251 | unsigned char *p1 = old_section, *p2 = new_section; 252 | int rc = 0; 253 | size_t pos; 254 | size_t off = (size_t)(old_section - (unsigned char*)old_dxbc); 255 | 256 | for (pos = 0; pos < size; pos++, p1++, p2++) { 257 | if (*p1 == *p2) 258 | continue; 259 | 260 | if (!rc) 261 | LogInfo("\n*** Assembly verification pass failed: mismatch in section %.4s:\n", section); 262 | LogInfo(" %.4s+0x%04Ix (0x%08Ix): expected 0x%02x, found 0x%02x\n", 263 | section, pos, off+pos, *p1, *p2); 264 | rc = 1; 265 | } 266 | 267 | return rc; 268 | } 269 | 270 | static int validate_assembly(string *assembly, vector *old_shader) 271 | { 272 | vector assembly_vec(assembly->begin(), assembly->end()); 273 | vector new_shader; 274 | struct dxbc_header *old_dxbc_header = NULL, *new_dxbc_header = NULL; 275 | struct section_header *old_section_header = NULL, *new_section_header = NULL; 276 | uint32_t *old_section_offset_ptr = NULL, *new_section_offset_ptr = NULL; 277 | unsigned char *old_section = NULL, *new_section = NULL; 278 | uint32_t size; 279 | unsigned i, j; 280 | int rc = 0; 281 | HRESULT hret; 282 | 283 | // Assemble the disassembly and compare it to the original shader. We 284 | // use the version that reconstructs the signature sections from the 285 | // assembly text so that we can check the signature parsing separately 286 | // from the assembler. FIXME: We really need to clean up how the 287 | // buffers are passed between these functions 288 | try { 289 | hret = AssembleFluganWithSignatureParsing(&assembly_vec, &new_shader); 290 | if (FAILED(hret)) { 291 | LogInfo("\n*** Assembly verification pass failed: Reassembly failed 0x%x\n", hret); 292 | return 1; 293 | } 294 | } catch (AssemblerParseError &e) { 295 | string disassembly; 296 | 297 | LogInfo("\n%s\n\n", e.what()); 298 | 299 | // Assembler threw a parse error. Switch to disassembly with 300 | // hexdump mode 2 enabled to identify bad instructions: 301 | hret = DisassembleFlugan(old_shader->data(), old_shader->size(), &disassembly, 2, false); 302 | if (SUCCEEDED(hret)) 303 | LogInfo("%s\n", disassembly.c_str()); 304 | return 1; 305 | } 306 | 307 | // Get some useful pointers into the buffers: 308 | old_dxbc_header = (struct dxbc_header*)old_shader->data(); 309 | new_dxbc_header = (struct dxbc_header*)new_shader.data(); 310 | 311 | old_section_offset_ptr = (uint32_t*)((char*)old_dxbc_header + sizeof(struct dxbc_header)); 312 | for (i = 0; i < old_dxbc_header->num_sections; i++, old_section_offset_ptr++) { 313 | old_section_header = (struct section_header*)((char*)old_dxbc_header + *old_section_offset_ptr); 314 | 315 | // Find the matching section in the new shader: 316 | new_section_offset_ptr = (uint32_t*)((char*)new_dxbc_header + sizeof(struct dxbc_header)); 317 | for (j = 0; j < new_dxbc_header->num_sections; j++, new_section_offset_ptr++) { 318 | new_section_header = (struct section_header*)((char*)new_dxbc_header + *new_section_offset_ptr); 319 | 320 | if (memcmp(old_section_header->signature, new_section_header->signature, 4)) { 321 | // If it's a mismatch between SHDR and SHEX 322 | // (SHader EXtension) we'll flag a failure and 323 | // warn, but still compare since the sections 324 | // are identical 325 | if ((!strncmp(old_section_header->signature, "SHDR", 4) && 326 | !strncmp(new_section_header->signature, "SHEX", 4)) || 327 | (!strncmp(old_section_header->signature, "SHEX", 4) && 328 | !strncmp(new_section_header->signature, "SHDR", 4))) { 329 | if (args.lenient) { 330 | LogInfo("Notice: SHDR / SHEX mismatch\n"); 331 | } else { 332 | LogInfo("\n*** Assembly verification pass failed: SHDR / SHEX mismatch ***\n"); 333 | rc = 1; 334 | } 335 | } else 336 | continue; 337 | } 338 | 339 | LogDebug(" Checking section %.4s...", old_section_header->signature); 340 | 341 | size = min(old_section_header->size, new_section_header->size); 342 | old_section = (unsigned char*)old_section_header + sizeof(struct section_header); 343 | new_section = (unsigned char*)new_section_header + sizeof(struct section_header); 344 | 345 | if (validate_section(old_section_header->signature, old_section, new_section, size, old_dxbc_header)) { 346 | rc = 1; 347 | 348 | // If the failure was in a bytecode section, 349 | // output the disassembly with hexdump enabled: 350 | if (!strncmp(old_section_header->signature, "SHDR", 4) || 351 | !strncmp(old_section_header->signature, "SHEX", 4)) { 352 | string disassembly; 353 | hret = DisassembleFlugan(old_shader->data(), old_shader->size(), &disassembly, 2, false); 354 | if (SUCCEEDED(hret)) 355 | LogInfo("\n%s\n", disassembly.c_str()); 356 | } 357 | } else 358 | LogDebug(" OK\n"); 359 | 360 | if (old_section_header->size != new_section_header->size) { 361 | LogInfo("\n*** Assembly verification pass failed: size mismatch in section %.4s, expected %i, found %i\n", 362 | old_section_header->signature, old_section_header->size, new_section_header->size); 363 | rc = 1; 364 | } 365 | 366 | break; 367 | } 368 | if (j == new_dxbc_header->num_sections) { 369 | // Whitelist sections that are okay to be missed: 370 | if (!args.lenient && 371 | strncmp(old_section_header->signature, "STAT", 4) && // Compiler Statistics 372 | strncmp(old_section_header->signature, "RDEF", 4) && // Resource Definitions 373 | strncmp(old_section_header->signature, "SDBG", 4) && // Debug Info 374 | strncmp(old_section_header->signature, "Aon9", 4)) { // Level 9 shader bytecode 375 | //strncmp(old_section_header->signature, "SFI0", 4)) { // Subtarget Feature Info (not yet sure if this is critical or not) 376 | LogInfo("*** Assembly verification pass failed: Reassembled shader missing %.4s section (not whitelisted)\n", old_section_header->signature); 377 | rc = 1; 378 | } else 379 | LogInfo("Reassembled shader missing %.4s section\n", old_section_header->signature); 380 | } 381 | } 382 | 383 | // List any sections in the new shader that weren't in the old (e.g. section version mismatches): 384 | new_section_offset_ptr = (uint32_t*)((char*)new_dxbc_header + sizeof(struct dxbc_header)); 385 | for (i = 0; i < new_dxbc_header->num_sections; i++, new_section_offset_ptr++) { 386 | new_section_header = (struct section_header*)((char*)new_dxbc_header + *new_section_offset_ptr); 387 | 388 | old_section_offset_ptr = (uint32_t*)((char*)old_dxbc_header + sizeof(struct dxbc_header)); 389 | for (j = 0; j < old_dxbc_header->num_sections; j++, old_section_offset_ptr++) { 390 | old_section_header = (struct section_header*)((char*)old_dxbc_header + *old_section_offset_ptr); 391 | if (!memcmp(old_section_header->signature, new_section_header->signature, 4)) 392 | break; 393 | } 394 | if (j == old_dxbc_header->num_sections) 395 | LogInfo("Reassembled shader contains %.4s section not in original\n", new_section_header->signature); 396 | } 397 | 398 | if (!rc) 399 | LogInfo(" Assembly verification pass succeeded\n"); 400 | return rc; 401 | } 402 | 403 | 404 | static HRESULT Decompile(const void *pShaderBytecode, size_t BytecodeLength, string *hlslText, string *shaderModel) 405 | { 406 | // Set all to zero, so we only init the ones we are using here: 407 | ParseParameters p = {0}; 408 | DecompilerSettings d; 409 | bool patched = false; 410 | bool errorOccurred = false; 411 | string disassembly; 412 | HRESULT hret; 413 | 414 | hret = DisassembleMS(pShaderBytecode, BytecodeLength, &disassembly); 415 | if (FAILED(hret)) 416 | return E_FAIL; 417 | 418 | LogInfo(" creating HLSL representation\n"); 419 | 420 | p.bytecode = pShaderBytecode; 421 | p.decompiled = disassembly.c_str(); // XXX: Why do we call this "decompiled" when it's actually disassembled? 422 | p.decompiledSize = disassembly.size(); 423 | p.G = &d; 424 | 425 | // Disable IniParams and StereoParams registers. This avoids inserting 426 | // these in a shader that already has them, such as some of our test 427 | // cases. Also, while cmd_Decompiler is part of 3DMigoto, it is NOT 428 | // 3DMigoto so it doesn't really make sense that it should add 3DMigoto 429 | // registers, and if someone wants these registers there is nothing 430 | // stopping them from adding them by hand. May break scripts that use 431 | // cmd_Decompiler and expect these to be here, but those scripts can be 432 | // updated to add them or they can keep using an old version. 433 | d.IniParamsReg = -1; 434 | d.StereoParamsReg = -1; 435 | 436 | *hlslText = DecompileBinaryHLSL(p, patched, *shaderModel, errorOccurred); 437 | if (!hlslText->size() || errorOccurred) { 438 | LogInfo(" error while decompiling\n"); 439 | return E_FAIL; 440 | } 441 | 442 | return S_OK; 443 | } 444 | 445 | static int validate_hlsl(string *hlsl, string *shaderModel) 446 | { 447 | ID3DBlob *ppBytecode = NULL; 448 | ID3DBlob *pErrorMsgs = NULL; 449 | HRESULT hr; 450 | 451 | // Using optimisation level 0 for faster verification: 452 | hr = D3DCompile(hlsl->c_str(), hlsl->size(), "wrapper1349", 0, D3D_COMPILE_STANDARD_FILE_INCLUDE, 453 | "main", shaderModel->c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, 0, &ppBytecode, &pErrorMsgs); 454 | 455 | if (ppBytecode) 456 | ppBytecode->Release(); 457 | 458 | if (pErrorMsgs && LogFile) { // Check LogFile so the fwrite doesn't crash 459 | LPVOID errMsg = pErrorMsgs->GetBufferPointer(); 460 | SIZE_T errSize = pErrorMsgs->GetBufferSize(); 461 | LogInfo("--------------------------------------------- BEGIN ---------------------------------------------\n"); 462 | fwrite(errMsg, 1, errSize - 1, LogFile); 463 | LogInfo("---------------------------------------------- END ----------------------------------------------\n"); 464 | pErrorMsgs->Release(); 465 | } 466 | 467 | if (FAILED(hr)) { 468 | LogInfo("\n*** Decompiler validation pass failed!\n"); 469 | return EXIT_FAILURE; 470 | } 471 | 472 | // Not a guarantee that the decompilation result is correct, but at 473 | // least it compiled... 474 | 475 | LogInfo(" Decompiler validation pass succeeded\n"); 476 | return EXIT_SUCCESS; 477 | } 478 | 479 | template 480 | static int ReadInput(vector *srcData, string const *filename) 481 | { 482 | DWORD srcDataSize; 483 | DWORD readSize; 484 | BOOL bret; 485 | HANDLE fp; 486 | 487 | // TODO: Handle reading from stdin for use in a pipeline 488 | 489 | fp = CreateFileA(filename->c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 490 | if (fp == INVALID_HANDLE_VALUE) { 491 | LogInfo(" Shader not found: %s\n", filename->c_str()); 492 | return EXIT_FAILURE; 493 | } 494 | 495 | srcDataSize = GetFileSize(fp, 0); 496 | srcData->resize(srcDataSize); 497 | 498 | bret = ReadFile(fp, srcData->data(), srcDataSize, &readSize, 0); 499 | CloseHandle(fp); 500 | if (!bret || srcDataSize != readSize) { 501 | LogInfo(" Error reading input file\n"); 502 | return EXIT_FAILURE; 503 | } 504 | 505 | return EXIT_SUCCESS; 506 | } 507 | 508 | static int WriteOutput(string const *in_filename, char const *extension, string const *output) 509 | { 510 | string out_filename; 511 | FILE *fp; 512 | 513 | // TODO: Use 3DMigoto style filenames when possible, but remember we 514 | // have no guarantee that the input filename is already in a form that 515 | // 3DMigoto can understand, and we should not assume as such. Maybe 516 | // make it an option. 517 | // 518 | // TODO: Handle writing to stdout for use in a pipeline 519 | 520 | // Also handles the case where the file has no extension (well, unless 521 | // some fool does foo.bar\baz): 522 | out_filename = in_filename->substr(0, in_filename->rfind(".")) + extension; 523 | LogInfo(" -> %s\n", out_filename.c_str()); 524 | 525 | fopen_s(&fp, out_filename.c_str(), "wb"); 526 | if (!fp) 527 | return EXIT_FAILURE; 528 | 529 | fwrite(output->c_str(), 1, output->size(), fp); 530 | fclose(fp); 531 | 532 | return EXIT_SUCCESS; 533 | } 534 | 535 | static int process(string const *filename) 536 | { 537 | HRESULT hret; 538 | string output; 539 | vector srcData; 540 | string model; 541 | 542 | if (ReadInput(&srcData, filename)) 543 | return EXIT_FAILURE; 544 | 545 | if (args.disassemble_ms) { 546 | LogInfo("Disassembling (MS) %s...\n", filename->c_str()); 547 | hret = DisassembleMS(srcData.data(), srcData.size(), &output); 548 | if (FAILED(hret)) 549 | return EXIT_FAILURE; 550 | 551 | if (args.validate) { 552 | if (validate_assembly(&output, &srcData)) 553 | return EXIT_FAILURE; 554 | } 555 | 556 | if (WriteOutput(filename, ".msasm", &output)) 557 | return EXIT_FAILURE; 558 | } 559 | 560 | if (args.disassemble_flugan || args.disassemble_hexdump || args.disassemble_46) { 561 | LogInfo("Disassembling (Flugan) %s...\n", filename->c_str()); 562 | hret = DisassembleFlugan(srcData.data(), srcData.size(), &output, args.disassemble_hexdump, args.disassemble_46); 563 | if (FAILED(hret)) 564 | return EXIT_FAILURE; 565 | 566 | if (args.validate) { 567 | if (validate_assembly(&output, &srcData)) 568 | return EXIT_FAILURE; 569 | // TODO: Validate signature parsing instead of binary identical files 570 | } 571 | 572 | if (WriteOutput(filename, ".asm", &output)) 573 | return EXIT_FAILURE; 574 | 575 | } 576 | 577 | if (args.assemble) { 578 | LogInfo("Assembling %s...\n", filename->c_str()); 579 | vector new_bytecode; 580 | if (args.reflection_reference.empty()) { 581 | hret = AssembleFluganWithSignatureParsing(&srcData, &new_bytecode); 582 | if (FAILED(hret)) 583 | return EXIT_FAILURE; 584 | } else { 585 | vector refData; 586 | if (ReadInput(&refData, &args.reflection_reference)) 587 | return EXIT_FAILURE; 588 | new_bytecode = AssembleFluganWithOptionalSignatureParsing(&srcData, false, &refData); 589 | } 590 | 591 | // TODO: 592 | // if (args.validate) 593 | // disassemble again and perform fuzzy compare 594 | 595 | output = string(new_bytecode.begin(), new_bytecode.end()); 596 | if (WriteOutput(filename, ".shdr", &output)) 597 | return EXIT_FAILURE; 598 | 599 | } 600 | 601 | if (args.decompile) { 602 | LogInfo("Decompiling %s...\n", filename->c_str()); 603 | hret = Decompile(srcData.data(), srcData.size(), &output, &model); 604 | if (FAILED(hret)) 605 | return EXIT_FAILURE; 606 | 607 | if (args.validate) { 608 | if (validate_hlsl(&output, &model)) 609 | return EXIT_FAILURE; 610 | } 611 | 612 | if (WriteOutput(filename, ".hlsl", &output)) 613 | return EXIT_FAILURE; 614 | 615 | } 616 | 617 | if (args.decompile2) { 618 | LogInfo("Decompiling %s...\n", filename->c_str()); 619 | vector new_bytecode; 620 | if (args.reflection_reference.empty()) { 621 | hret = AssembleFluganWithSignatureParsing(&srcData, &new_bytecode); 622 | if (FAILED(hret)) 623 | return EXIT_FAILURE; 624 | } 625 | else { 626 | vector refData; 627 | if (ReadInput(&refData, &args.reflection_reference)) 628 | return EXIT_FAILURE; 629 | new_bytecode = AssembleFluganWithOptionalSignatureParsing(&srcData, false, &refData); 630 | } 631 | 632 | hret = Decompile(new_bytecode.data(), new_bytecode.size(), &output, &model); 633 | if (FAILED(hret)) 634 | return EXIT_FAILURE; 635 | 636 | if (args.validate) { 637 | if (validate_hlsl(&output, &model)) 638 | return EXIT_FAILURE; 639 | } 640 | 641 | if (WriteOutput(filename, ".hlsl", &output)) 642 | return EXIT_FAILURE; 643 | 644 | } 645 | 646 | return EXIT_SUCCESS; 647 | } 648 | 649 | 650 | //----------------------------------------------------------------------------- 651 | // Console App Entry-Point. 652 | //----------------------------------------------------------------------------- 653 | int main(int argc, char *argv[]) 654 | { 655 | int rc = EXIT_SUCCESS; 656 | 657 | parse_args(argc, argv); 658 | 659 | for (string const &filename : args.files) { 660 | try { 661 | rc = process(&filename) || rc; 662 | } catch (const exception & e) { 663 | LogInfo("\n*** UNHANDLED EXCEPTION: %s\n", e.what()); 664 | rc = EXIT_FAILURE; 665 | } 666 | 667 | if (rc && args.stop) 668 | return rc; 669 | } 670 | 671 | if (rc) 672 | LogInfo("\n*** At least one error occurred during run ***\n"); 673 | 674 | return rc; 675 | } 676 | 677 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/cmd_Decompiler.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Zip Release 22 | Win32 23 | 24 | 25 | Zip Release 26 | x64 27 | 28 | 29 | 30 | {25E1F732-DCF5-428E-928D-D39C499CC95F} 31 | Win32Proj 32 | cmd_Decompiler 33 | 10.0 34 | 35 | 36 | 37 | Application 38 | true 39 | v142 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | Application 57 | false 58 | v142 59 | true 60 | Unicode 61 | 62 | 63 | Application 64 | false 65 | v142 66 | true 67 | Unicode 68 | 69 | 70 | Application 71 | false 72 | v142 73 | true 74 | Unicode 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | false 100 | $(SolutionDir)crc32c-hw-1.0.5\include;$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um 101 | $(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86);$(SolutionDir)\x32\$(Configuration)\ 102 | $(SolutionDir)\x32\$(Configuration)\ 103 | $(ProjectDir)\x32\$(Configuration)\ 104 | 105 | 106 | false 107 | $(SolutionDir)crc32c-hw-1.0.5\include;$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(WindowsSdkDir_80)Include\um;$(WindowsSdkDir_80)Include\shared;$(VC_IncludePath) 108 | $(WindowsSdkDir_80)Lib\win8\um\x64;$(VC_LibraryPath_x64) 109 | $(SolutionDir)\x64\$(Configuration)\ 110 | $(ProjectDir)\x64\$(Configuration)\ 111 | 112 | 113 | false 114 | $(SolutionDir)crc32c-hw-1.0.5\include;$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(VC_IncludePath);$(IncludePath) 115 | $(VC_LibraryPath_x86);C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x86 116 | $(SolutionDir)\x32\$(Configuration)\ 117 | $(ProjectDir)\x32\$(Configuration)\ 118 | 119 | 120 | false 121 | $(SolutionDir)\x64\$(Configuration)\ 122 | $(ProjectDir)\x64\$(Configuration)\ 123 | 124 | 125 | false 126 | $(SolutionDir)crc32c-hw-1.0.5\include;$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(WindowsSdkDir_80)Include\um;$(WindowsSdkDir_80)Include\shared;$(VC_IncludePath) 127 | $(WindowsSdkDir_80)Lib\win8\um\x86;$(VC_LibraryPath_x86) 128 | $(SolutionDir)\x32\$(Configuration)\ 129 | $(ProjectDir)\x32\$(Configuration)\ 130 | 131 | 132 | false 133 | $(SolutionDir)crc32c-hw-1.0.5\include;$(SolutionDir)BinaryDecompiler;$(SolutionDir)BinaryDecompiler\include;$(WindowsSdkDir_80)Include\um;$(WindowsSdkDir_80)Include\shared;$(VC_IncludePath) 134 | $(WindowsSdkDir_80)Lib\win8\um\x64;$(VC_LibraryPath_x64) 135 | $(SolutionDir)\x64\$(Configuration)\ 136 | $(ProjectDir)\x64\$(Configuration)\ 137 | 138 | 139 | 140 | 141 | 142 | Level3 143 | Disabled 144 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 145 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 146 | MultiThreadedDebug 147 | true 148 | true 149 | 150 | 151 | Console 152 | true 153 | d3dcompiler.lib;D3D_Shaders.lib;%(AdditionalDependencies) 154 | true 155 | 156 | 157 | 158 | 159 | 160 | 161 | Copy D3Dcompiler_46.dll 162 | 163 | 164 | 165 | 166 | NotUsing 167 | Level3 168 | Disabled 169 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 170 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 171 | MultiThreadedDebug 172 | Async 173 | 174 | 175 | Console 176 | true 177 | d3dcompiler.lib;%(AdditionalDependencies) 178 | 179 | 180 | xcopy “$(WindowsSdkDir_80)redist\d3d\x64\d3dcompiler_46.dll” “$(TargetDir)” /E /Y 181 | 182 | 183 | 184 | 185 | Copy D3Dcompiler_46.dll 186 | 187 | 188 | 189 | 190 | Level3 191 | 192 | 193 | MaxSpeed 194 | true 195 | true 196 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 197 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 198 | MultiThreaded 199 | 200 | 201 | Console 202 | true 203 | true 204 | true 205 | d3dcompiler.lib;%(AdditionalDependencies) 206 | 207 | 208 | 209 | 210 | 211 | 212 | Copy D3Dcompiler_46.dll 213 | 214 | 215 | 216 | 217 | Level3 218 | 219 | 220 | MaxSpeed 221 | true 222 | true 223 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 224 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 225 | MultiThreaded 226 | Async 227 | false 228 | 229 | 230 | Console 231 | true 232 | true 233 | true 234 | d3dcompiler.lib;%(AdditionalDependencies) 235 | 236 | 237 | xcopy “$(WindowsSdkDir_80)redist\d3d\x64\d3dcompiler_46.dll” “$(TargetDir)” /E /Y 238 | 239 | 240 | 241 | 242 | Copy D3Dcompiler_46.dll 243 | 244 | 245 | 246 | 247 | Level3 248 | 249 | 250 | MaxSpeed 251 | true 252 | true 253 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 254 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 255 | MultiThreaded 256 | 257 | 258 | Console 259 | true 260 | true 261 | true 262 | d3dcompiler.lib;%(AdditionalDependencies) 263 | 264 | 265 | xcopy “$(WindowsSdkDir_80)redist\d3d\x86\d3dcompiler_46.dll” “$(TargetDir)” /E /Y 266 | 267 | 268 | 269 | 270 | Copy D3Dcompiler_46.dll 271 | 272 | 273 | 274 | 275 | Level3 276 | 277 | 278 | MaxSpeed 279 | true 280 | true 281 | WIN32;NDEBUG;_CONSOLE;_LIB;CRC32C_STATIC=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1;_USRDLL;%(PreprocessorDefinitions) 282 | $(SolutionDir);$(SolutionDir)HLSLDecompiler;$(SolutionDir)D3D_Shaders 283 | MultiThreaded 284 | 285 | 286 | Console 287 | true 288 | true 289 | true 290 | d3dcompiler.lib;%(AdditionalDependencies) 291 | 292 | 293 | xcopy “$(WindowsSdkDir_80)redist\d3d\x64\d3dcompiler_46.dll” “$(TargetDir)” /E /Y 294 | 295 | 296 | 297 | 298 | Copy D3Dcompiler_46.dll 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | {258d0ad2-b762-41e3-a0c1-cf831d859da4} 323 | 324 | 325 | {59a9b0c6-8302-48a9-96e0-126fb32fb9ed} 326 | 327 | 328 | 329 | 330 | 331 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/cmd_Decompiler.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/cmd_Decompiler.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -D -v "aaa.dxbc" 5 | WindowsLocalDebugger 6 | -D -v "aaa.dxbc" 7 | 8 | 9 | -D -v "aaa.dxbc" 10 | WindowsLocalDebugger 11 | -D -v "aaa.dxbc" 12 | 13 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/crc32c.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC32C_H 2 | #define CRC32C_H 3 | 4 | #ifndef CRC32C_STATIC 5 | #ifdef CRC32C_EXPORTS 6 | #define CRC32C_API __declspec(dllexport) 7 | #else 8 | #define CRC32C_API __declspec(dllimport) 9 | #endif 10 | #else 11 | #define CRC32C_API 12 | #endif 13 | 14 | #include 15 | 16 | /* 17 | Computes CRC-32C using Castagnoli polynomial of 0x82f63b78. 18 | This polynomial is better at detecting errors than the more common CRC-32 polynomial. 19 | CRC-32C is implemented in hardware on newer Intel processors. 20 | This function will use the hardware if available and fall back to fast software implementation. 21 | */ 22 | extern "C" CRC32C_API uint32_t crc32c_append( 23 | uint32_t crc, // initial CRC, typically 0, may be used to accumulate CRC from multiple buffers 24 | const uint8_t *input, // data to be put through the CRC algorithm 25 | size_t length); // length of the data in the input buffer 26 | 27 | extern "C" CRC32C_API void crc32c_unittest(); 28 | uint32_t crc32_fast(const void* data, size_t length, uint32_t previousCrc32 = 0); 29 | #endif 30 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // cmd_Decompiler.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // TODO: reference additional headers your program requires here 15 | -------------------------------------------------------------------------------- /HLSLDecompiler/cmd_Decompiler/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 the 3Dmigoto project authors (see the file AUTHORS.txt 4 | for a complete list) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## HLSLDecompiler 2 | 3 | Translate dxbc to hlsl source code. You can use it alone, or as a renderdoc shader processing tool to decompile shader. Although the decompiled result looks very like the disassembly, you can edit the decompiled source code and refresh to see the change in Renderdoc. It's very useful while learning and analyzing rendering techniques in games if you don't have source code. 4 | 5 | ### How to integrate into renderdoc 6 | 7 | 1. Put `hlsl_decompiler_wrapper.bat` and `cmd_Decompiler.exe` in the same directory 8 | 2. Renderdoc -> Tools -> Settings -> Shader Viewer -> Add 9 | | Field | Value | 10 | |------|:--------------:| 11 | | Name | HLSLDecompiler | 12 | | Tool Type | Custom Tool | 13 | | Executable | Set absolute path of `hlsl_decompiler_wrapper.bat` | 14 | | Command Line | {input_file} | 15 | | Input/Output | DXBC/HLSL | 16 | 17 | 3. Renderdoc -> Pipeline State View -> Choose Any Shader Stage -> Edit -> Decompile with ${Name} 18 | 4. Modify shader as you wish, and click Refresh button to see the change 19 | -------------------------------------------------------------------------------- /StereovisionHacks.sdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quon/HLSLDecompiler/2ac334f7bd2c82c6d7731c2651a8a1245b94237f/StereovisionHacks.sdf -------------------------------------------------------------------------------- /StereovisionHacks.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BinaryDecompiler", "BinaryDecompiler\BinaryDecompiler.vcxproj", "{258D0AD2-B762-41E3-A0C1-CF831D859DA4}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D_Shaders", "D3D_Shaders\D3D_Shaders.vcxproj", "{59A9B0C6-8302-48A9-96E0-126FB32FB9ED}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmd_Decompiler", "HLSLDecompiler\cmd_Decompiler\cmd_Decompiler.vcxproj", "{25E1F732-DCF5-428E-928D-D39C499CC95F}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Win32 = Debug|Win32 15 | Debug|x64 = Debug|x64 16 | Release|Win32 = Release|Win32 17 | Release|x64 = Release|x64 18 | Zip Release|Win32 = Zip Release|Win32 19 | Zip Release|x64 = Zip Release|x64 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Debug|Win32.ActiveCfg = Debug|Win32 23 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Debug|Win32.Build.0 = Debug|Win32 24 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Debug|x64.ActiveCfg = Debug|x64 25 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Debug|x64.Build.0 = Debug|x64 26 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Release|Win32.ActiveCfg = Release|Win32 27 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Release|Win32.Build.0 = Release|Win32 28 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Release|x64.ActiveCfg = Release|x64 29 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Release|x64.Build.0 = Release|x64 30 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Zip Release|Win32.ActiveCfg = Zip Release|Win32 31 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Zip Release|Win32.Build.0 = Zip Release|Win32 32 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Zip Release|x64.ActiveCfg = Zip Release|x64 33 | {258D0AD2-B762-41E3-A0C1-CF831D859DA4}.Zip Release|x64.Build.0 = Zip Release|x64 34 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Debug|Win32.ActiveCfg = Debug|Win32 35 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Debug|Win32.Build.0 = Debug|Win32 36 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Debug|x64.ActiveCfg = Debug|x64 37 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Debug|x64.Build.0 = Debug|x64 38 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Release|Win32.ActiveCfg = Release|Win32 39 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Release|Win32.Build.0 = Release|Win32 40 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Release|x64.ActiveCfg = Release|x64 41 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Release|x64.Build.0 = Release|x64 42 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Zip Release|Win32.ActiveCfg = Release|Win32 43 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Zip Release|Win32.Build.0 = Release|Win32 44 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Zip Release|x64.ActiveCfg = Release|x64 45 | {59A9B0C6-8302-48A9-96E0-126FB32FB9ED}.Zip Release|x64.Build.0 = Release|x64 46 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Debug|Win32.ActiveCfg = Debug|Win32 47 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Debug|x64.ActiveCfg = Debug|x64 48 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Release|Win32.ActiveCfg = Release|Win32 49 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Release|x64.ActiveCfg = Release|x64 50 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Zip Release|Win32.ActiveCfg = Zip Release|Win32 51 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Zip Release|Win32.Build.0 = Zip Release|Win32 52 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Zip Release|x64.ActiveCfg = Zip Release|x64 53 | {25E1F732-DCF5-428E-928D-D39C499CC95F}.Zip Release|x64.Build.0 = Zip Release|x64 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /StereovisionHacks.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quon/HLSLDecompiler/2ac334f7bd2c82c6d7731c2651a8a1245b94237f/StereovisionHacks.v12.suo -------------------------------------------------------------------------------- /hlsl_decompiler_wrapper.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem USAGE: 4 | rem 1. Put this batch file and cmd_Decompiler.exe in the same directory 5 | rem 2. Renderdoc -> Tools -> Settings -> Shader Viewer -> Add 6 | rem 2.1. Name: whatever you like 7 | rem 2.2. Tool Type: Custom Tool 8 | rem 2.3. Executable: Choose this batch file instead of cmd_Decompiler.exe 9 | rem 2.4. Command Line: {input_file} 10 | rem 2.5. Input/Output: DXBC/HLSL 11 | rem 3. Renderdoc -> Pipeline State View -> Choose Any Shader Stage 12 | rem 3.1. Edit -> Decompile with ${Name} 13 | rem 4. Modify shader as you wish, and click Refresh button to see the change 14 | 15 | : decompile input_file 16 | "%~dp0cmd_Decompiler.exe" -D "%1" 17 | 18 | : redirect to stdout 19 | for %%f in ("%1") do type "%%~dpnf.hlsl" 20 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace std; 4 | 5 | #include 6 | #include 7 | 8 | // Wrappers to make logging cleaner. 9 | 10 | extern FILE *LogFile; 11 | extern bool gLogDebug; 12 | 13 | // Note that for now I've left the definitions of LogFile and LogDebug as they 14 | // were - either declared locally in a file, as an extern, or from another 15 | // namespace altogether. At some point this needs to be cleaned up, but it's 16 | // probably not worth doing so unless we were switching to use a central 17 | // logging framework. 18 | 19 | #define LogInfo(fmt, ...) \ 20 | do { if (LogFile) fprintf(LogFile, fmt, __VA_ARGS__); } while (0) 21 | #define vLogInfo(fmt, va_args) \ 22 | do { if (LogFile) vfprintf(LogFile, fmt, va_args); } while (0) 23 | #define LogInfoW(fmt, ...) \ 24 | do { if (LogFile) fwprintf(LogFile, fmt, __VA_ARGS__); } while (0) 25 | 26 | #define LogDebug(fmt, ...) \ 27 | do { if (gLogDebug) LogInfo(fmt, __VA_ARGS__); } while (0) 28 | #define vLogDebug(fmt, va_args) \ 29 | do { if (gLogDebug) vLogInfo(fmt, va_args); } while (0) 30 | #define LogDebugW(fmt, ...) \ 31 | do { if (gLogDebug) LogInfoW(fmt, __VA_ARGS__); } while (0) 32 | 33 | static string LogTime() 34 | { 35 | string timeStr; 36 | char cTime[32]; 37 | tm timestruct; 38 | 39 | time_t ltime = time(0); 40 | localtime_s(×truct, <ime); 41 | asctime_s(cTime, sizeof(cTime), ×truct); 42 | 43 | timeStr = cTime; 44 | return timeStr; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct dxbc_header { 4 | char signature[4]; // DXCB 5 | uint32_t hash[4]; // Not quite MD5 6 | uint32_t one; // File version? Always 1 7 | uint32_t size; 8 | uint32_t num_sections; 9 | }; 10 | 11 | struct section_header { 12 | char signature[4]; 13 | uint32_t size; 14 | }; 15 | 16 | struct sgn_header { 17 | uint32_t num_entries; 18 | uint32_t unknown; // Always 0x00000008? Probably the offset to the sgn_entry array 19 | }; 20 | 21 | struct sgn_entry_common { 22 | uint32_t semantic_index; 23 | uint32_t system_value; 24 | uint32_t format; 25 | uint32_t reg; 26 | uint8_t mask; 27 | uint8_t used; 28 | uint16_t zero; // 0x0000 29 | }; 30 | 31 | struct sgn_entry_serialiased { // Base version - 24 bytes 32 | uint32_t name_offset; // Relative to the start of sgn_header 33 | struct sgn_entry_common common; 34 | // Followed by an unpadded array of null-terminated names 35 | // Whole structure padded to a multiple of 4 bytes with 0xAB 36 | }; 37 | 38 | struct sg5_entry_serialiased { // Version "5" (only exists for geometry shader outputs) - 28 bytes 39 | uint32_t stream; 40 | struct sgn_entry_serialiased sgn; 41 | }; 42 | 43 | struct sg1_entry_serialiased { // "Version "1" (most recent - I assume that's 5.1?) - 32 bytes 44 | struct sg5_entry_serialiased sg5; 45 | uint32_t min_precision; 46 | }; 47 | 48 | struct sgn_entry_unserialised { 49 | uint32_t stream; 50 | string name; 51 | uint32_t name_offset; // Relative to start of the name list 52 | struct sgn_entry_common common; 53 | uint32_t min_precision; 54 | }; 55 | -------------------------------------------------------------------------------- /util_min.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Less dependencies for inclusion in Hooked*.cpp that cannot include certain headers 3 | 4 | // Grant enums sensible powers that were taken away when C++ ignored C 5 | // MS already defines a macro DEFINE_ENUM_FLAG_OPERATORS that goes part way, 6 | // but only does the bitwise operators and returns the result as enum types (so 7 | // a simple 'if (enum & mask)' will still fail). Really what I want is the 8 | // namespacing of an enum class that behaves like an int as an enum does. Not 9 | // sure why C++ had to try to solve two problems at once and in doing so 10 | // created a brand new problem... 11 | #define SENSIBLE_ENUM(ENUMTYPE) \ 12 | inline int operator | (ENUMTYPE a, ENUMTYPE b) { return (((int)a) | ((int)b)); } \ 13 | inline int operator & (ENUMTYPE a, ENUMTYPE b) { return (((int)a) & ((int)b)); } \ 14 | inline int operator ^ (ENUMTYPE a, ENUMTYPE b) { return (((int)a) ^ ((int)b)); } \ 15 | inline int operator ~ (ENUMTYPE a) { return (~((int)a)); } \ 16 | inline ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) |= ((int)b)); } \ 17 | inline ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) &= ((int)b)); } \ 18 | inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) ^= ((int)b)); } \ 19 | inline bool operator || (ENUMTYPE a, ENUMTYPE b) { return (((int)a) || ((int)b)); } \ 20 | inline bool operator || ( bool a, ENUMTYPE b) { return (((int)a) || ((int)b)); } \ 21 | inline bool operator || (ENUMTYPE a, bool b) { return (((int)a) || ((int)b)); } \ 22 | inline bool operator && (ENUMTYPE a, ENUMTYPE b) { return (((int)a) && ((int)b)); } \ 23 | inline bool operator && ( bool a, ENUMTYPE b) { return (((int)a) && ((int)b)); } \ 24 | inline bool operator && (ENUMTYPE a, bool b) { return (((int)a) && ((int)b)); } \ 25 | inline bool operator ! (ENUMTYPE a) { return (!((int)a)); } 26 | 27 | template 28 | struct EnumName_t { 29 | T1 name; 30 | T2 val; 31 | }; 32 | 33 | const char* find_ini_section_lite(const char *buf, const char *section_name); 34 | bool find_ini_setting_lite(const char *buf, const char *setting, char *ret, size_t n); 35 | bool find_ini_bool_lite(const char *buf, const char *setting, bool def); 36 | int find_ini_int_lite(const char *buf, const char *setting, int def); 37 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by DirectX9.rc 4 | // Used by DirectX11.rc 5 | // Used by NVAPI.rc 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 101 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | 18 | // Used for embedded font resource for overlay 19 | #define SPRITEFONT 256 20 | #define IDR_COURIERBOLD 101 21 | #define IDR_COURIERSMALL 102 22 | #define IDR_ARIAL 103 23 | 24 | 25 | // Actual version, name, copyright information that is built into the dlls. 26 | // This is what an end-user will see when they look at dll properties. 27 | // The VERSION_MAJOR and VERSION_MINOR are hand edited when versions are to change. 28 | // The VERSION_REVISION is automatically incremented for every Publish build. 29 | 30 | #define VERSION_MAJOR 1 31 | #define VERSION_MINOR 3 32 | #define VERSION_REVISION 16 33 | 34 | #define STRINGIZE2(s) #s 35 | #define STRINGIZE(s) STRINGIZE2(s) 36 | 37 | #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION 38 | #define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \ 39 | "." STRINGIZE(VERSION_MINOR) \ 40 | "." STRINGIZE(VERSION_REVISION) \ 41 | 42 | #define VER_PRODUCTNAME_STR "3Dmigoto" 43 | #define VER_PRODUCT_VERSION VER_FILE_VERSION 44 | #define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR 45 | #define VER_COPYRIGHT_STR "Copyright (C) 2014-2019" 46 | 47 | #ifdef _DEBUG 48 | #define VER_VER_DEBUG VS_FF_DEBUG 49 | #else 50 | #define VER_VER_DEBUG 0 51 | #endif 52 | 53 | #define VER_FILEOS VOS_NT_WINDOWS32 54 | #define VER_FILEFLAGS VER_VER_DEBUG 55 | #define VER_FILETYPE VFT_APP 56 | 57 | --------------------------------------------------------------------------------