2 Shows the structure of a swf file
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include "../config.h"
24 #ifdef HAVE_SYS_STAT_H
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
40 #include "../lib/rfxswf.h"
41 #include "../lib/args.h"
43 static char * filename = 0;
45 /* idtab stores the ids which are defined in the file. This allows us
46 to detect errors in the file. (i.e. ids which are defined more than
48 static char idtab[65536];
49 static char * indent = " ";
51 static int placements = 0;
52 static int action = 0;
56 static int showtext = 0;
57 static int showshapes = 0;
61 static int cumulative = 0;
63 static struct options_t options[] = {
83 int args_callback_option(char*name,char*val)
85 if(!strcmp(name, "V")) {
86 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
89 else if(name[0]=='a') {
93 else if(name[0]=='p') {
97 else if(name[0]=='t') {
101 else if(name[0]=='s') {
105 else if(name[0]=='e') {
109 else if(name[0]=='c') {
113 else if(name[0]=='E') {
118 else if(name[0]=='X') {
122 else if(name[0]=='Y') {
126 else if(name[0]=='r') {
130 else if(name[0]=='f') {
134 else if(name[0]=='d') {
138 else if(name[0]=='u') {
142 else if(name[0]=='b') {
146 else if(name[0]=='D') {
147 action = placements = showtext = showshapes = 1;
151 printf("Unknown option: -%s\n", name);
157 int args_callback_longoption(char*name,char*val)
159 return args_long2shortoption(options, name, val);
161 void args_callback_usage(char *name)
164 printf("Usage: %s [-atpdu] file.swf\n", name);
166 printf("-h , --help Print short help message and exit\n");
167 printf("-D , --full Show everything. Same as -atp\n");
168 printf("-V , --version Print version info and exit\n");
169 printf("-e , --html Print out html code for embedding the file\n");
170 printf("-E , --xhtml Print out xhtml code for embedding the file\n");
171 printf("-a , --action Disassemble action tags\n");
172 printf("-t , --text Show text fields (like swfstrings).\n");
173 printf("-s , --shapes Show shape coordinates/styles\n");
174 printf("-p , --placements Show placement information\n");
175 printf("-b , --bbox Print tag's bounding boxes\n");
176 printf("-X , --width Prints out a string of the form \"-X width\".\n");
177 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
178 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
179 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
180 printf("-d , --hex Print hex output of tag data, too.\n");
181 printf("-u , --used Show referred IDs for each Tag.\n");
184 int args_callback_command(char*name,char*val)
187 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
195 char* testfunc(char*str)
197 printf("%s: %s\n", what, str);
201 void dumpButton2Actions(TAG*tag, char*prefix)
207 oldTagPos = swf_GetTagPos(tag);
209 // scan DefineButton2 Record
211 swf_GetU16(tag); // Character ID
212 swf_GetU8(tag); // Flags;
214 offsetpos = swf_GetTagPos(tag); // first offset
217 while (swf_GetU8(tag)) // state -> parse ButtonRecord
218 { swf_GetU16(tag); // id
219 swf_GetU16(tag); // layer
220 swf_GetMatrix(tag,NULL); // matrix
221 swf_GetCXForm(tag,NULL,1); // cxform
228 if(tag->pos >= tag->len)
231 offsetpos = swf_GetU16(tag);
232 condition = swf_GetU16(tag); // condition
234 actions = swf_ActionGet(tag);
235 printf("%s condition %04x\n", prefix, condition);
236 swf_DumpActions(actions, prefix);
239 swf_SetTagPos(tag,oldTagPos);
243 void dumpButtonActions(TAG*tag, char*prefix)
246 swf_GetU16(tag); // id
247 while (swf_GetU8(tag)) // state -> parse ButtonRecord
248 { swf_GetU16(tag); // id
249 swf_GetU16(tag); // layer
250 swf_GetMatrix(tag,NULL); // matrix
252 actions = swf_ActionGet(tag);
253 swf_DumpActions(actions, prefix);
260 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
263 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
264 for(t=0;t<fontnum;t++)
266 if(fonts[t]->id == fontid) {
276 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
277 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
280 if(fonts[font]->glyph2ascii[glyphs[t]])
281 a = fonts[font]->glyph2ascii[glyphs[t]];
291 printf("\\x%x", (int)a);
296 void handleText(TAG*tag)
299 swf_ParseDefineText(tag,textcallback, 0);
302 void handleDefineSound(TAG*tag)
304 U16 id = swf_GetU16(tag);
305 U8 flags = swf_GetU8(tag);
306 int compression = (flags>>4)&7;
307 int rate = (flags>>2)&3;
308 int bits = flags&2?16:8;
309 int stereo = flags&1;
311 if(compression == 0) printf("Raw ");
312 else if(compression == 1) printf("ADPCM ");
313 else if(compression == 2) printf("MP3 ");
314 else if(compression == 3) printf("Raw little-endian ");
315 else if(compression == 6) printf("ASAO ");
317 if(rate == 0) printf("5.5Khz ");
318 if(rate == 1) printf("11Khz ");
319 if(rate == 2) printf("22Khz ");
320 if(rate == 3) printf("44Khz ");
321 printf("%dBit ", bits);
322 if(stereo) printf("stereo");
327 void handleDefineBits(TAG*tag)
333 id = swf_GetU16(tag);
334 mode = swf_GetU8(tag);
335 width = swf_GetU16(tag);
336 height = swf_GetU16(tag);
337 printf(" image %dx%d",width,height);
338 if(mode == 3) printf(" (8 bpp)");
339 else if(mode == 4) printf(" (16 bpp)");
340 else if(mode == 5) printf(" (32 bpp)");
341 else printf(" (? bpp)");
344 void handleEditText(TAG*tag)
349 id = swf_GetU16(tag);
352 //swf_ResetReadBits(tag);
358 flags = swf_GetBits(tag,16);
359 if(flags & ET_HASFONT) {
360 swf_GetU16(tag); //font
361 swf_GetU16(tag); //fontheight
363 if(flags & ET_HASTEXTCOLOR) {
364 swf_GetU8(tag); //rgba
369 if(flags & ET_HASMAXLENGTH) {
370 swf_GetU16(tag); //maxlength
372 if(flags & ET_HASLAYOUT) {
373 swf_GetU8(tag); //align
374 swf_GetU16(tag); //left margin
375 swf_GetU16(tag); //right margin
376 swf_GetU16(tag); //indent
377 swf_GetU16(tag); //leading
379 printf(" variable \"%s\" ", &tag->data[tag->pos]);
380 if(flags & ET_HTML) printf("(html)");
381 if(flags & ET_NOSELECT) printf("(noselect)");
382 if(flags & ET_PASSWORD) printf("(password)");
383 if(flags & ET_READONLY) printf("(readonly)");
385 if(flags & (ET_X1 | ET_X3 ))
387 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
390 while(tag->data[tag->pos++]);
391 if(flags & ET_HASTEXT)
392 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
395 void printhandlerflags(U32 handlerflags)
397 if(handlerflags&1) printf("[on load]");
398 if(handlerflags&2) printf("[enter frame]");
399 if(handlerflags&4) printf("[unload]");
400 if(handlerflags&8) printf("[mouse move]");
401 if(handlerflags&16) printf("[mouse down]");
402 if(handlerflags&32) printf("[mouse up]");
403 if(handlerflags&64) printf("[key down]");
404 if(handlerflags&128) printf("[key up]");
406 if(handlerflags&256) printf("[data]");
407 if(handlerflags&512) printf("[initialize]");
408 if(handlerflags&1024) printf("[mouse press]");
409 if(handlerflags&2048) printf("[mouse release]");
410 if(handlerflags&4096) printf("[mouse release outside]");
411 if(handlerflags&8192) printf("[mouse rollover]");
412 if(handlerflags&16384) printf("[mouse rollout]");
413 if(handlerflags&32768) printf("[mouse drag over]");
415 if(handlerflags&0x10000) printf("[mouse drag out]");
416 if(handlerflags&0x20000) printf("[key press]");
417 if(handlerflags&0x40000) printf("[construct even]");
418 if(handlerflags&0xfff80000) printf("[???]");
420 void handleVideoStream(TAG*tag, char*prefix)
422 U16 id = swf_GetU16(tag);
423 U16 frames = swf_GetU16(tag);
424 U16 width = swf_GetU16(tag);
425 U16 height = swf_GetU16(tag);
426 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
427 U8 codec = swf_GetU8(tag);
428 printf(" (%d frames, %dx%d", frames, width, height);
432 printf(" sorenson h.263)");
434 printf(" codec 0x%02x)", codec);
436 void handleVideoFrame(TAG*tag, char*prefix)
438 U32 code, version, reference, sizeflags;
439 U32 width=0, height=0;
441 U16 id = swf_GetU16(tag);
442 U16 frame = swf_GetU16(tag);
443 U8 deblock,flags, tmp, bit;
445 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
446 printf(" (frame %d) ", frame);
448 /* video packet follows */
449 code = swf_GetBits(tag, 17);
450 version = swf_GetBits(tag, 5);
451 reference = swf_GetBits(tag, 8);
453 sizeflags = swf_GetBits(tag, 3);
456 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
457 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
458 case 2: width = 352; height = 288; break;
459 case 3: width = 176; height = 144; break;
460 case 4: width = 128; height = 96; break;
461 case 5: width = 320; height = 240; break;
462 case 6: width = 160; height = 120; break;
463 case 7: width = -1; height = -1;/*reserved*/ break;
465 printf("%dx%d ", width, height);
466 type = swf_GetBits(tag, 2);
467 printf("%s", types[type]);
469 deblock = swf_GetBits(tag, 1);
471 printf(" deblock ", deblock);
472 quantizer = swf_GetBits(tag, 5);
473 printf(" quant: %d ", quantizer);
476 void dumpFilter(FILTER*filter)
478 if(filter->type == FILTERTYPE_BLUR) {
479 FILTER_BLUR*f = (FILTER_BLUR*)filter;
480 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
481 printf("passes: %d\n", f->passes);
482 } if(filter->type == FILTERTYPE_DROPSHADOW) {
483 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)filter;
484 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
485 printf("passes: %d\n", f->passes);
486 printf("angle: %f distance: %f\n", f->angle, f->distance);
487 printf("strength: %f passes: %d\n", f->strength, f->passes);
488 printf("flags: %s%s%s\n",
489 f->knockout?"knockout ":"",
490 f->composite?"composite ":"",
491 f->innershadow?"innershadow ":"");
492 } if(filter->type == FILTERTYPE_BEVEL) {
493 FILTER_BEVEL*f = (FILTER_BEVEL*)filter;
494 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
495 printf("passes: %d\n", f->passes);
496 printf("angle: %f distance: %f\n", f->angle, f->distance);
497 printf("strength: %f passes: %d\n", f->strength, f->passes);
498 printf("flags: %s%s%s%s\n",
500 f->knockout?"knockout ":"",
501 f->composite?"composite ":"",
502 f->innershadow?"innershadow ":"");
503 } if(filter->type == FILTERTYPE_GRADIENTGLOW) {
504 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)filter;
505 swf_DumpGradient(stdout, f->gradient);
506 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
507 printf("angle: %f distance: %f\n", f->angle, f->distance);
508 printf("strength: %f passes: %d\n", f->strength, f->passes);
509 printf("flags: %s%s%s%s\n",
510 f->knockout?"knockout ":"",
511 f->ontop?"ontop ":"",
512 f->composite?"composite ":"",
513 f->innershadow?"innershadow ":"");
518 void handlePlaceObject23(TAG*tag, char*prefix)
524 int ppos[3] = {0,0,0};
525 swf_SetTagPos(tag, 0);
526 flags = swf_GetU8(tag);
527 if(tag->id == ST_PLACEOBJECT3)
528 flags2 = swf_GetU8(tag);
529 swf_GetU16(tag); //depth
532 if(flags&2) swf_GetU16(tag); //id
534 swf_GetMatrix(tag,&m);
536 ppos[0] += sprintf(pstr[0], "| Matrix ");
537 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
538 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
542 swf_GetCXForm(tag, &cx, 1);
544 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
545 ppos[1] += sprintf(pstr[1]+ppos[1], "| mul %4.1f %4.1f %4.1f %4.1f ", cx.r0/256.0, cx.g0/256.0, cx.b0/256.0, cx.a0/256.0);
546 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
550 U16 ratio = swf_GetU16(tag); //ratio
552 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
553 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
554 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
558 U16 clip = swf_GetU16(tag); //clip
560 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
561 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-4d ", clip);
562 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
565 if(flags&32) { while(swf_GetU8(tag)); }
567 if(flags2&1) { // filter list
568 U8 num = swf_GetU8(tag);
570 printf("\n%d filters\n", num);
571 char*filtername[] = {"dropshadow","blur","glow","bevel","gradientglow","convolution","colormatrix","gradientbevel"};
574 FILTER*filter = swf_GetFilter(tag);
580 printf("filter %d: %02x (%s)\n", t, filter->type, (filter->type<sizeof(filtername)/sizeof(filtername[0]))?filtername[filter->type]:"?");
585 if(flags2&2) { // blend mode
586 U8 blendmode = swf_GetU8(tag);
590 sprintf(name, "%-5d", blendmode);
591 for(t=0;blendModeNames[t];t++) {
593 sprintf(name, "%-5s", blendModeNames[t]);
597 ppos[0] += sprintf(pstr[0]+ppos[0], "| Blend ");
598 ppos[1] += sprintf(pstr[1]+ppos[1], "| %s ", name);
599 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
603 if(placements && ppos[0]) {
605 printf("%s %s\n", prefix, pstr[0]);
606 printf("%s %s\n", prefix, pstr[1]);
607 printf("%s %s", prefix, pstr[2]);
616 reserved = swf_GetU16(tag); // must be 0
617 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
619 printf("Unknown parameter field not zero: %04x\n", reserved);
622 printf("global flags: %04x\n", globalflags);
624 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
626 handlerflags = swf_GetU32(tag);
629 while(handlerflags) {
634 globalflags &= ~handlerflags;
635 printf("%s flags %08x ",prefix, handlerflags);
636 printhandlerflags(handlerflags);
637 length = swf_GetU32(tag);
638 printf(", %d bytes actioncode\n",length);
639 a = swf_ActionGet(tag);
640 swf_DumpActions(a,prefix);
643 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
645 if(globalflags) // should go to sterr.
646 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
648 printf(" has action code\n");
653 void handlePlaceObject(TAG*tag, char*prefix)
655 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
660 swf_SetTagPos(tag, 0);
661 id = swf_GetU16(tag);
662 depth = swf_GetU16(tag);
663 swf_GetMatrix(tag, &matrix);
664 swf_GetCXForm(tag, &cxform, 0);
666 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
667 swf_SetU16(tag2, depth);
668 swf_SetU16(tag2, id);
669 swf_SetMatrix(tag2, &matrix);
670 swf_SetCXForm(tag2, &cxform, 1);
672 handlePlaceObject23(tag2, prefix);
675 char* fillstyle2str(FILLSTYLE*style)
677 switch(style->type) {
679 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
681 case 0x10: case 0x11: case 0x12: case 0x13:
682 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
684 case 0x40: case 0x42:
685 /* TODO: display information about that bitmap */
686 sprintf(stylebuf, "BITMAPt%s %d", (style->type&2)?"n":"", style->id_bitmap);
687 /* TODO: show matrix */
689 case 0x41: case 0x43:
690 /* TODO: display information about that bitmap */
691 sprintf(stylebuf, "BITMAPc%s %d", (style->type&2)?"n":"", style->id_bitmap);
692 /* TODO: show matrix */
695 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
699 char* linestyle2str(LINESTYLE*style)
701 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
705 void handleShape(TAG*tag, char*prefix)
713 swf_ParseDefineShape(tag, &shape);
715 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
717 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
722 else printf("%s | (Neither line nor fill styles)\n", prefix);
725 printf("%s", prefix);
726 if(t < shape.numfillstyles) {
727 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
731 if(t < shape.numlinestyles) {
732 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
737 printf("%s |\n", prefix);
741 printf("%s | fill: %02d/%02d line:%02d - ",
746 if(line->type == moveTo) {
747 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
748 } else if(line->type == lineTo) {
749 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
750 } else if(line->type == splineTo) {
751 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
752 line->sx/20.0, line->sy/20.0,
753 line->x/20.0, line->y/20.0
758 printf("%s |\n", prefix);
761 void fontcallback1(void*self, U16 id,U8 * name)
765 void fontcallback2(void*self, U16 id,U8 * name)
767 swf_FontExtract(&swf,id,&fonts[fontnum]);
771 static U8 printable(U8 a)
773 if(a<32 || a==127) return '.';
776 void hexdumpTag(TAG*tag, char* prefix)
780 printf(" %s-=> ",prefix);
781 for(t=0;t<tag->len;t++) {
782 printf("%02x ", tag->data[t]);
783 ascii[t&15] = printable(tag->data[t]);
784 if((t && ((t&15)==15)) || (t==tag->len-1))
788 for(s=p-1;s<16;s++) {
792 printf(" %s\n", ascii);
794 printf(" %s\n %s-=> ",ascii,prefix);
799 void handleExportAssets(TAG*tag, char* prefix)
805 num = swf_GetU16(tag);
808 id = swf_GetU16(tag);
809 name = swf_GetString(tag);
810 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
814 void dumperror(const char* format, ...)
819 va_start(arglist, format);
820 vsprintf(buf, format, arglist);
824 printf("==== Error: %s ====\n", buf);
827 static char strbuf[800];
830 char* timestring(double f)
832 int hours = (int)(f/3600);
833 int minutes = (int)((f-hours*3600)/60);
834 int seconds = (int)((f-hours*3600-minutes*60));
835 int useconds = (int)((f-(int)f)*1000+0.5);
838 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
839 return &strbuf[bufpos];
842 int main (int argc,char ** argv)
850 char issprite = 0; // are we inside a sprite definition?
853 char* spriteframelabel = 0;
854 char* framelabel = 0;
859 memset(idtab,0,65536);
861 processargs(argc, argv);
865 fprintf(stderr, "You must supply a filename.\n");
869 f = open(filename,O_RDONLY|O_BINARY);
874 sprintf(buffer, "Couldn't open %s", filename);
878 if FAILED(swf_ReadSWF(f,&swf))
880 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
887 if(statbuf.st_size != swf.fileSize && !swf.compressed)
888 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
889 statbuf.st_size, swf.fileSize);
890 filesize = statbuf.st_size;
895 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
896 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
900 printf("-X %d", xsize);
906 printf("-Y %d", ysize);
912 printf("-r %.2f", swf.frameRate/256.0);
918 printf("-f %d", swf.frameCount);
925 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
926 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
927 if(swf.fileVersion>9) {
928 fprintf(stderr, "Fileversion>9\n");
933 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
934 "<param name=\"movie\" value=\"%s\"/>\n"
935 "<param name=\"play\" value=\"true\"/>\n"
936 "<param name=\"loop\" value=\"false\"/>\n"
937 "<param name=\"quality\" value=\"high\"/>\n"
938 "<param name=\"loop\" value=\"false\"/>\n"
939 "</object>\n\n", filename, xsize, ysize, filename);
941 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
943 //" BGCOLOR=#ffffffff\n"?
945 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
946 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
947 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
948 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
949 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
950 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
951 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
952 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
953 " TYPE=\"application/x-shockwave-flash\"\n"
954 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
956 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
957 filename, filename, xsize, ysize);
961 printf("[HEADER] File version: %d\n", swf.fileVersion);
963 printf("[HEADER] File is zlib compressed.");
964 if(filesize && swf.fileSize)
965 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
969 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
970 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
971 printf("[HEADER] Frame count: %d\n",swf.frameCount);
972 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
973 if(swf.movieSize.xmin)
974 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
977 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
978 if(swf.movieSize.ymin)
979 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
987 swf_FontEnumerate(&swf,&fontcallback1, 0);
988 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
990 swf_FontEnumerate(&swf,&fontcallback2, 0);
994 char*name = swf_TagGetName(tag);
997 dumperror("Unknown tag:0x%03x", tag->id);
1002 name = "UNKNOWN TAG";
1005 filepos += tag->len;
1006 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
1008 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
1011 if(swf_isDefiningTag(tag)) {
1012 U16 id = swf_GetDefineID(tag);
1013 printf(" defines id %04d", id);
1015 dumperror("Id %04d is defined more than once.", id);
1018 else if(swf_isPseudoDefiningTag(tag)) {
1019 U16 id = swf_GetDefineID(tag);
1020 printf(" adds information to id %04d", id);
1022 dumperror("Id %04d is not yet defined.\n", id);
1024 else if(tag->id == ST_PLACEOBJECT) {
1025 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
1026 if(swf_GetName(tag))
1027 printf(" name \"%s\"",swf_GetName(tag));
1029 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1036 printf(" id %04d",swf_GetPlaceID(tag));
1040 printf(" at depth %04d", swf_GetDepth(tag));
1042 if(tag->id == ST_PLACEOBJECT3 && tag->data[1]&4)
1043 printf(" as bitmap");
1045 swf_SetTagPos(tag, 0);
1046 if(tag->data[0]&64) {
1048 swf_GetPlaceObject(tag, &po);
1049 printf(" (clip to %04d)", po.clipdepth);
1050 swf_PlaceObjectFree(&po);
1052 if(swf_GetName(tag))
1053 printf(" name \"%s\"",swf_GetName(tag));
1056 else if(tag->id == ST_REMOVEOBJECT) {
1057 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
1059 else if(tag->id == ST_REMOVEOBJECT2) {
1060 printf(" removes object from depth %04d", swf_GetDepth(tag));
1062 else if(tag->id == ST_FREECHARACTER) {
1063 printf(" frees object %04d", swf_GetPlaceID(tag));
1065 else if(tag->id == ST_STARTSOUND) {
1068 id = swf_GetU16(tag);
1069 flags = swf_GetU8(tag);
1071 printf(" stops sound with id %04d", id);
1073 printf(" starts sound with id %04d", id);
1075 printf(" (if not already playing)");
1081 printf(" looping %d times", swf_GetU16(tag));
1084 else if(tag->id == ST_FRAMELABEL) {
1085 int l = strlen(tag->data);
1086 printf(" \"%s\"", tag->data);
1087 if((l+1) < tag->len) {
1088 printf(" has %d extra bytes", tag->len-1-l);
1089 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1090 printf(" (ANCHOR)");
1092 if((framelabel && !issprite) ||
1093 (spriteframelabel && issprite)) {
1094 dumperror("Frame %d has more than one label",
1095 issprite?spriteframe:mainframe);
1097 if(issprite) spriteframelabel = tag->data;
1098 else framelabel = tag->data;
1100 else if(tag->id == ST_SHOWFRAME) {
1101 char*label = issprite?spriteframelabel:framelabel;
1102 int frame = issprite?spriteframe:mainframe;
1105 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1107 if(issprite) spriteframe++;
1113 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1115 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1116 timestring(frame*(256.0/(swf.frameRate+0.1))),
1117 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1120 printf(" (label \"%s\")", label);
1121 if(issprite) {spriteframe++; spriteframelabel = 0;}
1122 if(!issprite) {mainframe++; framelabel = 0;}
1125 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1126 U8 r = swf_GetU8(tag);
1127 U8 g = swf_GetU8(tag);
1128 U8 b = swf_GetU8(tag);
1129 printf(" (%02x/%02x/%02x)\n",r,g,b);
1131 else if(tag->id == ST_PROTECT) {
1133 printf(" %s\n", swf_GetString(tag));
1138 else if(tag->id == ST_CSMTEXTSETTINGS) {
1139 U16 id = swf_GetU16(tag);
1140 U8 flags = swf_GetU8(tag);
1143 printf("flashtype,");
1145 switch(((flags>>3)&7)) {
1146 case 0:printf("no grid,");break;
1147 case 1:printf("pixel grid,");break;
1148 case 2:printf("subpixel grid,");break;
1149 case 3:printf("unknown grid,");break;
1152 printf("unknown[%08x],", flags);
1153 float thickness = swf_GetFixed(tag);
1154 float sharpness = swf_GetFixed(tag);
1155 printf("s=%.2f,t=%.2f)\n", thickness, sharpness);
1158 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1159 tag->id == ST_DEFINEBITSLOSSLESS2) {
1160 handleDefineBits(tag);
1163 else if(tag->id == ST_DEFINESOUND) {
1164 handleDefineSound(tag);
1167 else if(tag->id == ST_VIDEOFRAME) {
1168 handleVideoFrame(tag, myprefix);
1171 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1172 handleVideoStream(tag, myprefix);
1175 else if(tag->id == ST_DEFINEEDITTEXT) {
1176 handleEditText(tag);
1179 else if(tag->id == ST_DEFINEMOVIE) {
1180 U16 id = swf_GetU16(tag);
1181 char*s = swf_GetString(tag);
1182 printf(" URL: %s\n", s);
1184 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1190 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1192 else if(tag->id == ST_NAMECHARACTER) {
1194 printf(" \"%s\"\n", swf_GetString(tag));
1200 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1201 SRECT r = swf_GetDefineBBox(tag);
1202 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1209 sprintf(myprefix, " %s", prefix);
1211 if(tag->id == ST_DEFINESPRITE) {
1212 sprintf(prefix, " ");
1214 dumperror("Sprite definition inside a sprite definition");
1218 spriteframelabel = 0;
1220 else if(tag->id == ST_END) {
1223 spriteframelabel = 0;
1225 dumperror("End Tag not empty");
1227 else if(tag->id == ST_EXPORTASSETS) {
1228 handleExportAssets(tag, myprefix);
1230 else if(tag->id == ST_DOACTION && action) {
1232 actions = swf_ActionGet(tag);
1233 swf_DumpActions(actions, myprefix);
1235 else if(tag->id == ST_DOINITACTION && action) {
1237 swf_GetU16(tag); // id
1238 actions = swf_ActionGet(tag);
1239 swf_DumpActions(actions, myprefix);
1241 else if(tag->id == ST_DEFINEBUTTON && action) {
1242 dumpButtonActions(tag, myprefix);
1244 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1245 dumpButton2Actions(tag, myprefix);
1247 else if(tag->id == ST_PLACEOBJECT) {
1248 handlePlaceObject(tag, myprefix);
1250 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1251 handlePlaceObject23(tag, myprefix);
1253 else if(tag->id == ST_DEFINESHAPE ||
1254 tag->id == ST_DEFINESHAPE2 ||
1255 tag->id == ST_DEFINESHAPE3 ||
1256 tag->id == ST_DEFINESHAPE4) {
1258 handleShape(tag, myprefix);
1261 if(tag->len && used) {
1262 int num = swf_GetNumUsedIDs(tag);
1266 used = (int*)malloc(sizeof(int)*num);
1267 swf_GetUsedIDs(tag, used);
1268 printf("%s%suses IDs: ", indent, prefix);
1269 for(t=0;t<num;t++) {
1271 swf_SetTagPos(tag, used[t]);
1272 id = swf_GetU16(tag);
1273 printf("%d%s", id, t<num-1?", ":"");
1275 dumperror("Id %04d is not yet defined.\n", id);
1282 if(tag->id == ST_FREECHARACTER) {
1284 swf_SetTagPos(tag, 0);
1285 id = swf_GetU16(tag);
1289 if(tag->len && hex) {
1290 hexdumpTag(tag, prefix);