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