added DefineFunction and With parsing.
[swftools.git] / lib / modules / swfaction.c
index 014730b..48087ab 100644 (file)
@@ -35,7 +35,7 @@ m: method (byte) swf_GetUrl2:(0=none, 1=get, 2=post)/GotoFrame2:(1=play)
 b: branch (word) (number of bytes)
 p (push): type(byte), type=0:string, type=1:double
 {: define function (name (string), num (word), params (num strings), codesize (word)
-o: object (string)
+o: codesize (word) object (string)
 r: register (byte)
  */
 {3,"End", 0x00, ""},
@@ -126,7 +126,8 @@ r: register (byte)
 {5,"ToString", 0x4b,""}, //?
 {5,"TypeOf", 0x44,""},
 {5,"Add2", 0x47,""},
-{5,"Less2", 0x48,""}
+{5,"Less2", 0x48,""},
+{5/*6?*/,"Less3", 0x67,""}
 };
 static int definedactions = sizeof(actions)/sizeof(struct Action);
 
@@ -191,7 +192,7 @@ void swf_ActionSet(TAG*tag, ActionTAG*action)
     }
 }
 
-int OpAdvance(char c, char*data)
+int OpAdvance(char c, U8*data)
 {
     switch (c)
     {
@@ -234,116 +235,202 @@ int OpAdvance(char c, char*data)
            } else return 1;
            break;
        }
+       case 'o': {
+           return 2;
+       }
+       case '{': {
+           U16 num;
+           U16 codesize;
+           U8* odata = data;
+           int t;
+           while(*data++); //name
+           num = (*data++)*256; //num
+           num += (*data++);
+           for(t=0;t<num;t++)
+               while(*data++); //param
+           codesize = (*data++)*256; //num
+           codesize += (*data++);
+           return data-odata;
+       }
     }
     return 0;
 }
