From 01672a9824edf0b16a741a7b6ab0322bf02e1c24 Mon Sep 17 00:00:00 2001 From: icculus Date: Sat, 9 Feb 2008 01:15:39 -0500 Subject: [PATCH] [svn] Initial add. --HG-- branch : trunk --- CMakeLists.txt | 5 + LICENSE.txt | 22 ++++ parse.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE.txt create mode 100644 parse.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..1d367bb4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +PROJECT(d3d2glsl) +ADD_EXECUTABLE(parse parse.c) + +# End of CMakeLists.txt ... + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..b574688e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ + + Copyright (c) 2008 Ryan C. Gordon. + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from + the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Ryan C. Gordon diff --git a/parse.c b/parse.c new file mode 100644 index 00000000..8465eb78 --- /dev/null +++ b/parse.c @@ -0,0 +1,320 @@ +#include +#include + +#define SWAP32(x) (x) +typedef unsigned int uint; +typedef unsigned char uint8; +typedef unsigned int uint32; + +// This enum complements of Filip Navara's public domain dev-cpp d3d9 header. +typedef enum +{ + OPCODE_NOP = 0, + OPCODE_MOV = 1, + OPCODE_ADD = 2, + OPCODE_SUB = 3, + OPCODE_MAD = 4, + OPCODE_MUL = 5, + OPCODE_RCP = 6, + OPCODE_RSQ = 7, + OPCODE_DP3 = 8, + OPCODE_DP4 = 9, + OPCODE_MIN = 10, + OPCODE_MAX = 11, + OPCODE_SLT = 12, + OPCODE_SGE = 13, + OPCODE_EXP = 14, + OPCODE_LOG = 15, + OPCODE_LIT = 16, + OPCODE_DST = 17, + OPCODE_LRP = 18, + OPCODE_FRC = 19, + OPCODE_M4x4 = 20, + OPCODE_M4x3 = 21, + OPCODE_M3x4 = 22, + OPCODE_M3x3 = 23, + OPCODE_M3x2 = 24, + OPCODE_CALL = 25, + OPCODE_CALLNZ = 26, + OPCODE_LOOP = 27, + OPCODE_RET = 28, + OPCODE_ENDLOOP = 29, + OPCODE_LABEL = 30, + OPCODE_DCL = 31, + OPCODE_POW = 32, + OPCODE_CRS = 33, + OPCODE_SGN = 34, + OPCODE_ABS = 35, + OPCODE_NRM = 36, + OPCODE_SINCOS = 37, + OPCODE_REP = 38, + OPCODE_ENDREP = 39, + OPCODE_IF = 40, + OPCODE_IFC = 41, + OPCODE_ELSE = 42, + OPCODE_ENDIF = 43, + OPCODE_BREAK = 44, + OPCODE_BREAKC = 45, + OPCODE_MOVA = 46, + OPCODE_DEFB = 47, + OPCODE_DEFI = 48, + OPCODE_TEXCOORD = 64, + OPCODE_TEXKILL = 65, + OPCODE_TEX = 66, + OPCODE_TEXBEM = 67, + OPCODE_TEXBEML = 68, + OPCODE_TEXREG2AR = 69, + OPCODE_TEXREG2GB = 70, + OPCODE_TEXM3x2PAD = 71, + OPCODE_TEXM3x2TEX = 72, + OPCODE_TEXM3x3PAD = 73, + OPCODE_TEXM3x3TEX = 74, + OPCODE_RESERVED0 = 75, + OPCODE_TEXM3x3SPEC = 76, + OPCODE_TEXM3x3VSPEC = 77, + OPCODE_EXPP = 78, + OPCODE_LOGP = 79, + OPCODE_CND = 80, + OPCODE_DEF = 81, + OPCODE_TEXREG2RGB = 82, + OPCODE_TEXDP3TEX = 83, + OPCODE_TEXM3x2DEPTH = 84, + OPCODE_TEXDP3 = 85, + OPCODE_TEXM3x3 = 86, + OPCODE_TEXDEPTH = 87, + OPCODE_CMP = 88, + OPCODE_BEM = 89, + OPCODE_DP2ADD = 90, + OPCODE_DSX = 91, + OPCODE_DSY = 92, + OPCODE_TEXLDD = 93, + OPCODE_SETP = 94, + OPCODE_TEXLDL = 95, + OPCODE_BREAKP = 96, + OPCODE_PHASE = 0xfffd, +} OpcodeVal; + + +static int parse_version_token(const uint32 *tokens, const uint32 tokencount) +{ + if (tokencount == 0) + return -1; // no tokens at all? + + const uint32 token = SWAP32(*tokens); + const uint32 shadertype = ((token >> 16) & 0xFFFF); + const uint32 major = ((token >> 8) & 0xFF); + const uint32 minor = (token & 0xFF); + + if (shadertype == 0xFFFF) + printf("Pixel shader\n"); + else if (shadertype == 0xFFFE) + printf("Vertex shader\n"); + else + return -1; // geometry shader? Unsupported at the moment. FAIL. + + printf("Version %u.%u\n", (uint) major, (uint) minor); + + return 1; // ate one token. +} // parse_version_token + + +static int parse_comment_token(const uint32 *tokens, const uint32 tokencount) +{ + const uint32 token = SWAP32(*tokens); + if ((token & 0xFFFF) != 0xFFFE) + return 0; // not a comment token. + else if ((token & 0x80000000) != 0) + return -1; // msdn docs say high bit must be zero. FAIL. + + const uint32 commenttoks = ((token >> 16) & 0xFFFF); + const uint32 commentlen = commenttoks * sizeof (uint32); + printf("Comment (%u tokens, %u bytes): ", + (uint) commenttoks, (uint) commentlen); + + uint32 i = 0; + const char *comment = (const char *) (tokens+1); + while (i < commentlen) + fputc(comment[i++], stdout); + + printf("\n"); + + return commenttoks + 1; // comment data plus the initial token. +} // parse_comment_token + + +static int parse_end_token(const uint32 *tokens, const uint32 tokencount) +{ + if (SWAP32(*tokens) != 0x0000FFFF) // end token is always 0x0000FFFF. + return 0; // not us, eat no tokens. + + printf("END\n"); + + // we _must_ be last. If so, eat the token. Otherwise: FAIL. + return (tokencount == 1) ? 1 : -1; +} // parse_end_token + + +static int parse_instruction_token(const uint32 *tokens, const uint32 tokencount) +{ + const uint32 token = SWAP32(*tokens); + const uint32 opcode = (token & 0xFFFF); + const uint32 controls = ((token >> 16) & 0xFF); + const uint32 insttoks = ((token >> 24) & 0x0F); + const int coissue = (token & 0x40000000) ? 1 : 0; + const int predicated = (token & 0x10000000) ? 1 : 0; + + if ((token & 0x80000000) != 0) + return -1; // msdn docs say high bit must be zero. FAIL. + + #define PARSE_OP(op) printf("OPCODE %s\n", #op); + //case OPCODE_##op: + // parse_op_##op(tokens+1, opcode, controls, insttoks, coissue, predicated); + // break; + + PARSE_OP(NOP); + PARSE_OP(MOV); + PARSE_OP(ADD); + PARSE_OP(SUB); + PARSE_OP(MAD); + PARSE_OP(MUL); + PARSE_OP(RCP); + PARSE_OP(RSQ); + PARSE_OP(DP3); + PARSE_OP(DP4); + PARSE_OP(MIN); + PARSE_OP(MAX); + PARSE_OP(SLT); + PARSE_OP(SGE); + PARSE_OP(EXP); + PARSE_OP(LOG); + PARSE_OP(LIT); + PARSE_OP(DST); + PARSE_OP(LRP); + PARSE_OP(FRC); + PARSE_OP(M4x4); + PARSE_OP(M4x3); + PARSE_OP(M3x4); + PARSE_OP(M3x3); + PARSE_OP(M3x2); + PARSE_OP(CALL); + PARSE_OP(CALLNZ); + PARSE_OP(LOOP); + PARSE_OP(RET); + PARSE_OP(ENDLOOP); + PARSE_OP(LABEL); + PARSE_OP(DCL); + PARSE_OP(POW); + PARSE_OP(CRS); + PARSE_OP(SGN); + PARSE_OP(ABS); + PARSE_OP(NRM); + PARSE_OP(SINCOS); + PARSE_OP(REP); + PARSE_OP(ENDREP); + PARSE_OP(IF); + PARSE_OP(IFC); + PARSE_OP(ELSE); + PARSE_OP(ENDIF); + PARSE_OP(BREAK); + PARSE_OP(BREAKC); + PARSE_OP(MOVA); + PARSE_OP(DEFB); + PARSE_OP(DEFI); + PARSE_OP(TEXCOORD); + PARSE_OP(TEXKILL); + PARSE_OP(TEX); + PARSE_OP(TEXBEM); + PARSE_OP(TEXBEML); + PARSE_OP(TEXREG2AR); + PARSE_OP(TEXREG2GB); + PARSE_OP(TEXM3x2PAD); + PARSE_OP(TEXM3x2TEX); + PARSE_OP(TEXM3x3PAD); + PARSE_OP(TEXM3x3TEX); + PARSE_OP(RESERVED0); + PARSE_OP(TEXM3x3SPEC); + PARSE_OP(TEXM3x3VSPEC); + PARSE_OP(EXPP); + PARSE_OP(LOGP); + PARSE_OP(CND); + PARSE_OP(DEF); + PARSE_OP(TEXREG2RGB); + PARSE_OP(TEXDP3TEX); + PARSE_OP(TEXM3x2DEPTH); + PARSE_OP(TEXDP3); + PARSE_OP(TEXM3x3); + PARSE_OP(TEXDEPTH); + PARSE_OP(CMP); + PARSE_OP(BEM); + PARSE_OP(DP2ADD); + PARSE_OP(DSX); + PARSE_OP(DSY); + PARSE_OP(TEXLDD); + PARSE_OP(SETP); + PARSE_OP(TEXLDL); + PARSE_OP(BREAKP); + PARSE_OP(PHASE); + + #undef PARSE_OP +} // parse_instruction_token + + +static int parse_token(const uint32 *tokens, const uint32 tokencount) +{ + int retval = -1; + int rc = 0; + + if (tokencount == 0) + return -1; // shouldn't happen, but just in case... + + if ((rc = parse_comment_token(tokens, tokencount)) != 0) + return rc; + + if ((rc = parse_end_token(tokens, tokencount)) != 0) + return rc; + + if ((rc = parse_instruction_token(tokens, tokencount)) != 0) + return rc; + + return -1; // nothing handled this? FAIL. +} // parse_token + + +int D3D2GLSL_parse(const uint8 *tokenbuf, const uint32 bufsize) +{ + const uint32 *tokens = (const uint32 *) tokenbuf; + uint32 tokencount = bufsize / sizeof (uint32); + int rc = parse_version_token(tokens, tokencount); + + // parse out the rest of the tokens after the version token... + while ((rc > 0) && (tokencount > 0)) + { + tokens += rc; + tokencount -= rc; + rc = parse_token(tokens, tokencount); + } // while + + return ((rc <= 0) || (tokencount > 0)) ? 0 : 1; +} // D3D2GLSL_parse + + +int main(int argc, char **argv) +{ + if (argv[1] != NULL) + { + FILE *io = fopen(argv[1], "rb"); + if (io != NULL) + { + uint8 *buf = (uint8 *) malloc(1000000); + int rc = fread(buf, 1, 1000000, io); + fclose(io); + D3D2GLSL_parse(buf, rc); + free(buf); + } // if + } // if + + return 0; +} // main + +// end of parse.c ... +