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 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 } 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 568 void printDefineBitsJpeg(FILE *f, int length) 569 { 570 println("Bitmap id: %i", readUInt16(f)); 571 printJpegStream(f, length-2); 572 } 573 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 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 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 1056 void printDecompiledAction(FILE *f, int l, int n) 1057 { 1058 char *as = decompile5Action(f, l, n); 1059 puts(as); 1060 } 1061 #endif 1062 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 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 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 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 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 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 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 1242 void printRemoveObject(FILE *f) 1243 { 1244 println("ID: %i", readUInt16(f)); 1245 println("Depth: %i", readUInt16(f)); 1246 } 1247 1248 void printRemoveObject2(FILE *f) 1249 { 1250 println("Depth: %i", readUInt16(f)); 1251 } 1252 1253 void printSetBackgroundColor(FILE *f) 1254 { 1255 print("Color: "); 1256 printRGB(f); 1257 putchar('\n'); 1258 } 1259 1260 void printFrameLabel(FILE *f) 1261 { 1262 println("Label: %s\n", readString(f)); 1263 } 1264 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 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 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 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 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 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 1629 void silentSkipBytes(FILE *f, int length) 1630 { 1631 for(; length>0; --length) 1632 readUInt8(f); 1633 } 1634 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 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 */ 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 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 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 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 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 1962 void printPassword(FILE *f, int length) 1963 { 1964 println("mystery number: %i", readUInt16(f)); 1965 println("encrypted password: %s", readString(f)); 1966 } 1967 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 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 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