Filled in and fixed some stuff in the Effect parser.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 31 May 2011 16:01:10 -0400
changeset 1037 b102a563d9cb
parent 1036 8a3597b44ff7
child 1038 9b23f9a8aa31
Filled in and fixed some stuff in the Effect parser. This code is all nasty, because I'm planning to rewrite it later.
mojoshader.h
mojoshader_effects.c
utils/testparse.c
--- a/mojoshader.h	Tue May 31 03:23:39 2011 -0400
+++ b/mojoshader.h	Tue May 31 16:01:10 2011 -0400
@@ -699,6 +699,12 @@
 
 /* Effects interface... */  /* !!! FIXME: THIS API IS NOT STABLE YET! */
 
+typedef struct MOJOSHADER_effectParam
+{
+    const char *name;
+    const char *semantic;
+} MOJOSHADER_effectParam;
+
 typedef struct MOJOSHADER_effectState
 {
     unsigned int type;
@@ -755,6 +761,18 @@
     const char *profile;
 
     /*
+     * The number of params pointed to by (params).
+     */
+    int param_count;
+
+    /*
+     * (param_count) elements of data that specify parameter bind points for
+     *  this effect.
+     * This can be NULL on error or if (param_count) is zero.
+     */
+    MOJOSHADER_effectParam *params;
+
+    /*
      * The number of elements pointed to by (techniques).
      */
     int technique_count;
--- a/mojoshader_effects.c	Tue May 31 03:23:39 2011 -0400
+++ b/mojoshader_effects.c	Tue May 31 16:01:10 2011 -0400
@@ -217,11 +217,14 @@
     if (len < 8)
         goto parseEffect_unexpectedEOF;
 
+    const uint8 *base = NULL;
     if (readui32(&ptr, &len) != 0xFEFF0901) // !!! FIXME: is this always magic?
         goto parseEffect_notAnEffectsFile;
     else
     {
         const uint32 offset = readui32(&ptr, &len);
+        base = ptr;
+//printf("base offset == %u\n", offset);
         if (offset > len)
             goto parseEffect_unexpectedEOF;
         ptr += offset;
@@ -236,27 +239,61 @@
     const uint32 numparams = readui32(&ptr, &len);
     const uint32 numtechniques = readui32(&ptr, &len);
 
-    readui32(&ptr, &len); // !!! FIXME: there are 8 unknown bytes here.
-    readui32(&ptr, &len);
+    readui32(&ptr, &len); // !!! FIXME: there are 8 unknown bytes here. Annotations?
+    /*const uint32 numobjects = */ readui32(&ptr, &len);
 
-    for (i = 0; i < numparams; i++)
+    if (numparams > 0)
     {
-        if (len < 16)
-            goto parseEffect_unexpectedEOF;
+        siz = sizeof (MOJOSHADER_effectParam) * numparams;
+        retval->params = (MOJOSHADER_effectParam *) m(siz, d);
+        if (retval->params == NULL)
+            goto parseEffect_outOfMemory;
+        memset(retval->params, '\0', siz);
+
+        retval->param_count = numparams;
+
+        for (i = 0; i < numparams; i++)
+        {
+            if (len < 16)
+                goto parseEffect_unexpectedEOF;
 
-        /*const uint32 startoffset = */ readui32(&ptr, &len);
-        /*const uint32 endoffset = */ readui32(&ptr, &len);
-        readui32(&ptr, &len);  // !!! FIXME: don't know what this is.
-        const uint32 numannos = readui32(&ptr, &len);
-        for (j = 0; j < numannos; j++)
-        {
-            if (len < 8)
-                goto parseEffect_unexpectedEOF;
-            // !!! FIXME: parse annotations.
-            readui32(&ptr, &len);
-            readui32(&ptr, &len);
+            const uint32 typeoffset = readui32(&ptr, &len);
+            const uint32 valoffset = readui32(&ptr, &len);
+            const uint32 flags = readui32(&ptr, &len);
+            const uint32 numannos = readui32(&ptr, &len);
+            for (j = 0; j < numannos; j++)
+            {
+                if (len < 8)
+                    goto parseEffect_unexpectedEOF;
+                // !!! FIXME: parse annotations.
+                readui32(&ptr, &len);
+                readui32(&ptr, &len);
+            } // for
+
+            const uint8 *typeptr = base + typeoffset;
+            unsigned int typelen = 9999999;  // !!! FIXME
+            const uint32 paramtype = readui32(&typeptr, &typelen);
+            const uint32 paramclass = readui32(&typeptr, &typelen);
+            const uint32 paramname = readui32(&typeptr, &typelen);
+            const uint32 paramsemantic = readui32(&typeptr, &typelen);
+
+            // !!! FIXME: sanity checks!
+            const char *namestr = ((const char *) base) + paramname;
+            const char *semstr = ((const char *) base) + paramsemantic;
+            uint32 len;
+            char *strptr;
+            len = *((const uint32 *) namestr);
+            strptr = (char *) m(len + 1, d);
+            memcpy(strptr, namestr + 4, len);
+            strptr[len] = '\0';
+            retval->params[i].name = strptr;
+            len = *((const uint32 *) semstr);
+            strptr = (char *) m(len + 1, d);
+            memcpy(strptr, semstr + 4, len);
+            strptr[len] = '\0';
+            retval->params[i].semantic = strptr;
         } // for
-    } // for
+    } // if
 
     uint32 numshaders = 0;  // we'll calculate this later.
 
@@ -279,23 +316,37 @@
             
             MOJOSHADER_effectTechnique *technique = &retval->techniques[i];
 
-            // !!! FIXME: is this always 12?
-            const uint32 nameoffset = readui32(&ptr, &len) + 12;
-            readui32(&ptr, &len);  // !!! FIXME: don't know what this field does.
+            const uint32 nameoffset = readui32(&ptr, &len);
+            const uint32 numannos = readui32(&ptr, &len);
             const uint32 numpasses = readui32(&ptr, &len);
 
             if (nameoffset >= _len)
                 goto parseEffect_unexpectedEOF;
 
+            if (numannos > 0)
+            {
+                // !!! FIXME: expose these to the caller?
+                for (j = 0; j < numannos; j++)
+                {
+                    if (len < 8)
+                        goto parseEffect_unexpectedEOF;
+                    readui32(&ptr, &len);  // typedef offset
+                    readui32(&ptr, &len);  // value offset
+                } // for
+            } // if
+
+            // !!! FIXME: verify this doesn't go past EOF looking for a null.
+            {
+                const char *namestr = ((char *) base) + nameoffset;
+                uint32 len = *((const uint32 *) namestr);
+                char *strptr = (char *) m(len + 1, d);
+                memcpy(strptr, namestr + 4, len);
+                strptr[len] = '\0';
+                technique->name = strptr;
+            }
+
             if (numpasses > 0)
             {
-                // !!! FIXME: verify this doesn't go past EOF looking for a null.
-                siz = strlen(((const char *) buf) + nameoffset) + 1;
-                technique->name = (char *) m(siz, d);
-                if (technique->name == NULL)
-                    goto parseEffect_outOfMemory;
-                strcpy((char *) technique->name, ((const char *) buf) + nameoffset);
-
                 technique->pass_count = numpasses;
 
                 siz = sizeof (MOJOSHADER_effectPass) * numpasses;
@@ -311,20 +362,34 @@
 
                     MOJOSHADER_effectPass *pass = &technique->passes[j];
 
-                    // !!! FIXME: is this always 12?
-                    const uint32 passnameoffset = readui32(&ptr, &len) + 12;
-                    readui32(&ptr, &len);  // !!! FIXME: don't know what this field does.
+                    const uint32 passnameoffset = readui32(&ptr, &len);
+                    const uint32 numannos = readui32(&ptr, &len);
                     const uint32 numstates = readui32(&ptr, &len);
 
                     if (passnameoffset >= _len)
                         goto parseEffect_unexpectedEOF;
 
                     // !!! FIXME: verify this doesn't go past EOF looking for a null.
-                    siz = strlen(((const char *) buf) + passnameoffset) + 1;
-                    pass->name = (char *) m(siz, d);
-                    if (pass->name == NULL)
-                        goto parseEffect_outOfMemory;
-                    strcpy((char *) pass->name, ((const char *) buf) + passnameoffset);
+                    {
+                        const char *namestr = ((char *) base) + passnameoffset;
+                        uint32 len = *((const uint32 *) namestr);
+                        char *strptr = (char *) m(len + 1, d);
+                        memcpy(strptr, namestr + 4, len);
+                        strptr[len] = '\0';
+                        pass->name = strptr;
+                    }
+
+                    if (numannos > 0)
+                    {
+                        for (k = 0; k < numannos; k++)
+                        {
+                            if (len < 8)
+                                goto parseEffect_unexpectedEOF;
+                            // !!! FIXME: do something with this.
+                            readui32(&ptr, &len);
+                            readui32(&ptr, &len);
+                        } // for
+                    } // if
 
                     if (numstates > 0)
                     {
@@ -503,6 +568,13 @@
 
     f((void *) effect->profile, d);
 
+    for (i = 0; i < effect->param_count; i++)
+    {
+        f((void *) effect->params[i].name, d);
+        f((void *) effect->params[i].semantic, d);
+    } // for
+    f(effect->params, d);
+
     for (i = 0; i < effect->technique_count; i++)
     {
         MOJOSHADER_effectTechnique *technique = &effect->techniques[i];
--- a/utils/testparse.c	Tue May 31 03:23:39 2011 -0400
+++ b/utils/testparse.c	Tue May 31 16:01:10 2011 -0400
@@ -400,6 +400,15 @@
         const MOJOSHADER_effectTechnique *technique = effect->techniques;
         const MOJOSHADER_effectTexture *texture = effect->textures;
         const MOJOSHADER_effectShader *shader = effect->shaders;
+        const MOJOSHADER_effectParam *param = effect->params;
+
+        for (i = 0; i < effect->param_count; i++, param++)
+        {
+            INDENT();
+            printf("PARAM #%d '%s' -> '%s'\n", i, param->name, param->semantic);
+        } // for
+
+        printf("\n");
 
         for (i = 0; i < effect->technique_count; i++, technique++)
         {