file copied from ming 0.3alpha2
[swftools.git] / lib / action / listaction.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include "action.h"
5 #include "compile.h"
6
7
8 #define print(x)        {fputs(x,stdout);}
9
10 int gIndent;
11 #define INDENT_LEVEL 2
12
13 void println(const char *s, ...)
14 {
15   va_list ap;
16   int n = gIndent*INDENT_LEVEL;
17
18   while(n-- > 0)
19     putchar(' ');
20
21   va_start(ap, s);
22   vprintf(s, ap);
23   va_end(ap);
24
25   putchar('\n');
26 }
27
28 int fileOffset = 0;
29
30 int readUInt8(Buffer f)
31 {
32   return f->buffer[fileOffset++];
33 }
34
35 int readSInt8(Buffer f)
36 {
37   return (signed char)readUInt8(f);
38 }
39
40 int readSInt16(Buffer f)
41 {
42   return readUInt8(f) + readSInt8(f)*256;
43 }
44
45 int readUInt16(Buffer f)
46 {
47   return readUInt8(f) + (readUInt8(f)<<8);
48 }
49
50 long readSInt32(Buffer f)
51 {
52   return (long)readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24);
53 }
54
55 unsigned long readUInt32(Buffer f)
56 {
57   return (unsigned long)(readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24));
58 }
59
60 double readDouble(Buffer f)
61 {
62   double d;
63   unsigned char *p = (unsigned char *)&d;
64
65   p[4] = readUInt8(f);
66   p[5] = readUInt8(f);
67   p[6] = readUInt8(f);
68   p[7] = readUInt8(f);
69   p[0] = readUInt8(f);
70   p[1] = readUInt8(f);
71   p[2] = readUInt8(f);
72   p[3] = readUInt8(f);
73
74   return d;
75 }
76
77 char *readString(Buffer f)
78 {
79   int len = 0, buflen = 256;
80   char c, *buf, *p;
81
82   buf = (char *)malloc(sizeof(char)*256);
83   p = buf;
84
85   while((c=(char)readUInt8(f)) != '\0')
86   {
87     if(len==buflen)
88     {
89       buf = (char *)realloc(buf, sizeof(char)*(buflen+256));
90       buflen += 256;
91       p = buf+len;
92     }
93
94     *(p++) = c;
95     ++len;
96   }
97
98   *p = 0;
99
100   return buf;
101 }
102
103 void dumpBytes(Buffer f, int length)
104 {
105   int j=0, i, k;
106   unsigned char buf[16];
107
108   if(length==0)
109     return;
110
111   for(;;)
112   {
113     for(i=0; i<16; ++i)
114     {
115       printf("%02x ", buf[i] = readUInt8(f));
116       ++j;
117
118       if(j==length)
119                 break;
120     }
121
122     if(j==length)
123     {
124       for(k=i+1; k<16; ++k)
125         print("   ");
126
127       ++i;
128     }
129
130     print("   ");
131
132     for(k=0; k<i; ++k)
133       if((buf[k] > 31) && (buf[k] < 128))
134         putchar(buf[k]);
135       else
136         putchar('.');
137
138     putchar('\n');
139
140     if(j==length)
141       break;
142   }
143   putchar('\n');
144   putchar('\n');
145 }
146
147 void printDoAction(Buffer f, int length);
148
149 char *dictionary[256];
150
151 int printActionRecord(Buffer f)
152 {
153   int length = 0, type;
154
155   printf("(%i)\t", fileOffset);
156
157   type = readUInt8(f);
158
159   if((type&0x80) == 0x80)
160     length = readUInt16(f);
161
162   switch(type)
163   {
164     case SWFACTION_ADD:
165       println("Add");
166       break;
167     case SWFACTION_SUBTRACT:
168       println("Subtract");
169       break;
170     case SWFACTION_MULTIPLY:
171       println("Multiply");
172       break;
173     case SWFACTION_DIVIDE:
174       println("Divide");
175       break;
176     case SWFACTION_EQUAL:
177       println("Equals");
178       break;
179     case SWFACTION_LESSTHAN:
180       println("Less Than");
181       break;
182     case SWFACTION_LOGICALAND:
183       println("And");
184       break;
185     case SWFACTION_LOGICALOR:
186       println("Or");
187       break;
188     case SWFACTION_LOGICALNOT:
189       println("Not");
190       break;
191     case SWFACTION_STRINGEQ:
192       println("String eq");
193       break;
194     case SWFACTION_STRINGLENGTH:
195       println("String Length");
196       break;
197     case SWFACTION_SUBSTRING:
198       println("Substring");
199       break;
200     case SWFACTION_POP:
201       println("Pop");
202       break;
203     case SWFACTION_INT:
204       println("Int");
205       break;
206     case SWFACTION_GETVARIABLE:
207       println("Get Variable");
208       break;
209     case SWFACTION_SETVARIABLE:
210       println("Set Variable");
211       break;
212     case SWFACTION_SETTARGETEXPRESSION:
213       println("Set Target Expression");
214       break;
215     case SWFACTION_STRINGCONCAT:
216       println("String Concat");
217       break;
218     case SWFACTION_GETPROPERTY:
219       println("Get Property");
220       break;
221     case SWFACTION_SETPROPERTY:
222       println("Set Property");
223       break;
224     case SWFACTION_DUPLICATECLIP:
225       println("Duplicate Clip");
226       break;
227     case SWFACTION_REMOVECLIP:
228       println("Remove Clip");
229       break;
230     case SWFACTION_TRACE:
231       println("Trace");
232       break;
233     case SWFACTION_STARTDRAGMOVIE:
234       println("Start Drag Movie");
235       break;
236     case SWFACTION_STOPDRAGMOVIE:
237       println("Stop Drag Movie");
238       break;
239     case SWFACTION_STRINGCOMPARE:
240       println("String Compare");
241       break;
242     case SWFACTION_RANDOM:
243       println("Random");
244       break;
245     case SWFACTION_MBLENGTH:
246       println("String MB Length");
247       break;
248     case SWFACTION_ORD:
249       println("Ord");
250       break;
251     case SWFACTION_CHR:
252       println("Chr");
253       break;
254     case SWFACTION_GETTIMER:
255       println("Get Timer");
256       break;
257     case SWFACTION_MBSUBSTRING:
258       println("MB Substring");
259       break;
260     case SWFACTION_MBORD:
261       println("MB Ord");
262       break;
263     case SWFACTION_MBCHR:
264       println("MB Chr");
265       break;
266     case SWFACTION_NEXTFRAME:
267       println("Next Frame");
268       break;
269     case SWFACTION_PREVFRAME:
270       println("Previous Frame");
271       break;
272     case SWFACTION_PLAY:
273       println("Play");
274       break;
275     case SWFACTION_STOP:
276       println("Stop");
277       break;
278     case SWFACTION_TOGGLEQUALITY:
279       println("Toggle Quality");
280       break;
281     case SWFACTION_STOPSOUNDS:
282       println("Stop Sounds");
283       break;
284
285     /* ops with args */
286     case SWFACTION_PUSHDATA:
287     {
288       int type;
289       int start = fileOffset;
290
291       while(fileOffset < start+length)
292       {
293         switch(type = readUInt8(f))
294         {
295           case 0: /* string */
296             println("Push String: %s", readString(f));
297             break;
298           case 1: /* property */
299             readUInt16(f); /* always 0? */
300             println("Push Property: %04x", readUInt16(f));
301             break;
302           case 2: /* null */
303             println("Push NULL");
304             break;
305           case 3: /* ??? */
306             println("Push type 3- ??");
307             break;
308           case 4: 
309             println("Push register %i", readUInt8(f));
310             break;
311           case 5:
312             if(readUInt8(f))
313               println("Push true");
314             else
315               println("Push false");
316             break;
317           case 6: /* double */
318             println("Push %f", readDouble(f));
319             break;
320           case 7: /* int */
321             println("Push %i", readSInt32(f));
322             break;
323           case 8: /* dictionary */
324             println("Push \"%s\"", dictionary[readUInt8(f)]);
325             break;
326           case 9: /* dictionary */
327             println("Push \"%s\"", dictionary[readSInt16(f)]);
328           default:
329             println("unknown push type: %i", type);
330         }
331       }
332       break;
333     }
334     case SWFACTION_GOTOFRAME:
335       println("Goto Frame %i", readUInt16(f));
336       break;
337     case SWFACTION_GETURL:
338     {
339       char *url = readString(f);
340       println("Get URL \"%s\" target \"%s\"", url, readString(f));
341       break;
342     }
343     case SWFACTION_WAITFORFRAMEEXPRESSION:
344       println("Wait For Frame Expression, skip %i\n", readUInt8(f));
345       break;
346     case SWFACTION_BRANCHALWAYS:
347       println("Branch Always %i", readSInt16(f));
348       break;
349     case SWFACTION_GETURL2:
350       {
351         int flags = readUInt8(f);
352
353         const char *op = (flags & 0x80) ? "Get URL2 (loadvariables)" : "Get URL2";
354         const char *tgt = (flags & 0x40) ? " into target" : "";
355
356         switch(flags & 0x03)
357         {
358           case 0: println("%s%s (Don't send)", op, tgt); break;
359           case 1: println("%s%s (GET)", op, tgt); break;
360           case 2: println("%s%s (POST)", op, tgt); break;
361         }
362       }
363       break;
364     case SWFACTION_BRANCHIFTRUE:
365       println("Branch If True %i", readSInt16(f));
366       break;
367     case SWFACTION_CALLFRAME:
368       println("Call Frame");
369       dumpBytes(f, length);
370       break;
371     case SWFACTION_GOTOEXPRESSION:
372       print("Goto Expression");
373       if(readUInt8(f) == 1)
374         printf(" and Play\n");
375       else
376         printf(" and Stop\n");
377       break;
378     case SWFACTION_WAITFORFRAME:
379     {
380       int frame = readUInt16(f);
381       println("Wait for frame %i else skip %i", frame, readUInt8(f));
382       break;
383     }
384     case SWFACTION_SETTARGET:
385       println("Set Target %s", readString(f));
386       break;
387     case SWFACTION_GOTOLABEL:
388       println("Goto Label %s", readString(f));
389       break;
390     case SWFACTION_END:
391       return 0;
392       break;
393
394     /* f5 ops */
395     case SWFACTION_DELETE:
396       println("Delete");
397       break;
398     case SWFACTION_VAR:
399       println("Var");
400       break;
401     case SWFACTION_VAREQUALS:
402       println("Var assign");
403       break;
404     case SWFACTION_INITARRAY:
405       println("Init array");
406       break;
407     case SWFACTION_INITOBJECT:
408       println("Init object");
409       break;
410     case SWFACTION_CALLFUNCTION:
411       println("call function");
412       break;
413     case SWFACTION_RETURN:
414       println("return");
415       break;
416     case SWFACTION_MODULO:
417       println("modulo");
418       break;
419     case SWFACTION_NEW:
420       println("new");
421       break;
422     case SWFACTION_TYPEOF:
423       println("typeof");
424       break;
425     case SWFACTION_NEWADD:
426       println("new add");
427       break;
428     case SWFACTION_NEWLESSTHAN:
429       println("new less than");
430       break;
431     case SWFACTION_NEWEQUALS:
432       println("new equals");
433       break;
434     case SWFACTION_DUP:
435       println("dup");
436       break;
437     case SWFACTION_SWAP:
438       println("swap");
439       break;
440     case SWFACTION_GETMEMBER:
441       println("get member");
442       break;
443     case SWFACTION_SETMEMBER:
444       println("set member");
445       break;
446     case SWFACTION_INCREMENT:
447       println("increment");
448       break;
449     case SWFACTION_CALLMETHOD:
450       println("call method");
451       break;
452     case SWFACTION_BITWISEAND:
453       println("bitwise and");
454       break;
455     case SWFACTION_BITWISEOR:
456       println("bitwise or");
457       break;
458     case SWFACTION_BITWISEXOR:
459       println("bitwise xor");
460       break;
461     case SWFACTION_SHIFTLEFT:
462       println("shift left");
463       break;
464     case SWFACTION_SHIFTRIGHT:
465       println("shift right");
466       break;
467     case SWFACTION_SHIFTRIGHT2:
468       println("shift right 2");
469       break;
470
471     case SWFACTION_CONSTANTPOOL:
472     {
473       int i, n = readUInt16(f);
474       print("declare dictionary:");
475
476       for(i=0; i<n; ++i)
477         printf(" %s%c", dictionary[i]=readString(f), (i<n-1)?',':'\n');
478
479       break;
480     }
481     case SWFACTION_WITH:
482     {
483       println("with");
484
485       ++gIndent;
486       printDoAction(f, readUInt16(f));
487       --gIndent;
488
489       break;
490     }
491     case SWFACTION_DEFINEFUNCTION:
492     {
493       char *name = readString(f);
494       int n = readUInt16(f);
495
496       print("function ");
497       print(name);
498       putchar('(');
499
500       if(n > 0)
501       {
502         printf("%s", readString(f));
503         --n;
504       }
505
506       for(; n>0; --n)
507         printf(", %s", readString(f));
508
509       putchar(')');
510       putchar('\n');
511
512       ++gIndent;
513       printDoAction(f, readUInt16(f));
514       --gIndent;
515
516       break;
517     }
518
519     case SWFACTION_ENUMERATE:
520       println("enumerate");
521       break;
522
523     case SWFACTION_SETREGISTER:
524       println("set register %i", readUInt8(f));
525       break;
526
527 /* f6 actions */
528     case SWFACTION_INSTANCEOF:
529       println("instanceof");
530       break;
531     case SWFACTION_STRICTEQ:
532       println("strict_equals");
533       break;
534     case SWFACTION_ENUM2:
535       println("enum2");
536       break;
537
538     default:
539       println("Unknown Action: %02X", type);
540       dumpBytes(f, length);
541   }
542
543   return 1;
544 }
545
546 void printDoAction(Buffer f, int length)
547 {
548   int end;
549
550   if(!f)
551     return;
552
553   end = fileOffset + length;
554
555   while(fileOffset < end && printActionRecord(f))
556     ;
557 }