1 
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <math.h>
6 
7 #include "blocks/blocktypes.h"
8 #include "action.h"
9 #include "read.h"
10 #include "decompile.h"
11 
12 
13 #ifdef NODECOMPILE
14 #define decompileAction(f,l,n) printDoAction((f),(l))
15 #else
16 #define decompileAction(f,l,n) printDecompiledAction((f),(l),(n))
17 #endif
18 
19 /*#define decompileAction(f,l) dumpBytes((f),(l))*/
20 
21 #define puts(s) fputs((s),stdout)
22 
23 /* char *blockName(SWFBlocktype type); */
24 void skipBytes(FILE *f, int length);
25 extern const char *blockName(int header);
26 
27 #define INDENT_LEVEL 3
28 
print(const char * s,...)29 void print(const char *s, ...)
30 {
31   va_list ap;
32   int n = gIndent*INDENT_LEVEL;
33 
34   while(n-- > 0)
35     putchar(' ');
36 
37   va_start(ap, s);
38   vprintf(s, ap);
39   va_end(ap);
40 }
println(const char * s,...)41 void println(const char *s, ...)
42 {
43   va_list ap;
44   int n = gIndent*INDENT_LEVEL;
45 
46   while(n-- > 0)
47     putchar(' ');
48 
49   va_start(ap, s);
50   vprintf(s, ap);
51   va_end(ap);
52 
53   putchar('\n');
54 }
55 
printMatrix(FILE * f)56 void printMatrix(FILE *f)
57 {
58   int nBits;
59   float num;
60 
61   byteAlign();
62 
63   if(readBits(f, 1)) /* has scale */
64   {
65     nBits = readBits(f, 5);
66     num = (float)readSBits(f, nBits)/0x10000;
67     println("xScale: %f", num);
68     num = (float)readSBits(f, nBits)/0x10000;
69     println("yScale: %f", num);
70   }
71   if(readBits(f, 1)) /* has rotate */
72   {
73     nBits = readBits(f, 5);
74     num = (float)readSBits(f, nBits)/0x10000;
75     println("rotate0: %f", num);
76     num = (float)readSBits(f, nBits)/0x10000;
77     println("rotate1: %f", num);
78   }
79 
80   nBits = readBits(f, 5);
81   println("x: %i", readSBits(f, nBits));
82   println("y: %i", readSBits(f, nBits));
83 }
84 
printCXForm(FILE * f,boolean hasAlpha)85 void printCXForm(FILE *f, boolean hasAlpha)
86 {
87   int hasAdd, hasMult, nBits;
88 
89   byteAlign();
90 
91   hasAdd = readBits(f, 1);
92   hasMult = readBits(f, 1);
93   nBits = readBits(f, 4);
94 
95   if(hasMult)
96   {
97     puts("x(");
98     printf("%i,", readSBits(f, nBits));
99     printf("%i,", readSBits(f, nBits));
100     printf("%i)", readSBits(f, nBits));
101     if(hasAlpha)
102       printf("%i,", readSBits(f, nBits));
103   }
104   else puts("x()");
105 
106   if(hasAdd)
107   {
108     puts("+(");
109     printf("%i,", readSBits(f, nBits));
110     printf("%i,", readSBits(f, nBits));
111     printf("%i)", readSBits(f, nBits));
112     if(hasAlpha)
113       printf("%i,", readSBits(f, nBits));
114   }
115   else puts("+()");
116 
117   putchar('\n');
118 }
119 
120 
printRect(FILE * f)121 void printRect(FILE *f)
122 {
123   int nBits, xMin, xMax, yMin, yMax;
124 
125   byteAlign();
126 
127   nBits = readBits(f, 5);
128   xMin = readSBits(f, nBits);
129   xMax = readSBits(f, nBits);
130   yMin = readSBits(f, nBits);
131   yMax = readSBits(f, nBits);
132 
133   printf("(%i,%i)x(%i,%i)", xMin, xMax, yMin, yMax);
134 }
135 
printRGB(FILE * f)136 void printRGB(FILE *f)
137 {
138   int r = readUInt8(f);
139   int g = readUInt8(f);
140   int b = readUInt8(f);
141 
142   printf("(%02x,%02x,%02x)", r, g, b);
143 }
144 
printRGBA(FILE * f)145 void printRGBA(FILE *f)
146 {
147   int r = readUInt8(f);
148   int g = readUInt8(f);
149   int b = readUInt8(f);
150   int a = readUInt8(f);
151 
152   printf("(%02x,%02x,%02x,%02x)", r, g, b, a);
153 }
154 
printGradient(FILE * f,int shapeType)155 void printGradient(FILE *f, int shapeType)
156 {
157   int i;
158   int numGrads = readUInt8(f);
159 
160   for(i=0; i<numGrads; ++i)
161   {
162     print("Grad[%i]: ratio=%i, ", i, readUInt8(f));
163     puts("color=");
164 
165     if(shapeType==SWF_DEFINESHAPE3)
166       printRGBA(f);
167     else
168       printRGB(f);
169 
170     putchar('\n');
171   }
172 }
173 
printMorphGradient(FILE * f)174 void printMorphGradient(FILE *f)
175 {
176   int i;
177   int numGrads = readUInt8(f);
178 
179   for(i=0; i<numGrads; ++i)
180   {
181     print("Shape 1, Grad[%i]: ratio=%i, ", i, readUInt8(f));
182     puts("color=");
183     printRGBA(f);
184     putchar('\n');
185 
186     print("Shape 2, Grad[%i]: ratio=%i, ", i, readUInt8(f));
187     puts("color=");
188     printRGBA(f);
189     putchar('\n');
190   }
191 }
192 
printLineStyleArray(FILE * f,int shapeType)193 void printLineStyleArray(FILE *f, int shapeType)
194 {
195   int count, i;
196 
197   count = readUInt8(f);
198 
199   if(count==255)
200     count = readUInt16(f);
201 
202   for(i=0; i<count; ++i)
203   {
204     print("LineStyle %i: ", i+1);
205     printf("width=%i ", readUInt16(f));
206 
207     if(shapeType==SWF_DEFINEMORPHSHAPE)
208       printf("width2=%i ", readUInt16(f));
209 
210     puts("color=");
211 
212     if(shapeType==SWF_DEFINESHAPE3 || shapeType==SWF_DEFINEMORPHSHAPE)
213       printRGBA(f);
214     else
215       printRGB(f);
216 
217     if(shapeType==SWF_DEFINEMORPHSHAPE)
218     {
219       puts("color2=");
220       printRGBA(f);
221     }
222 
223     putchar('\n');
224   }
225 }
226 
printFillStyle(FILE * f,int shapeType)227 void printFillStyle(FILE *f, int shapeType)
228 {
229   int type;
230 
231   type = readUInt8(f);
232 
233   if(type==0) /* solid fill */
234   {
235     print("color=");
236 
237     if(shapeType==SWF_DEFINESHAPE3 || shapeType==SWF_DEFINEMORPHSHAPE)
238       printRGBA(f);
239     else
240       printRGB(f);
241 
242     if(shapeType==SWF_DEFINEMORPHSHAPE)
243     {
244       print("color2=");
245       printRGBA(f);
246     }
247 
248     putchar('\n');
249   }
250   else if(type==0x10) /* linear */
251   {
252     println("Matrix:");
253     ++gIndent;
254     printMatrix(f);
255     --gIndent;
256 
257     if(shapeType==SWF_DEFINEMORPHSHAPE)
258     {
259       println("Matrix2:");
260       ++gIndent;
261       printMatrix(f);
262       --gIndent;
263     }
264 
265     println("Gradient (linear):");
266     ++gIndent;
267     if(shapeType==SWF_DEFINEMORPHSHAPE)
268       printMorphGradient(f);
269     else
270       printGradient(f, shapeType);
271     --gIndent;
272   }
273   else if(type==0x12) /* radial gradient */
274   {
275     println("Matrix:");
276     ++gIndent;
277     printMatrix(f);
278     --gIndent;
279 
280     if(shapeType==SWF_DEFINEMORPHSHAPE)
281     {
282       println("Matrix2:");
283       ++gIndent;
284       printMatrix(f);
285       --gIndent;
286     }
287 
288     println("Gradient (radial):");
289     ++gIndent;
290     if(shapeType==SWF_DEFINEMORPHSHAPE)
291       printMorphGradient(f);
292     else
293       printGradient(f, shapeType);
294     --gIndent;
295   }
296   else if(type==0x40) /* tiled bitmap */
297   {
298     println("Bitmap id: %i (tiled)", readUInt16(f));
299     println("Bitmap matrix:");
300     ++gIndent;
301     printMatrix(f);
302     --gIndent;
303 
304     if(shapeType==SWF_DEFINEMORPHSHAPE)
305     {
306       println("Bitmap matrix:");
307       ++gIndent;
308       printMatrix(f);
309       --gIndent;
310     }
311   }
312   else if(type==0x41) /* clipped bitmap */
313   {
314     println("Bitmap id: %i (clipped)", readUInt16(f));
315     println("Bitmap matrix:");
316     ++gIndent;
317     printMatrix(f);
318     --gIndent;
319 
320     if(shapeType==SWF_DEFINEMORPHSHAPE)
321     {
322       println("Bitmap matrix:");
323       ++gIndent;
324       printMatrix(f);
325       --gIndent;
326     }
327   }
328   else
329     println("Unknown fill type: %i", type);
330 }
331 
printFillStyleArray(FILE * f,int shapeType)332 void printFillStyleArray(FILE *f, int shapeType)
333 {
334   int count, i;
335 
336   count = readUInt8(f);
337 
338   if(count==255)
339     count = readUInt16(f);
340 
341   for(i=0; i<count; ++i)
342   {
343     println("FillStyle %i:", i+1);
344     ++gIndent;
345     printFillStyle(f, shapeType);
346     --gIndent;
347     putchar('\n');
348   }
349 }
350 
printShapeRec(FILE * f,int * lineBits,int * fillBits,int shapeType)351 int printShapeRec(FILE *f, int *lineBits, int *fillBits, int shapeType)
352 {
353   int type;
354 
355   //  printf("(%i:%i)",fileOffset,bufbits);
356 
357   type = readBits(f, 1);
358 
359   if(type==0) /* state change */
360   {
361     int newStyles = readBits(f, 1);
362     int lineStyle = readBits(f, 1);
363     int fillStyle1 = readBits(f, 1);
364     int fillStyle0 = readBits(f, 1);
365     int moveTo = readBits(f, 1);
366 
367     if(newStyles==0 && lineStyle==0 && fillStyle1==0 && fillStyle0==0 && moveTo==0)
368     {
369       println("EndShape");
370       return 0;
371     }
372 
373     if(moveTo==1)
374     {
375       int moveBits = readBits(f, 5);
376       int x = readSBits(f, moveBits);
377       int y = readSBits(f, moveBits);
378 
379       println("MoveTo (%i) - (%i,%i)", moveBits, x, y);
380     }
381 
382     if(fillStyle0==1)
383       println("FillStyle0: %i", readBits(f, *fillBits));
384 
385     if(fillStyle1==1)
386       println("FillStyle1: %i", readBits(f, *fillBits));
387 
388     if(lineStyle==1)
389       println("LineStyle1: %i", readBits(f, *lineBits));
390 
391     if(newStyles==1)
392     {
393       println("NewStyles:");
394       printFillStyleArray(f, shapeType);
395       printLineStyleArray(f, shapeType);
396       *fillBits = readBits(f, 4);
397       *lineBits = readBits(f, 4);
398     }
399   }
400   else /* it's an edge record */
401   {
402     int straight = readBits(f, 1);
403     int numBits = readBits(f, 4)+2;
404 
405     if(straight==1)
406     {
407       if(readBits(f, 1)) /* general line */
408       {
409 	int x = readSBits(f, numBits);
410 	int y = readSBits(f, numBits);
411 
412 	println("StraightEdge: (%i) - (%i,%i)", numBits, x, y);
413       }
414       else
415 	if(readBits(f, 1)) /* vert = 1 */
416 	  println("StraightEdge: (%i) - (0,%i)", numBits, readSBits(f, numBits));
417 	else
418 	  println("StraightEdge: (%i) - (%i,0)", numBits, readSBits(f, numBits));
419     }
420     else
421     {
422       int controlX = readSBits(f, numBits);
423       int controlY = readSBits(f, numBits);
424       int anchorX = readSBits(f, numBits);
425       int anchorY = readSBits(f, numBits);
426       println("CurvedEdge: (%i) - (%i,%i)->(%i,%i)", numBits, controlX, controlY, anchorX, anchorY);
427     }
428   }
429 
430   return 1;
431 }
432 
printShape(FILE * f,int length,SWFBlocktype type)433 void printShape(FILE *f, int length, SWFBlocktype type)
434 {
435   int start = fileOffset;
436   int fillBits, lineBits;
437 
438   println("ShapeID: %i", readUInt16(f));
439 
440   print("Bounds: ");
441   printRect(f);
442 
443   putchar('\n');
444   putchar('\n');
445 
446   printFillStyleArray(f, type);
447   printLineStyleArray(f, type);
448 
449   putchar('\n');
450 
451   byteAlign();
452 
453   fillBits = readBits(f,4);
454   lineBits = readBits(f,4);
455 
456   while(fileOffset < length+start &&
457 	printShapeRec(f, &lineBits, &fillBits, type)) ;
458 
459   /* go for end tag..
460   if(fileOffset == length+start && bufbits > 5)
461     printShapeRec(f, &lineBits, &fillBits, type);
462   */
463 
464   putchar('\n');
465 }
466 
printMorphShape(FILE * f,int length)467 void printMorphShape(FILE *f, int length)
468 {
469   int offset, start = fileOffset;
470   int fillBits, lineBits, here;
471 
472   println("ShapeID: %i", readUInt16(f));
473 
474   print("Bounds1: ");
475   printRect(f);
476   putchar('\n');
477   print("Bounds2: ");
478   printRect(f);
479   putchar('\n');
480 
481   offset = readUInt32(f);
482   println("(%i)\toffset = %i", fileOffset, offset);
483 
484   here = fileOffset;
485 
486   printFillStyleArray(f, SWF_DEFINEMORPHSHAPE);
487   printLineStyleArray(f, SWF_DEFINEMORPHSHAPE);
488 
489   fillBits = readBits(f, 4);
490   lineBits = readBits(f, 4);
491 
492   putchar('\n');
493   println("Shape1:");
494   while(fileOffset < here+offset)
495     printShapeRec(f, &lineBits, &fillBits, SWF_DEFINESHAPE3);
496 
497   byteAlign();
498 
499   /* ??? */
500   fillBits = readBits(f, 4);
501   lineBits = readBits(f, 4);
502 
503   putchar('\n');
504   println("Shape2:");
505   while(fileOffset < start+length)
506     printShapeRec(f, &lineBits, &fillBits, SWF_DEFINESHAPE3);
507 }
508 
509 /* JPEG stream markers: */
510 #define JPEG_MARKER 0xFF
511 
512 /* Start of Image, End of Image */
513 #define JPEG_SOI  0xD8
514 #define JPEG_EOI  0xD9
515 
516 #define JPEG_JFIF 0xE0
517 
518 /* encoding markers, quantization tables and Huffman tables */
519 #define JPEG_QUANT 0xDB
520 #define JPEG_HUFF  0xC4
521 
522 /* image markers, start of frame and start of scan */
523 #define JPEG_SOF0 0xC0
524 #define JPEG_SOF1 0xC1
525 #define JPEG_SOF2 0xC2
526 #define JPEG_SOS  0xDA
527 
printJpegStream(FILE * f,int length)528 void printJpegStream(FILE *f, int length)
529 {
530   int end = fileOffset+length;
531   int c, l;
532 
533   while(fileOffset < end)
534   {
535     if(readUInt8(f) != JPEG_MARKER)
536     {
537       println("Jpeg marker not found!");
538       break;
539     }
540 
541     switch(c=readUInt8(f))
542     {
543       case JPEG_SOI:   println("SOI"); break;
544       case JPEG_EOI:   println("EOI"); break;
545       case JPEG_JFIF:  println("JFIF"); break;
546       case JPEG_QUANT: println("Quantization table"); break;
547       case JPEG_HUFF:  println("Huffman table"); break;
548       case JPEG_SOF0:  println("Start of frame 0"); break;
549       case JPEG_SOF1:  println("Start of frame 1"); break;
550       case JPEG_SOF2:  println("Start of frame 2"); break;
551       case JPEG_SOS:   println("Start of scan"); break;
552       default:         println("Unknown JPEG block: %02x", c);
553     }
554 
555     if(c==JPEG_SOS)
556       break;
557 
558     if(c != JPEG_SOI && c != JPEG_EOI)
559     {
560       l = (readUInt8(f)<<8) + readUInt8(f);
561       skipBytes(f, l-2);
562     }
563   }
564 
565   skipBytes(f, end-fileOffset);
566 }
567 
printDefineBitsJpeg(FILE * f,int length)568 void printDefineBitsJpeg(FILE *f, int length)
569 {
570   println("Bitmap id: %i", readUInt16(f));
571   printJpegStream(f, length-2);
572 }
573 
printDefineBitsJpeg3(FILE * f,int length)574 void printDefineBitsJpeg3(FILE *f, int length)
575 {
576   int offset;
577 
578   println("Bitmap id: %i", readUInt16(f));
579 
580   offset = readUInt32(f);
581 
582   printJpegStream(f, offset);
583 
584   putchar('\n');
585   println("zlib-compressed alpha data:");
586 
587   skipBytes(f, length-offset-6);
588 }
589 
printDefineBitsLossless(FILE * f,int length)590 void printDefineBitsLossless(FILE *f, int length)
591 {
592 	int format, start = fileOffset;
593 	int width, height, tablesize, bpp;
594 
595 	println("Bitmap id: %i", readUInt16(f));
596 
597 	format = readUInt8(f);
598 	width = readUInt16(f);
599 	height = readUInt16(f);
600 
601 	switch(format)
602 	{
603 		case 3:
604 			tablesize = readUInt8(f)+1;
605 			bpp = 8;
606 			break;
607 		case 4:
608 			tablesize = readUInt16(f)+1;
609 			bpp = 16;
610 			break;
611 		case 5:
612 			tablesize = readUInt32(f)+1;
613 			bpp = 32;
614 			break;
615 		default:
616 			error("unknown bit format: %i", format);
617 			return;
618 	}
619 
620 	println("Format: %d bpp", bpp);
621 	println("Width: %i", width);
622 	println("Height: %i", height);
623 	println("Number of palette entries: %i", tablesize);
624 
625 #if 0
626 	println("zlib-compressed image data:");
627 	{
628 		unsigned char *data, *buffer;
629 		long size = width*height;
630 		long bufsize = start+length-fileOffset;
631 		int i;
632 		//int res;
633 
634 		buffer = malloc(bufsize);
635 
636 		for(i=0; i<bufsize; ++i)
637 			buffer[i] = readUInt8(f);
638 
639 		if(format == 3) size += tablesize*4;
640 		else size *= 4;
641 
642 		data = malloc(size);
643 
644 		/*
645 		if((res = uncompress(data, &size, buffer, bufsize)) != Z_OK)
646 			error("Couldn't uncompress bits! (err: %i)\n", res);
647 
648 		dumpBuffer(data, size);
649 		*/
650 	}
651 #endif
652 
653 	skipBytes(f, start+length-fileOffset);
654 	//  dumpBytes(f, start+length-fileOffset);
655 }
656 
657 void printDoAction(FILE *f, int length);
658 
659 static char *dictionary[65536];
660 
printActionRecord(FILE * f)661 int printActionRecord(FILE *f)
662 {
663   int length = 0, type = readUInt8(f);
664 
665   if((type&0x80) == 0x80)
666     length = readUInt16(f);
667 
668   switch(type)
669   {
670     case SWFACTION_ADD:
671       println("Add");
672       break;
673     case SWFACTION_SUBTRACT:
674       println("Subtract");
675       break;
676     case SWFACTION_MULTIPLY:
677       println("Multiply");
678       break;
679     case SWFACTION_DIVIDE:
680       println("Divide");
681       break;
682     case SWFACTION_EQUAL:
683       println("Equals");
684       break;
685     case SWFACTION_STRICTEQ:
686       println("Strictly Equals");
687       break;
688     case SWFACTION_LESSTHAN:
689       println("Less Than");
690       break;
691     case SWFACTION_LOGICALAND:
692       println("And");
693       break;
694     case SWFACTION_LOGICALOR:
695       println("Or");
696       break;
697     case SWFACTION_LOGICALNOT:
698       println("Not");
699       break;
700     case SWFACTION_STRINGEQ:
701       println("String eq");
702       break;
703     case SWFACTION_STRINGLENGTH:
704       println("String Length");
705       break;
706     case SWFACTION_SUBSTRING:
707       println("Substring");
708       break;
709     case SWFACTION_INT:
710       println("Int");
711       break;
712     case SWFACTION_POP:
713       println("Pop");
714       break;
715     case SWFACTION_SWAP:
716       println("Swap");
717       break;
718     case SWFACTION_INITOBJECT:
719       println("Init Object");
720       break;
721     case SWFACTION_INITARRAY:
722       println("Init Array");
723       break;
724     case SWFACTION_GETVARIABLE:
725       println("Get Variable");
726       break;
727     case SWFACTION_SETVARIABLE:
728       println("Set Variable");
729       break;
730     case SWFACTION_SETTARGETEXPRESSION:
731       println("Set Target Expression");
732       break;
733     case SWFACTION_STRINGCONCAT:
734       println("String Concat");
735       break;
736     case SWFACTION_GETPROPERTY:
737       println("Get Property");
738       break;
739     case SWFACTION_SETPROPERTY:
740       println("Set Property");
741       break;
742     case SWFACTION_DUPLICATECLIP:
743       println("Duplicate Clip");
744       break;
745     case SWFACTION_REMOVECLIP:
746       println("Remove Clip");
747       break;
748     case SWFACTION_TRACE:
749       println("Trace");
750       break;
751     case SWFACTION_STARTDRAGMOVIE:
752       println("Start Drag Movie");
753       break;
754     case SWFACTION_STOPDRAGMOVIE:
755       println("Stop Drag Movie");
756       break;
757     case SWFACTION_STRINGCOMPARE:
758       println("String Compare");
759       break;
760     case SWFACTION_RANDOM:
761       println("Random");
762       break;
763     case SWFACTION_MBLENGTH:
764       println("String MB Length");
765       break;
766     case SWFACTION_ORD:
767       println("Ord");
768       break;
769     case SWFACTION_CHR:
770       println("Chr");
771       break;
772     case SWFACTION_GETTIMER:
773       println("Get Timer");
774       break;
775     case SWFACTION_MBSUBSTRING:
776       println("MB Substring");
777       break;
778     case SWFACTION_MBORD:
779       println("MB Ord");
780       break;
781     case SWFACTION_MBCHR:
782       println("MB Chr");
783       break;
784     case SWFACTION_NEXTFRAME:
785       println("Next Frame");
786       break;
787     case SWFACTION_PREVFRAME:
788       println("Previous Frame");
789       break;
790     case SWFACTION_PLAY:
791       println("Play");
792       break;
793     case SWFACTION_STOP:
794       println("Stop");
795       break;
796     case SWFACTION_TOGGLEQUALITY:
797       println("Toggle Quality");
798       break;
799     case SWFACTION_STOPSOUNDS:
800       println("Stop Sounds");
801       break;
802 
803     /* ops with args */
804     case SWFACTION_PUSHDATA:
805     {
806       int type;
807       int start = fileOffset;
808       int count = 0;
809 
810       print("Push:");
811       while(fileOffset < start+length)
812       {
813 	if ( count++ ) putchar(',');
814 	switch(type = readUInt8(f))
815 	{
816 	  case 0: /* string */
817 	    printf(" string:%s", readString(f));
818 	    break;
819 	  case 1: /* property */
820 	    readUInt16(f); /* always 0? */
821 	    printf(" property:%04x", readUInt16(f));
822 	    break;
823 	  case 2: /* null */
824 	    printf(" NULL");
825 	    break;
826 	  case 3: /* ??? */
827 	    printf(" type_3:");
828 	    break;
829 	  case 4:
830 	    printf(" register:%i", readUInt8(f));
831 	    break;
832 	  case 5:
833 	    if(readUInt8(f))
834 	      printf(" TRUE");
835 	    else
836 	      printf(" FALSE");
837 	    break;
838 	  case 6: /* double */
839 	    printf(" double:%f", readDouble(f));
840 	    break;
841 	  case 7: /* int */
842 	    printf(" int:%i", readSInt32(f));
843 	    break;
844 	  case 8: /* dictionary */
845 	    printf(" dict:\"%s\"", dictionary[readUInt8(f)]);
846 	    break;
847 	  default:
848 	    printf(" unknown_type_%i", type);
849 	}
850       }
851       putchar('\n');
852       break;
853     }
854     case SWFACTION_GOTOFRAME:
855       println("Goto Frame %i", readUInt16(f));
856       break;
857     case SWFACTION_GETURL:
858     {
859       char *url = readString(f);
860       println("Get URL \"%s\" target \"%s\"", url, readString(f));
861       break;
862     }
863     case SWFACTION_WAITFORFRAMEEXPRESSION:
864       println("Wait For Frame Expression, skip %i\n", readUInt8(f));
865       break;
866     case SWFACTION_BRANCHALWAYS:
867       println("Branch Always %i", readSInt16(f));
868       break;
869     case SWFACTION_GETURL2:
870     {
871       int flags = readUInt8(f);
872 
873       switch(flags)
874       {
875         case 0: println("Get URL2 (Don't send)"); break;
876         case 1: println("Get URL2 (GET)"); break;
877         case 2: println("Get URL2 (POST)"); break;
878         default: println("GET URL2 (0x%x)", flags);
879       }
880       break;
881     }
882     case SWFACTION_BRANCHIFTRUE:
883       println("Branch If True %i", readSInt16(f));
884       break;
885     case SWFACTION_CALLFRAME:
886       println("Call Frame");
887       dumpBytes(f, length);
888       break;
889     case SWFACTION_GOTOEXPRESSION:
890       print("Goto Expression");
891       if(readUInt8(f) == 1)
892 	printf(" and Play\n");
893       else
894 	printf(" and Stop\n");
895       break;
896     case SWFACTION_WAITFORFRAME:
897     {
898       int frame = readUInt16(f);
899       println("Wait for frame %i else skip %i", frame, readUInt8(f));
900       break;
901     }
902     case SWFACTION_SETTARGET:
903       println("Set Target %s", readString(f));
904       break;
905     case SWFACTION_GOTOLABEL:
906       println("Goto Label %s", readString(f));
907       break;
908     case SWFACTION_END:
909       return 0;
910       break;
911 
912     /* f5 ops */
913     case SWFACTION_DELETE:
914       println("Delete");
915       break;
916 
917     case SWFACTION_DELETEVAR:
918       println("Delete2");
919       break;
920 
921     case SWFACTION_VAR:
922       println("Var");
923       break;
924     case SWFACTION_VAREQUALS:
925       println("Var Assign");
926       break;
927     case SWFACTION_CALLFUNCTION:
928       println("Call Function");
929       break;
930     case SWFACTION_RETURN:
931       println("Return");
932       break;
933     case SWFACTION_MODULO:
934       println("Modulo");
935       break;
936     case SWFACTION_NEW:
937       println("New");
938       break;
939     case SWFACTION_NEWMETHOD:
940       println("NewMethod");
941       break;
942     case SWFACTION_TYPEOF:
943       println("Typeof");
944       break;
945     case SWFACTION_TARGETPATH:
946       println("TargetPath");
947       break;
948     case SWFACTION_NEWADD:
949       println("New Add");
950       break;
951     case SWFACTION_NEWLESSTHAN:
952       println("New Less Than");
953       break;
954     case SWFACTION_NEWEQUAL:
955       println("New Equals");
956       break;
957     case SWFACTION_DUP:
958       println("Dup");
959       break;
960     case SWFACTION_GETMEMBER:
961       println("Get Member");
962       break;
963     case SWFACTION_SETMEMBER:
964       println("Set Member");
965       break;
966     case SWFACTION_INCREMENT:
967       println("Increment");
968       break;
969     case SWFACTION_DECREMENT:
970       println("Decrement");
971       break;
972     case SWFACTION_CALLMETHOD:
973       println("Call Method");
974       break;
975     case SWFACTION_BITWISEAND:
976       println("Bitwise And");
977       break;
978     case SWFACTION_BITWISEOR:
979       println("Bitwise Or");
980       break;
981     case SWFACTION_BITWISEXOR:
982       println("Bitwise Xor");
983       break;
984     case SWFACTION_SHIFTLEFT:
985       println("Shift Left");
986       break;
987     case SWFACTION_SHIFTRIGHT:
988       println("Shift Right");
989       break;
990     case SWFACTION_SHIFTRIGHT2:
991       println("Shift Right 2");
992       break;
993 
994     case SWFACTION_DECLARENAMES:
995     {
996       int i, n = readUInt16(f);
997       print("Declare Dictionary:");
998 
999       for(i=0; i<n; ++i)
1000 	printf(" %s%c", dictionary[i]=readString(f), (i<n-1)?',':'\n');
1001 
1002       break;
1003     }
1004     case SWFACTION_WITH:
1005     {
1006       println("With");
1007 
1008       ++gIndent;
1009       printDoAction(f, readUInt16(f));
1010       --gIndent;
1011 
1012       break;
1013     }
1014     case SWFACTION_DEFINEFUNCTION:
1015     {
1016       char *name = readString(f);
1017       int n = readUInt16(f);
1018 
1019       print("function %s(", name);
1020 
1021       if(n>0)
1022       {
1023 	printf("%s", readString(f));
1024 	--n;
1025       }
1026 
1027       for(; n>0; --n)
1028 	printf(", %s", readString(f));
1029 
1030       putchar(')');
1031       putchar('\n');
1032 
1033       ++gIndent;
1034       printDoAction(f, readUInt16(f));
1035       --gIndent;
1036 
1037       break;
1038     }
1039 
1040     case SWFACTION_ENUMERATE:
1041       println("Enumerate");
1042       break;
1043 
1044     case SWFACTION_SETREGISTER:
1045       println("Set Register %i", readUInt8(f));
1046       break;
1047 
1048     default:
1049       println("Unknown Action: %02X", type);
1050       dumpBytes(f, length);
1051   }
1052   return 1;
1053 }
1054 
1055 #ifndef NODECOMPILE
printDecompiledAction(FILE * f,int l,int n)1056 void printDecompiledAction(FILE *f, int l, int n)
1057 {
1058 	char *as = decompile5Action(f, l, n);
1059 	puts(as);
1060 }
1061 #endif
1062 
printDoAction(FILE * f,int length)1063 void printDoAction(FILE *f, int length)
1064 {
1065   int start = fileOffset, end = fileOffset+length;
1066 
1067   while(fileOffset<end)
1068   {
1069     printf("%i\t", fileOffset-start);
1070     if(!printActionRecord(f))
1071       break;
1072   }
1073 }
1074 
printButtonRecord(FILE * f,int recordType)1075 int printButtonRecord(FILE *f, int recordType)
1076 {
1077   int character, layer;
1078   int flags = readUInt8(f);
1079 
1080   if(flags == 0)
1081     return 0;
1082 
1083   if(flags & 0x08)
1084     println("Hit flag: ");
1085   if(flags & 0x04)
1086     println("Down flag: ");
1087   if(flags & 0x02)
1088     println("Over flag: ");
1089   if(flags & 0x01)
1090     println("Up flag: ");
1091 
1092   character = readUInt16(f);
1093   layer = readUInt16(f);
1094 
1095   println("character: %i, layer %i", character, layer);
1096   printMatrix(f);
1097 
1098   if(recordType == 2)
1099     printCXForm(f, true); /* XXX - should be true? */
1100 
1101   return 1;
1102 }
1103 
printDefineButton(FILE * f,int length)1104 void printDefineButton(FILE *f, int length)
1105 {
1106   int offset = fileOffset;
1107 
1108   println("Button id: %i", readUInt16(f));
1109 
1110   ++gIndent;
1111   while(printButtonRecord(f, 1)) ;
1112 
1113   decompileAction(f, length-(fileOffset-offset), 0);
1114   --gIndent;
1115 }
1116 
printButton2ActionCondition(FILE * f,int end)1117 int printButton2ActionCondition(FILE *f, int end)
1118 {
1119   int offset = readUInt16(f);
1120   int condition = readUInt16(f);
1121 
1122   println("offset = %i", offset);
1123 
1124   if(condition & 0xfe00) println("condition: keyPress(%c)", (condition&0xfe00)>>9);
1125   if(condition & 0x100) println("condition: overDownToIdle");
1126   if(condition & 0x80)  println("condition: idleToOverDown");
1127   if(condition & 0x40)  println("condition: outDownToIdle");
1128   if(condition & 0x20)  println("condition: outDownToOverDown");
1129   if(condition & 0x10)  println("condition: overDownToOutDown");
1130   if(condition & 0x08)  println("condition: overDownToOverUp");
1131   if(condition & 0x04)  println("condition: overUpToOverDown");
1132   if(condition & 0x02)  println("condition: overUpToIdle");
1133   if(condition & 0x01)  println("condition: idleToOverUp");
1134 
1135   if(offset == 0)
1136     decompileAction(f, end-fileOffset, 0);
1137   else
1138     decompileAction(f, offset-4, 0);
1139 
1140   return offset;
1141 }
1142 
printDefineButton2(FILE * f,int length)1143 void printDefineButton2(FILE *f, int length)
1144 {
1145   int flags, offset, end = fileOffset+length;
1146 
1147   println("Button id: %i", readUInt16(f));
1148   flags = readUInt8(f); /* flags */
1149 
1150   if(flags)
1151     println("tracked as menu item (whatever that means..)");
1152 
1153   offset = readUInt16(f); /* offset */
1154   println("offset = %i", offset);
1155 
1156   while(printButtonRecord(f, 2)) ;
1157 
1158   if(offset>0)
1159     while(printButton2ActionCondition(f, end)) ;
1160 }
1161 
printPlaceObject(FILE * f,int length)1162 void printPlaceObject(FILE *f, int length)
1163 {
1164   int start = fileOffset;
1165 
1166   println("Character ID: %i", readUInt16(f));
1167   println("Depth: %i", readUInt16(f));
1168   println("Matrix:");
1169   printMatrix(f);
1170 
1171   if(fileOffset < start+length)
1172   {
1173     print("CXform: ");
1174     printCXForm(f, false);
1175     putchar('\n');
1176   }
1177 }
1178 
1179 #define PLACE_RESERVED		(1<<7)
1180 #define PLACE_HASCLIP		(1<<6)
1181 #define PLACE_HASNAME		(1<<5)
1182 #define PLACE_HASRATIO		(1<<4)
1183 #define PLACE_HASCXFORM		(1<<3)
1184 #define PLACE_HASMATRIX		(1<<2)
1185 #define PLACE_HASCHARACTER	(1<<1)
1186 #define PLACE_HASMOVE		(1<<0)
1187 
printPlaceObject2(FILE * f,int length)1188 void printPlaceObject2(FILE *f, int length)
1189 {
1190   int start = fileOffset;
1191   int flags = readUInt8(f);
1192   int l;
1193 
1194   println("Depth: %i", readUInt16(f));
1195 
1196   if(flags & PLACE_HASMOVE)
1197     println("Has move flag");
1198 
1199   if(flags & PLACE_HASCHARACTER)
1200     println("Character ID: %i", readUInt16(f));
1201 
1202   if(flags & PLACE_HASMATRIX)
1203   {
1204     println("Matrix:");
1205     printMatrix(f);
1206   }
1207 
1208   if(flags & PLACE_HASCXFORM)
1209   {
1210     print("CXForm: ");
1211     printCXForm(f, true);
1212     putchar('\n');
1213   }
1214 
1215   if(flags & PLACE_HASRATIO)
1216     println("Ratio: %i", readUInt16(f));
1217 
1218   if(flags & PLACE_HASNAME)
1219     println("Name: %s", readString(f));
1220 
1221   if(flags & PLACE_HASCLIP)
1222     println("ClipDepth: %i", readUInt16(f));
1223 
1224   if(flags & PLACE_RESERVED)
1225   {
1226     println("Mystery number: %04x", readUInt16(f));
1227 
1228     flags = readUInt16(f);
1229     println("Clip flags: %04x", flags);
1230 
1231     while((flags = readUInt16(f)) != 0)
1232     {
1233       println("Flags: %04x", flags);
1234       l = readUInt32(f);
1235       decompileAction(f, l, 0);
1236     }
1237   }
1238 
1239   dumpBytes(f, length-(fileOffset-start));
1240 }
1241 
printRemoveObject(FILE * f)1242 void printRemoveObject(FILE *f)
1243 {
1244   println("ID: %i", readUInt16(f));
1245   println("Depth: %i", readUInt16(f));
1246 }
1247 
printRemoveObject2(FILE * f)1248 void printRemoveObject2(FILE *f)
1249 {
1250   println("Depth: %i", readUInt16(f));
1251 }
1252 
printSetBackgroundColor(FILE * f)1253 void printSetBackgroundColor(FILE *f)
1254 {
1255   print("Color: ");
1256   printRGB(f);
1257   putchar('\n');
1258 }
1259 
printFrameLabel(FILE * f)1260 void printFrameLabel(FILE *f)
1261 {
1262   println("Label: %s\n", readString(f));
1263 }
1264 
printDefineFont(FILE * f,int length)1265 void printDefineFont(FILE *f, int length)
1266 {
1267   int here, off0, off, i, nShapes, fillBits=1, lineBits=1;
1268   int *offset;
1269 
1270   println("FontID: %i", readUInt16(f));
1271 
1272   off0 = readUInt16(f);
1273 
1274   nShapes = off0/2;
1275   println("Number of shapes: %i", nShapes);
1276 
1277   offset = (int *)malloc(nShapes*sizeof(int));
1278 
1279   ++gIndent;
1280   println("Offset0: 0");
1281 
1282   for(i=1; i<nShapes; ++i)
1283   {
1284     off = readUInt16(f);
1285     offset[i-1] = off-off0;
1286     println("Offset%i: %i", i, offset[i-1]);
1287   }
1288   offset[nShapes-1] = length-2-(nShapes*2);
1289 
1290   here = fileOffset;
1291 
1292   for(i=0; i<nShapes; ++i)
1293   {
1294     putchar('\n');
1295 
1296     byteAlign();
1297     println("Shape %i:", i);
1298 
1299     fillBits = readBits(f, 4);
1300     lineBits = readBits(f, 4);
1301 
1302     ++gIndent;
1303     while(fileOffset < here+offset[i])
1304       printShapeRec(f, &fillBits, &lineBits, 2);
1305     --gIndent;
1306   }
1307 
1308   --gIndent;
1309 }
1310 
1311 #define FONTINFO2_HASLAYOUT		(1<<7)
1312 #define FONTINFO2_SHIFTJIS		(1<<6)
1313 #define FONTINFO2_UNICODE		(1<<5)
1314 #define FONTINFO2_ANSI			(1<<4)
1315 #define FONTINFO2_WIDEOFFSETS	        (1<<3)
1316 #define FONTINFO2_WIDECODES		(1<<2)
1317 #define FONTINFO2_ITALIC		(1<<1)
1318 #define FONTINFO2_BOLD			(1<<0)
1319 
printDefineFont2(FILE * f,int length)1320 void printDefineFont2(FILE *f, int length)
1321 {
1322   int flags, nGlyphs, namelen, i, fillBits, lineBits;
1323   int here = fileOffset;
1324   int *offset;
1325 
1326   println("fontID: %i", readUInt16(f));
1327 
1328   flags = readUInt8(f);
1329 
1330   readUInt8(f); /* "reserved" */
1331 
1332   namelen = readUInt8(f);
1333 
1334   print("Font Name: ");
1335 
1336   for(; namelen>0; --namelen)
1337     putchar((unsigned char)readUInt8(f));
1338 
1339   putchar('\n');
1340 
1341   nGlyphs = readUInt16(f);
1342   println("number of glyphs: %i\n", nGlyphs);
1343 
1344   offset = (unsigned int *)malloc(nGlyphs*sizeof(int));
1345 
1346   /* offset table */
1347 
1348   here = fileOffset;
1349 
1350   for(i=0; i<=nGlyphs; ++i)
1351   {
1352     if(flags & FONTINFO2_WIDEOFFSETS)
1353       offset[i] = readUInt32(f)-4*nGlyphs-2;
1354     else
1355       offset[i] = readUInt16(f)-2*nGlyphs-2;
1356 
1357     println("Offset%i: %i", i, offset[i]);
1358   }
1359 
1360   here = fileOffset;
1361 
1362   /* shape table */
1363   for(i=0; i<nGlyphs; ++i)
1364   {
1365     byteAlign();
1366     println("Glyph %i:", i);
1367 
1368     fillBits = readBits(f, 4);
1369     lineBits = readBits(f, 4);
1370 
1371     byteAlign();
1372     while(printShapeRec(f, &fillBits, &lineBits, 2)) ;
1373 
1374     putchar('\n');
1375   }
1376 
1377   /* code table */
1378   for(i=0; i<nGlyphs; ++i)
1379   {
1380     if(flags & FONTINFO2_WIDECODES)
1381       println("glyph code %i: %i", i, readUInt16(f));
1382     else
1383       println("glyph code %i: %i", i, readUInt8(f));
1384   }
1385 
1386   if(flags & FONTINFO2_HASLAYOUT)
1387   {
1388     int kernCount, code1, code2;
1389 
1390     println("ascender height: %i", readSInt16(f));
1391     println("descender height: %i", readSInt16(f));
1392     println("leading height: %i", readSInt16(f));
1393 
1394     for(i=0; i<nGlyphs; ++i)
1395       printf("\tadvance %i: %i\n", i, readSInt16(f));
1396 
1397     for(i=0; i<nGlyphs; ++i)
1398     {
1399       print("bounds %i: ", i);
1400       printRect(f);
1401       putchar('\n');
1402     }
1403 
1404     kernCount = readUInt16(f);
1405 
1406     for(i=0; i<kernCount; ++i)
1407     {
1408       code1 = (flags & FONTINFO2_WIDECODES) ? readUInt16(f) : readUInt8(f);
1409       code2 = (flags & FONTINFO2_WIDECODES) ? readUInt16(f) : readUInt8(f);
1410       println("(%i,%i): adjustment = %i", code1, code2, readSInt16(f));
1411     }
1412   }
1413 }
1414 
1415 #define FONTINFO_RESERVED	(1<<6 | 1<<7)
1416 #define FONTINFO_UNICODE	(1<<5)
1417 #define FONTINFO_SHIFTJIS	(1<<4)
1418 #define FONTINFO_ANSI		(1<<3)
1419 #define FONTINFO_ITALIC		(1<<2)
1420 #define FONTINFO_BOLD		(1<<1)
1421 #define FONTINFO_WIDE		(1<<0)
1422 
printFontInfo(FILE * f,int length)1423 void printFontInfo(FILE *f, int length)
1424 {
1425   int namelen, nGlyphs, flags, i;
1426 
1427   println("FontID: %i", readUInt16(f));
1428 
1429   namelen = readUInt8(f);
1430   nGlyphs = length-namelen-4;
1431 
1432   print("Font Name: ");
1433 
1434   for(; namelen>0; --namelen)
1435     putchar((unsigned char)readUInt8(f));
1436 
1437   putchar('\n');
1438 
1439   flags = readUInt8(f);
1440 
1441   if(flags & FONTINFO_UNICODE)
1442     println("Unicode character codes!");
1443 
1444   if(flags & FONTINFO_SHIFTJIS)
1445     println("\tShiftJIS character codes!");
1446 
1447   if(flags & FONTINFO_ANSI)
1448     println("\tANSI character codes!");
1449 
1450   if(flags & FONTINFO_ITALIC)
1451     println("\tFont is italic!");
1452 
1453   if(flags & FONTINFO_BOLD)
1454     println("\tFont is bold!");
1455 
1456   if(flags & FONTINFO_WIDE)
1457     nGlyphs /= 2;
1458 
1459   for(i=0; i<nGlyphs; ++i)
1460     if(flags & FONTINFO_WIDE)
1461       println("glyph %i: %i", i, readUInt16(f));
1462     else
1463       println("glyph %i: %i", i, readUInt8(f));
1464 }
1465 
1466 #define TEXTRECORD_STATECHANGE	(1<<7)
1467 #define TEXTRECORD_RESERVED		(1<<6 | 1<<5 | 1<<4)
1468 #define TEXTRECORD_HASFONT		(1<<3)
1469 #define TEXTRECORD_HASCOLOR		(1<<2)
1470 #define TEXTRECORD_HASYOFF		(1<<1)
1471 #define TEXTRECORD_HASXOFF		(1<<0)
1472 #define TEXTRECORD_NUMGLYPHS	0x7f
1473 
printTextRecord(FILE * f,int glyphBits,int advanceBits,int type)1474 int printTextRecord(FILE *f, int glyphBits, int advanceBits, int type)
1475 {
1476   int i, numGlyphs;
1477   int flags = readUInt8(f);
1478 
1479   if(flags == 0)
1480     return 0;
1481 
1482   if(flags & TEXTRECORD_STATECHANGE)
1483   {
1484     if(flags & TEXTRECORD_HASFONT)
1485       println("font id: %i", readUInt16(f));
1486 
1487     if(flags & TEXTRECORD_HASCOLOR)
1488     {
1489       print("color: ");
1490 
1491       if(type == 2)
1492 	printRGBA(f);
1493       else
1494 	printRGB(f);
1495 
1496       putchar('\n');
1497     }
1498 
1499     if(flags & TEXTRECORD_HASXOFF)
1500       println("X Offset: %i", readSInt16(f));
1501 
1502     if(flags & TEXTRECORD_HASYOFF)
1503       println("Y Offset: %i", readSInt16(f));
1504 
1505     if(flags & TEXTRECORD_HASFONT)
1506       println("font height: %i", readUInt16(f));
1507   }
1508   else
1509   {
1510     numGlyphs = flags & TEXTRECORD_NUMGLYPHS;
1511 
1512     for(i=0; i<numGlyphs; ++i)
1513     {
1514       println("glyph index: %i", readBits(f, glyphBits));
1515       println("glyph x advance: %i", readSBits(f, advanceBits));
1516     }
1517   }
1518 
1519   return 1;
1520 }
1521 
printDefineText(FILE * f,int length,int type)1522 void printDefineText(FILE *f, int length, int type) /* type 2 allows transparency */
1523 {
1524   int glyphBits, advanceBits, end = fileOffset+length;
1525 
1526   println("character id: %i", readUInt16(f));
1527   print("bounds: ");
1528   printRect(f);
1529   putchar('\n');
1530   byteAlign();
1531   println("matrix:");
1532   printMatrix(f);
1533   glyphBits = readUInt8(f);
1534   advanceBits = readUInt8(f);
1535 
1536   while(fileOffset < end &&
1537 	printTextRecord(f, glyphBits, advanceBits, type)) ;
1538 }
1539 
printSoundInfo(FILE * f)1540 void printSoundInfo(FILE *f)
1541 {
1542   int flags = readUInt8(f), nPoints, i;
1543 
1544   ++gIndent;
1545 
1546   if(flags&0x40)
1547     println("Don't start if already playing");
1548 
1549   if(flags&0x80)
1550     println("Stop sound");
1551 
1552   if(flags&0x01)
1553     println("In Point: %i", readUInt32(f));
1554 
1555   if(flags&0x02)
1556     println("Out Point: %i", readUInt32(f));
1557 
1558   if(flags&0x04)
1559     println("Loops: %i", readUInt16(f));
1560 
1561   if(flags&0x08)
1562   {
1563     nPoints = readUInt8(f);
1564     for(i=0; i<nPoints; ++i)
1565     {
1566       println("Envelope point %i:", i);
1567       println("Mark44: %i", readUInt32(f));
1568       println("Level0: %i", readUInt16(f));
1569       println("Level1: %i", readUInt16(f));
1570     }
1571   }
1572 
1573   --gIndent;
1574 }
1575 
1576 
1577 #define MP3_FRAME_SYNC       0xFFE00000
1578 
1579 #define MP3_VERSION          0x00180000
1580 #define MP3_VERSION_25       0x00000000
1581 #define MP3_VERSION_RESERVED 0x00080000
1582 #define MP3_VERSION_2        0x00100000
1583 #define MP3_VERSION_1        0x00180000
1584 
1585 #define MP3_LAYER            0x00060000
1586 #define MP3_LAYER_RESERVED   0x00000000
1587 #define MP3_LAYER_3          0x00020000
1588 #define MP3_LAYER_2          0x00040000
1589 #define MP3_LAYER_1          0x00060000
1590 
1591 #define MP3_PROTECT          0x00010000 /* 16-bit CRC after header */
1592 
1593 #define MP3_BITRATE          0x0000F000
1594 #define MP3_BITRATE_SHIFT    12
1595 
1596 int mp1l1_bitrate_table[] = { 0,   32,   64,  96, 128, 160, 192, 224,
1597 			      256, 288, 320, 352, 382, 416, 448 };
1598 
1599 int mp1l2_bitrate_table[] = { 0,   32,   48,  56,  64,  80,  96, 112,
1600 			      128, 160, 192, 224, 256, 320, 384 };
1601 
1602 int mp1l3_bitrate_table[] = { 0,    32,  40,  48,  56,  64,  80,  96,
1603 			      112, 128, 160, 192, 224, 256, 320 };
1604 
1605 int mp2l1_bitrate_table[] = { 0,    32,  48,  56,  64,  80,  96, 112,
1606 			      128, 144, 160, 176, 192, 224, 256 };
1607 
1608 int mp2l23_bitrate_table[] = { 0,    8,  16,  24,  32,  40,  48,  56,
1609 			       64,  80,  96, 112, 128, 144, 160 };
1610 
1611 #define MP3_SAMPLERATE       0x00000C00
1612 #define MP3_SAMPLERATE_SHIFT 10
1613 
1614 int mp1_samplerate_table[] = { 44100, 48000, 32000 };
1615 int mp2_samplerate_table[] = { 22050, 24000, 16000 }; /* is this right?? */
1616 int mp25_samplerate_table[] = { 11025, 12000, 8000 }; /* less samples in > versions? */
1617 
1618 #define MP3_PADDING          0x00000200 /* if set, add an extra slot - 4 bytes
1619 					   for layer 1, 1 byte for 2+3 */
1620 
1621 #define MP3_CHANNEL          0x000000C0
1622 #define MP3_CHANNEL_STEREO   0x00000000
1623 #define MP3_CHANNEL_JOINT    0x00000040
1624 #define MP3_CHANNEL_DUAL     0x00000080
1625 #define MP3_CHANNEL_MONO     0x000000C0
1626 
1627 /* rest of the header info doesn't affect frame size.. */
1628 
silentSkipBytes(FILE * f,int length)1629 void silentSkipBytes(FILE *f, int length)
1630 {
1631   for(; length>0; --length)
1632     readUInt8(f);
1633 }
1634 
printMP3Headers(FILE * f,int length)1635 void printMP3Headers(FILE *f, int length)
1636 {
1637   unsigned long flags;
1638   int frameLen, frameNum = 0;
1639   int bitrate, bitrate_idx, samplerate, samplerate_idx;
1640   int version, layer, channels;
1641   int padding;
1642 
1643   while(length > 0)
1644   {
1645     ++frameNum;
1646 
1647     /* get 4-byte header, bigendian */
1648     flags = fgetc(f) << 24;
1649     flags += fgetc(f) << 16;
1650     flags += fgetc(f) << 8;
1651     flags += fgetc(f);
1652     if (feof(f))
1653     {
1654       fprintf(stderr, "truncated file\n");
1655       exit(-1);
1656     }
1657 
1658     fileOffset += 4;
1659 
1660     if((flags & MP3_FRAME_SYNC) != MP3_FRAME_SYNC)
1661       error("bad sync on MP3 block!");
1662 
1663     bitrate_idx = (flags & MP3_BITRATE) >> MP3_BITRATE_SHIFT;
1664     samplerate_idx = (flags & MP3_SAMPLERATE) >> MP3_SAMPLERATE_SHIFT;
1665 
1666     channels = ((flags & MP3_CHANNEL) == MP3_CHANNEL_MONO) ? 1 : 2;
1667 
1668     switch(flags & MP3_VERSION)
1669     {
1670       case MP3_VERSION_1:  version = 1; break;
1671       case MP3_VERSION_2:  version = 2; break;
1672       case MP3_VERSION_25: version = 25; break;
1673       default: error("unknown MP3 version!"); return;
1674     }
1675     switch(flags & MP3_LAYER)
1676     {
1677       case MP3_LAYER_1: layer = 1; break;
1678       case MP3_LAYER_2: layer = 2; break;
1679       case MP3_LAYER_3: layer = 3; break;
1680       default: error("unknown MP3 layer!"); return;
1681     }
1682 
1683     if(version == 1)
1684     {
1685       samplerate = mp1_samplerate_table[samplerate_idx];
1686 
1687       if(layer == 1)
1688 	bitrate = mp1l1_bitrate_table[bitrate_idx];
1689 
1690       else if(layer == 2)
1691 	bitrate = mp1l2_bitrate_table[bitrate_idx];
1692 
1693       else // if(layer == 3)
1694 	bitrate = mp1l3_bitrate_table[bitrate_idx];
1695     }
1696     else
1697     {
1698       if(version == 2)
1699 	samplerate = mp2_samplerate_table[samplerate_idx];
1700       else
1701 	samplerate = mp25_samplerate_table[samplerate_idx];
1702 
1703       if(layer == 1)
1704 	bitrate = mp2l1_bitrate_table[bitrate_idx];
1705       else
1706 	bitrate = mp2l23_bitrate_table[bitrate_idx];
1707     }
1708 
1709     padding = (flags & MP3_PADDING) ? 1 : 0;
1710 
1711     if(layer == 1)
1712       padding <<= 2;
1713 
1714     if(version == 1)
1715       frameLen = 144 * bitrate * 1000 / samplerate + padding;
1716     else
1717       frameLen = 72 * bitrate * 1000 / samplerate + padding;
1718 
1719     println("frame %i: MP%i layer %i, %i Hz, %ikbps, %s, length=%i, protect %s",
1720 	   frameNum, version, layer, samplerate, bitrate,
1721 	   (channels==2) ? "stereo" : "mono", frameLen,
1722 	   (flags&MP3_PROTECT) ? "on" : "off");
1723 
1724     if(length < frameLen-4)
1725       silentSkipBytes(f, length);
1726     else
1727       silentSkipBytes(f, frameLen-4);
1728 
1729     length -= frameLen;
1730   }
1731 
1732   if(length>0)
1733     dumpBytes(f, length);
1734 }
1735 
printDefineSound(FILE * f,int length)1736 void printDefineSound(FILE *f, int length)
1737 {
1738   int flags;
1739 
1740   println("Character ID: %i", readUInt16(f));
1741 
1742   flags = readUInt8(f);
1743 
1744   switch(flags&0xf0)
1745   {
1746     case 0x20: print("Sound Format: mp3 ");              break;
1747     case 0x10: print("Sound Format: ADPCM compressed "); break;
1748     case 0x00: print("Sound Format: uncompressed ");     break;
1749     default:   print("Sound Format: unknown compression ");
1750   }
1751 
1752   if((flags&0x0c) == 0)
1753     puts("5KHz ");
1754   else if((flags&0x0c) == 4)
1755     puts("11KHz ");
1756   else if((flags&0x0c) == 8)
1757     puts("22KHz ");
1758   else
1759     puts("44KHz ");
1760 
1761   if(flags&0x02)
1762     puts("16 bit ");
1763   else
1764     puts("8 bit ");
1765 
1766   if(flags&0x01)
1767     puts("stereo\n");
1768   else
1769     puts("mono\n");
1770 
1771   println("Number of samples: %i", readUInt32(f));
1772 
1773   if((flags&0xf0) == 0x20) /* mp3 */
1774   {
1775     ++gIndent;
1776     println("Delay: %i", readUInt16(f));
1777     printMP3Headers(f, length-9);
1778     --gIndent;
1779   }
1780   else
1781     dumpBytes(f, length-7);
1782 }
1783 
1784 int streamflags;
1785 
1786 /* only difference is type 2 allows uncompressed data,
1787    and 8-bit if uncompressed */
printSoundStreamHead(FILE * f,int type)1788 void printSoundStreamHead(FILE *f, int type)
1789 {
1790   int recFormat = readUInt8(f);
1791   int flags = readUInt8(f);
1792 
1793   streamflags = flags;
1794 
1795   println("Recommended Format: %02x", recFormat);
1796   println("flags: %02x", flags);
1797 
1798   if((flags&0xf0) == 0x20)
1799   {
1800     println("mp3 format");
1801     println("Avg. number of Samples per Block: %i", readUInt16(f));
1802     println("Mystery goo: %i", readUInt16(f));
1803   }
1804   else
1805     println("Number of Samples: %i", readUInt16(f));
1806 }
1807 
printSoundStreamBlock(FILE * f,int length)1808 void printSoundStreamBlock(FILE *f, int length)
1809 {
1810   int samplesperframe, delay;
1811 
1812   if((streamflags&0xf0) == 0x00)
1813   {
1814     println("Uncompressed samples");
1815     skipBytes(f, length);
1816   }
1817   else if((streamflags&0xf0) == 0x10)
1818   {
1819     println("ADPCM compressed samples");
1820     skipBytes(f, length);
1821   }
1822   else if((streamflags&0xf0) == 0x20)
1823   {
1824     samplesperframe = readUInt16(f);
1825     delay = readUInt16(f);
1826     println("MP3 compressed samples: %i samples, delay=%i",
1827 	    samplesperframe, delay);
1828 
1829     printMP3Headers(f, length-4);
1830   }
1831   else
1832     println("Unknown compression type!");
1833 }
1834 
printSprite(FILE * f,int length)1835 void printSprite(FILE *f, int length)
1836 {
1837   int start = fileOffset;
1838   int block, type, l;
1839 
1840   println("id: %i", readUInt16(f));
1841   println("frame count: %i\n", readUInt16(f));
1842 
1843   while(fileOffset < start+length)
1844   {
1845     println("Offset %i (0x%x)", fileOffset, fileOffset);
1846 
1847     block = readUInt16(f);
1848     type = block>>6;
1849 
1850     println("Block type: %i (%s)", type, blockName(type));
1851 
1852     l = block & ((1<<6)-1);
1853 
1854     if(l == 63) /* it's a long block. */
1855       l = readUInt32(f);
1856 
1857     println("Block length: %i\n", l);
1858 
1859     ++gIndent;
1860 
1861     switch(type)
1862     {
1863       case SWF_PLACEOBJECT:		printPlaceObject(f, l);		break;
1864       case SWF_PLACEOBJECT2:		printPlaceObject2(f, l);	break;
1865       case SWF_REMOVEOBJECT:		printRemoveObject(f);		break;
1866       case SWF_REMOVEOBJECT2:		printRemoveObject2(f);		break;
1867       case SWF_FRAMELABEL:		printFrameLabel(f);		break;
1868       case SWF_DOACTION:		decompileAction(f, l, 0);       break;
1869       case SWF_SOUNDSTREAMHEAD: 	printSoundStreamHead(f, 1);     break;
1870       case SWF_SOUNDSTREAMHEAD2:	printSoundStreamHead(f, 2);     break;
1871       case SWF_SOUNDSTREAMBLOCK:	printSoundStreamBlock(f, l);    break;
1872       default:			if(l>0) dumpBytes(f, l);		break;
1873     }
1874 
1875     --gIndent;
1876   /*
1877     startsound
1878   */
1879   }
1880 }
1881 
1882 #define TEXTFIELD_HASLENGTH (1<<1)
1883 #define TEXTFIELD_NOEDIT    (1<<3)
1884 #define TEXTFIELD_PASSWORD  (1<<4)
1885 #define TEXTFIELD_MULTILINE (1<<5)
1886 #define TEXTFIELD_WORDWRAP  (1<<6)
1887 #define TEXTFIELD_DRAWBOX   (1<<11)
1888 #define TEXTFIELD_NOSELECT  (1<<12)
1889 
1890 #define TEXTFIELD_JUSTIFY_LEFT    0
1891 #define TEXTFIELD_JUSTIFY_RIGHT   1
1892 #define TEXTFIELD_JUSTIFY_CENTER  2
1893 #define TEXTFIELD_JUSTIFY_JUSTIFY 3
1894 
printTextField(FILE * f,int length)1895 void printTextField(FILE *f, int length)
1896 {
1897   int flags, num, end = fileOffset+length;
1898 
1899   println("Character id: %i", readUInt16(f));
1900   print("Bounds: ");
1901   printRect(f);
1902   println("flags: 0x%04x", flags=readUInt16(f));
1903 
1904   if(flags & TEXTFIELD_HASLENGTH)
1905     println("Has Length");
1906   if(flags & TEXTFIELD_NOEDIT)
1907     println("Disable Editing");
1908   if(flags & TEXTFIELD_PASSWORD)
1909     println("Password Field");
1910   if(flags & TEXTFIELD_MULTILINE)
1911     println("Multiline");
1912   if(flags & TEXTFIELD_WORDWRAP)
1913     println("Word Wrap");
1914   if(flags & TEXTFIELD_DRAWBOX)
1915     println("Draw Bounding Box");
1916   if(flags & TEXTFIELD_NOSELECT)
1917     println("No Select");
1918 
1919   println("Font id: %i", readUInt16(f));
1920   println("Font height: %i", readUInt16(f));
1921   print("Color: ");
1922   printRGBA(f);
1923   putchar('\n');
1924 
1925   if(flags & TEXTFIELD_HASLENGTH)
1926     println("Length (max chars): %i", readUInt16(f));
1927 
1928   print("Alignment: ");
1929 
1930   switch(num = readUInt8(f))
1931   {
1932     case TEXTFIELD_JUSTIFY_LEFT:    print("left\n");    break;
1933     case TEXTFIELD_JUSTIFY_RIGHT:   print("right\n");   break;
1934     case TEXTFIELD_JUSTIFY_CENTER:  print("center\n");  break;
1935     case TEXTFIELD_JUSTIFY_JUSTIFY: print("justify\n"); break;
1936     default: println("unexpected justification: %i", num);
1937   }
1938 
1939   println("Left margin: %i", readUInt16(f));
1940   println("Right margin: %i", readUInt16(f));
1941   println("First line indentation: %i", readUInt16(f));
1942   println("Line spacing: %i", readUInt16(f));
1943 
1944   println("Variable Name: %s", readString(f));
1945 
1946   if(fileOffset<end)
1947     println("Initial Text: %s", readString(f));
1948 
1949   putchar('\n');
1950 
1951   if(fileOffset<end)
1952     dumpBytes(f, end-fileOffset);
1953 }
1954 
printLibrarySymbol(FILE * f,int length)1955 void printLibrarySymbol(FILE *f, int length)
1956 {
1957   println("mystery number: %i", readUInt16(f));
1958   println("character id: %i", readUInt16(f));
1959   println("name: %s", readString(f));
1960 }
1961 
printPassword(FILE * f,int length)1962 void printPassword(FILE *f, int length)
1963 {
1964   println("mystery number: %i", readUInt16(f));
1965   println("encrypted password: %s", readString(f));
1966 }
1967 
skipBytes(FILE * f,int length)1968 void skipBytes(FILE *f, int length)
1969 {
1970   ++gIndent;
1971   println("<%i bytes skipped>", length);
1972   --gIndent;
1973 
1974   for(; length>0; --length)
1975     readUInt8(f);
1976 }
1977 
printImportAssets(FILE * f,int length)1978 void printImportAssets(FILE *f, int length)
1979 {
1980       int n, i;
1981       println("\tAsset URL: %s", readString(f));
1982       n = readUInt16(f);
1983       println("\tNumber of assets: %d", n);
1984       for (i=0; i<n; i++)
1985       {
1986       	print("\tTag%d: %d\n", i+1, readUInt16(f));
1987       	print("\tName%d: %s\n", i+1, readString(f));
1988       }
1989 }
1990 
main(int argc,char * argv[])1991 int main(int argc, char *argv[])
1992 {
1993   FILE *f;
1994   int size, version, block, type, length;
1995 
1996   if(argc > 1)
1997   {
1998     if(!(f = fopen(argv[1],"rb")))
1999       error("Sorry, can't seem to read that file.\n");
2000   }
2001   else
2002     f = stdin;
2003 
2004   while(!feof(f))
2005   {
2006     if(fgetc(f)=='F' && fgetc(f)=='W' && fgetc(f)=='S')
2007       break;
2008   }
2009 
2010   if(feof(f))
2011     error("Doesn't look like a swf file to me..\n");
2012 
2013   fileOffset = 3;
2014 
2015   version = readUInt8(f);
2016 
2017   size = readUInt32(f);
2018 
2019   println("File size: %i", size);
2020 
2021   print("Frame size: ");
2022   printRect(f);
2023   putchar('\n');
2024 
2025   println("Frame rate: %f / sec.", readUInt8(f)/256.0+readUInt8(f));
2026 
2027   println("Total frames: %i", readUInt16(f));
2028   putchar('\n');
2029 
2030   for(;;)
2031   {
2032     println("Offset: %i (0x%06x)", fileOffset, fileOffset);
2033 
2034     block = readUInt16(f);
2035     type = block>>6;
2036 
2037     println("Block type: %i (%s)", type, blockName(type));
2038 
2039     length = block & ((1<<6)-1);
2040 
2041     if(length == 63) /* it's a long block. */
2042       length = readUInt32(f);
2043 
2044     println("Block length: %i", length);
2045     putchar('\n');
2046 
2047     if(type == 0 || fileOffset >= size || length < 0)
2048       break;
2049 
2050     ++gIndent;
2051 
2052     switch(type)
2053     {
2054       case SWF_DEFINESPRITE:        printSprite(f, length);         break;
2055       case SWF_DEFINESHAPE3:
2056       case SWF_DEFINESHAPE2:
2057       case SWF_DEFINESHAPE:         printShape(f, length, type);	break;
2058       case SWF_PLACEOBJECT:		printPlaceObject(f, length);	break;
2059       case SWF_PLACEOBJECT2:	printPlaceObject2(f, length);	break;
2060       case SWF_REMOVEOBJECT:	printRemoveObject(f);		break;
2061       case SWF_REMOVEOBJECT2:	printRemoveObject2(f);		break;
2062       case SWF_SETBACKGROUNDCOLOR:	printSetBackgroundColor(f);	break;
2063       case SWF_FRAMELABEL:		printFrameLabel(f);		break;
2064       case SWF_DEFINEMORPHSHAPE:	printMorphShape(f, length);	break;
2065       case SWF_DEFINEFONT:		printDefineFont(f, length);	break;
2066       case SWF_DEFINEFONT2:		printDefineFont2(f, length);	break;
2067       case SWF_DEFINEFONTINFO:	printFontInfo(f, length);	break;
2068       case SWF_DEFINETEXT:		printDefineText(f, length, 1);	break;
2069       case SWF_DEFINETEXT2:		printDefineText(f, length, 2);	break;
2070       case SWF_DOACTION:		decompileAction(f, length, 0);	break;
2071       case SWF_DEFINESOUND:         printDefineSound(f, length);    break;
2072       case SWF_SOUNDSTREAMHEAD:     printSoundStreamHead(f, 1);     break;
2073       case SWF_SOUNDSTREAMHEAD2:    printSoundStreamHead(f, 2);     break;
2074       case SWF_SOUNDSTREAMBLOCK:    printSoundStreamBlock(f, length); break;
2075       case SWF_DEFINEBUTTON:        printDefineButton(f, length);   break;
2076       case SWF_DEFINEBUTTON2:       printDefineButton2(f, length);  break;
2077       case SWF_JPEGTABLES:          printJpegStream(f, length);     break;
2078       case SWF_DEFINEBITS:
2079       case SWF_DEFINEBITSJPEG2:     printDefineBitsJpeg(f,length);  break;
2080       case SWF_DEFINEBITSJPEG3:     printDefineBitsJpeg3(f,length); break;
2081       case SWF_DEFINELOSSLESS:
2082       case SWF_DEFINELOSSLESS2:	printDefineBitsLossless(f,length); break;
2083       case SWF_DEFINEEDITTEXT:	printTextField(f, length);	break;
2084       case SWF_EXPORTASSETS:	printLibrarySymbol(f, length);	break;
2085       case SWF_ENABLEDEBUGGER:	printPassword(f, length);	break;
2086       case SWF_IMPORTASSETS:	printImportAssets(f, length);   break;
2087 
2088       default:                  dumpBytes(f, length);	        break;
2089     }
2090 
2091     --gIndent;
2092     putchar('\n');
2093   }
2094 
2095   dumpBytes(f, size-fileOffset);
2096 
2097   return 0;
2098 }
2099