-
-/* TODO: this should be in swfdump.c */
+#define ATAG_FULLLENGTH(atag) ((atag)->len + 1 + ((atag)->op&0x80?2:0))
+#define MAX_LEVELS 16
+/* TODO: * this should be in swfdump.c */
 void swf_DumpActions(ActionTAG*atag, char*prefix) 
 {
     int t;
     U8*data;
     char* cp;
     int entry = 0;
-
+    char spaces[MAX_LEVELS*4+1];
+    struct {
+       char*text;
+       int count;
+    } counter[MAX_LEVELS];
+    int countpos = 0;
 #ifdef MAX_LOOKUP
-
     char * lookup[MAX_LOOKUP];
     memset(lookup,0x00,sizeof(lookup));
-
 #endif
+    memset(spaces, 32, sizeof(spaces));
+    spaces[sizeof(spaces)-1] = 0;
 
    if (!prefix)
         prefix="";
 
     while(atag)
     {
+       char*indent = &spaces[sizeof(spaces)-1-countpos*4];
        U8 poollen = 0;
        for(t=0;t<definedactions;t++)
            if(actions[t].op == atag->op)
                break;
 
        if(t==definedactions) {
-           printf("%s (%5d bytes) action: %02x\n", prefix, atag->len, atag->op);
-           atag = atag->next;
-           continue;
+           printf("%s (%5d bytes) action:%s unknown[%02x]", prefix, atag->len, indent, atag->op);
+       } else {
+           printf("%s (%5d bytes) action:%s %s", prefix, atag->len, indent, actions[t].name);
        }
-       printf("%s (%5d bytes) action: %s", prefix, atag->len, actions[t].name);
-       cp = actions[t].flags;
        data = atag->data;
-       if(atag->len) //TODO: check for consistency: should we have a length?
-       while(*cp)
+       if(atag->len && t!=definedactions) //TODO: check for consistency: should we have a length?
        {
-           switch(*cp)
-           {
-               case 'f': {
-                   printf(" %d", *(U16*)data); //FIXME: le/be
-               } break;
-               case 'u': {
-                   printf(" URL:\"%s\"", data);
-               } break;
-               case 't': {
-                   printf(" Target:\"%s\"", data);
-               } break;
-               case 'l': {
-                   printf(" Label:\"%s\"", data);
-               } break;
-               case 'c': {
-                   printf(" String:\"%s\"", data);
+         cp = actions[t].flags;
+         while(*cp)
+         {
+             switch(*cp)
+             {
+                 case 'f': { //frame
+                     printf(" %d", data[0]+256*data[1]);
+                 } break;
+                 case 'u': {
+                     printf(" URL:\"%s\"", data);
+                 } break;
+                 case 't': {
+                     printf(" Target:\"%s\"", data);
+                 } break;
+                 case 'l': {
+                     printf(" Label:\"%s\"", data);
+                 } break;
+                 case 'c': {
+                     printf(" String:\"%s\"", data);
 #ifdef MAX_LOOKUP
-                    if (entry<MAX_LOOKUP)
-                     lookup[entry++] = strdup(data);
+                     if (entry<MAX_LOOKUP)
+                       lookup[entry++] = strdup(data);
 #endif
-               } break;
-               case 'C': {
-                   poollen = *data;
-                    entry = 0;
-                   printf("(%d entries)", poollen);
-               } break;
-               case 's': {
-                   printf(" +%d", *data);
-               } break;
-               case 'm': {
-                   //m: method (byte) url:(0=none, 1=get, 2=datat)/gf2:(1=play)
-                   printf(" %d", *data);
-               } break;
-               case 'b': {
-                   printf(" %d", *(U16*)data);
-               } break;
-               case 'p': {
-                   U8 type = *data;
-                   char*value = data+1;
-                   if(type == 0) {
-                       printf(" String:\"%s\"", value);
-                   } else if (type == 1) {
-                       printf(" Float:%f", *(float*)value);
-                   } else if (type == 2) {
-                       printf(" NULL");
-                   } else if (type == 4) {
-                       printf(" register:%d", *value);
-                   } else if (type == 5) {
-                       printf(" bool:%s", *value?"true":"false");
-                   } else if (type == 6) {
-                       printf(" float:%f", *(double*)value);
-                   } else if (type == 7) {
-                       printf(" int:%d", *(int*)value);
-                   } else if (type == 8) {
-                       printf(" Lookup:%d", *value);
+                 } break;
+                 case 'C': {
+                     poollen = *data;
+                     entry = 0;
+                     printf("(%d entries)", poollen);
+                 } break;
+                 case 's': {
+                     printf(" +%d", *data);
+                 } break;
+                 case 'm': {
+                     //m: method (byte) url:(0=none, 1=get, 2=datat)/gf2:(1=play)
+                     printf(" %d", *data);
+                 } break;
+                 case '{': {
+                     U16 num;
+                     U16 codesize;
+                     int t;
+                     printf(" %s(", data);
+                     while(*data++); //name
+                     num = (*data++); //num
+                     num += (*data++)*256;
+                     for(t=0;t<num;t++) {
+                         printf("%s",data);
+                         if(t<num-1)
+                             printf(", ");
+                         while(*data++); //param
+                     }
+                     printf(")");
+                     codesize = (*data++); //num
+                     codesize += (*data++)*256;
+                     printf(" codesize:%d ",codesize);
+                     printf("\n%s                       %s{", prefix, indent);
+                     if(countpos>=15) {
+                         printf("Error: nested too deep\n");
+                         continue;
+                     }
+                     counter[countpos].text = "}";
+                     counter[countpos].count = codesize + ATAG_FULLLENGTH(atag);
+                     countpos++;
+                 } break;
+                 case 'o': {
+                     int t;
+                     U16 codesize = data[0]+256*data[1];
+                     printf(" codesize:%d ", codesize);
+
+                     /* the following tries to find the "string"
+                        the flash documentation speaks of- I've
+                        never actually seen one yet. -mk */
+                     for(t=2;t<atag->len;t++)
+                         printf("[%02x]", atag->data[t]);
+
+                     printf("\n%s                       %s{", prefix, indent);
+                     if(countpos>=15) {
+                         printf("Error: nested too deep\n");
+                         continue;
+                     }
+                     counter[countpos].text = "}";
+                     counter[countpos].count = codesize + ATAG_FULLLENGTH(atag);
+                     countpos++;
+                 } break;
+                 case 'b': {
+                     printf(" %d", data[0]+256*(signed char)data[1]);
+                 } break;
+                 case 'p': {
+                     U8 type = *data;
+                     unsigned char*value = data+1;
+                     if(type == 0) {
+                         printf(" String:\"%s\"", value);
+                     } else if (type == 1) {
+                         U32 f = value[0]+(value[1]<<8)+
+                                 (value[2]<<16)+(value[3]<<24);
+                         printf(" Float:%f", *(float*)&f);
+                     } else if (type == 2) {
+                         printf(" NULL");
+                     } else if (type == 4) {
+                         printf(" register:%d", *value);
+                     } else if (type == 5) {
+                         printf(" bool:%s", *value?"true":"false");
+                     } else if (type == 6) {
+                         U8 a[8];
+                         int t;
+                         memcpy(&a[4],value,4);
+                         memcpy(a,&value[4],4);
+#ifdef WORDS_BIGENDIAN
+                         for(t=0;t<4;t++) {
+                             U8 tmp = a[t];
+                             a[t]=a[7-t];
+                             a[7-t] = tmp;
+                         }
+#endif
+                         printf(" double:%f", *(double*)a);
+                     } else if (type == 7) {
+                         printf(" int:%d", value[0]+(value[1]<<8)+
+                                           (value[2]<<16)+(value[3]<<24));
+                     } else if (type == 8) {
+                         printf(" Lookup:%d", *value);
 #ifdef MAX_LOOKUP
-                       if (lookup[*value])
-                         printf(" (\"%s\")",lookup[*value]);
+                         if (lookup[*value])
+                           printf(" (\"%s\")",lookup[*value]);
 #endif
-                   } else {
-                       printf(" UNKNOWN[%02x]",type);
-                   }
-               } break;
-           }
-           data += OpAdvance(*cp, data);
-           if((*cp!='c' || !poollen) &&
-              (*cp!='p' || !(data<&atag->data[atag->len])))
-               cp++;
-           if(poollen)
-               poollen--;
+                     } else {
+                         printf(" UNKNOWN[%02x]",type);
+                     }
+                 } break;
+             }
+             data += OpAdvance(*cp, data);
+             if((*cp!='c' || !poollen) &&
+                (*cp!='p' || !(data<&atag->data[atag->len])))
+                 cp++;
+             if(poollen)
+                 poollen--;
+         }
        }
 
        if(data < atag->data + atag->len)
@@ -360,6 +447,24 @@ void swf_DumpActions(ActionTAG*atag, char*prefix)
            printf("\")");
        }
        printf("\n");
+
+       for(t=0;t<countpos;t++) {
+           counter[t].count -= ATAG_FULLLENGTH(atag);
+           if(counter[t].count < 0) {
+               printf("===== Error: Oplength errors =====\n");
+               countpos = 0;
+               break;
+           }
+       }
+
+       while(countpos && !counter[countpos-1].count)
+       {
+           printf("%s                   %s%s\n", 
+               prefix, indent, counter[countpos-1].text);
+           indent += 4;
+           countpos--;
+       }
+
        atag = atag->next;
     }
 
@@ -650,7 +755,7 @@ void action_fixjump(ActionMarker m1, ActionMarker m2)
 
     if (a1->op == ACTION_IF || a1->op == ACTION_JUMP) 
     {
-       *(U16*)(a1->data) = len;
+       *(U16*)(a1->data) = SWAP16(len);
     }
     else if(a1->op == ACTION_WAITFORFRAME)
     {
@@ -740,17 +845,17 @@ void action_Call() {swf_AddActionTAG(ACTION_CALL, 0, 0);}
 void action_End() {swf_AddActionTAG(ACTION_END, 0, 0);}
 void action_GotoFrame(U16 frame) 
 {
-    *(U16*)currentatag->tmp = frame;
+    *(U16*)currentatag->tmp = SWAP16(frame);
     swf_AddActionTAG(ACTION_GOTOFRAME, (U8*)currentatag->tmp, 2);
 }
 void action_Jump(U16 branch) 
 {
-    *(U16*)currentatag->tmp = branch;
+    *(U16*)currentatag->tmp = SWAP16(branch);
     swf_AddActionTAG(ACTION_JUMP, (U8*)currentatag->tmp, 2);
 }
 void action_If(U16 branch) 
 {
-    *(U16*)currentatag->tmp = branch;
+    *(U16*)currentatag->tmp = SWAP16(branch);
     swf_AddActionTAG(ACTION_IF, (U8*)currentatag->tmp, 2);
 }
 void action_StoreRegister(U8 reg) 
@@ -775,7 +880,7 @@ void action_WaitForFrame2(U8 skip)
 }
 void action_WaitForFrame(U16 frame, U8 skip) 
 {
-    *(U16*)currentatag->tmp = frame;
+    *(U16*)currentatag->tmp = SWAP16(frame);
     *(U8*)&currentatag->tmp[2] = skip;
     swf_AddActionTAG(ACTION_WAITFORFRAME, (U8*)currentatag->tmp, 3);
 }
@@ -818,21 +923,39 @@ void action_PushString(char*str)
 void action_PushFloat(float f)
 {
     char*ptr = (char*)malloc(5);
+    U32 fd = *(U32*)&f;
     ptr[0] = 1; //float
-    *(float*)&ptr[1]  = f;
+    ptr[1]  = fd;
+    ptr[2]  = fd>>8;
+    ptr[3]  = fd>>16;
+    ptr[4]  = fd>>24;
     swf_AddActionTAG(ACTION_PUSH, (U8*)ptr, 5);
 }
 void action_PushDouble(double d) 
 {
     char*ptr = (char*)malloc(9);
+    U8*dd = (U8*)&d;
     ptr[0] = 6; //double
-    *(double*)&ptr[1]  = d;
+#ifdef WORDS_BIGENDIAN
+    ptr[1] = dd[7];ptr[2] = dd[6];
+    ptr[3] = dd[5];ptr[4] = dd[4];
+    ptr[5] = dd[3];ptr[6] = dd[2];
+    ptr[7] = dd[1];ptr[8] = dd[0];
+#else
+    ptr[1] = dd[0];ptr[2] = dd[1];
+    ptr[3] = dd[2];ptr[4] = dd[3];
+    ptr[5] = dd[4];ptr[6] = dd[5];
+    ptr[7] = dd[6];ptr[8] = dd[7];
+#endif
     swf_AddActionTAG(ACTION_PUSH, (U8*)ptr, 9);
 }
 void action_PushInt(int i)
 {
     *(U8*)currentatag->tmp = 7; //int
-    *(U32*)&currentatag->tmp[1] = i;
+    currentatag->tmp[1] = i;
+    currentatag->tmp[2] = i>>8;
+    currentatag->tmp[3] = i>>16;
+    currentatag->tmp[4] = i>>24;
     swf_AddActionTAG(ACTION_PUSH, (U8*)currentatag->tmp, 5);
 }
 void action_GotoLabel(char* label)