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;
62 static int showfonts = 0;
64 static struct options_t options[] = {
85 int args_callback_option(char*name,char*val)
87 if(!strcmp(name, "V")) {
88 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
91 else if(name[0]=='a') {
95 else if(name[0]=='p') {
99 else if(name[0]=='t') {
103 else if(name[0]=='s') {
107 else if(name[0]=='e') {
111 else if(name[0]=='c') {
115 else if(name[0]=='E') {
120 else if(name[0]=='X') {
124 else if(name[0]=='Y') {
128 else if(name[0]=='r') {
132 else if(name[0]=='f') {
136 else if(name[0]=='F') {
140 else if(name[0]=='d') {
144 else if(name[0]=='u') {
148 else if(name[0]=='b') {
152 else if(name[0]=='D') {
153 action = placements = showtext = showshapes = 1;
157 printf("Unknown option: -%s\n", name);
163 int args_callback_longoption(char*name,char*val)
165 return args_long2shortoption(options, name, val);
167 void args_callback_usage(char *name)
170 printf("Usage: %s [-atpdu] file.swf\n", name);
172 printf("-h , --help Print short help message and exit\n");
173 printf("-D , --full Show everything. Same as -atp\n");
174 printf("-V , --version Print version info and exit\n");
175 printf("-e , --html Print out html code for embedding the file\n");
176 printf("-E , --xhtml Print out xhtml code for embedding the file\n");
177 printf("-a , --action Disassemble action tags\n");
178 printf("-t , --text Show text fields (like swfstrings).\n");
179 printf("-s , --shapes Show shape coordinates/styles\n");
180 printf("-F , --fonts Show font information\n");
181 printf("-p , --placements Show placement information\n");
182 printf("-b , --bbox Print tag's bounding boxes\n");
183 printf("-X , --width Prints out a string of the form \"-X width\".\n");
184 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
185 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
186 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
187 printf("-d , --hex Print hex output of tag data, too.\n");
188 printf("-u , --used Show referred IDs for each Tag.\n");
191 int args_callback_command(char*name,char*val)
194 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
202 char* testfunc(char*str)
204 printf("%s: %s\n", what, str);
208 void dumpButton2Actions(TAG*tag, char*prefix)
214 oldTagPos = swf_GetTagPos(tag);
216 // scan DefineButton2 Record
218 swf_GetU16(tag); // Character ID
219 swf_GetU8(tag); // Flags;
221 offsetpos = swf_GetTagPos(tag); // first offset
224 while (swf_GetU8(tag)) // state -> parse ButtonRecord
225 { swf_GetU16(tag); // id
226 swf_GetU16(tag); // layer
227 swf_GetMatrix(tag,NULL); // matrix
228 swf_GetCXForm(tag,NULL,1); // cxform
235 if(tag->pos >= tag->len)
238 offsetpos = swf_GetU16(tag);
239 condition = swf_GetU16(tag); // condition
241 actions = swf_ActionGet(tag);
242 printf("%s condition %04x\n", prefix, condition);
243 swf_DumpActions(actions, prefix);
246 swf_SetTagPos(tag,oldTagPos);
250 void dumpButtonActions(TAG*tag, char*prefix)
253 swf_GetU16(tag); // id
254 while (swf_GetU8(tag)) // state -> parse ButtonRecord
255 { swf_GetU16(tag); // id
256 swf_GetU16(tag); // layer
257 swf_GetMatrix(tag,NULL); // matrix
259 actions = swf_ActionGet(tag);
260 swf_DumpActions(actions, prefix);
263 void dumpFont(TAG*tag, char*prefix)
265 SWFFONT* font = malloc(sizeof(SWFFONT));
266 memset(font, 0, sizeof(SWFFONT));
267 if(tag->id == ST_DEFINEFONT2) {
268 swf_FontExtract_DefineFont2(0, font, tag);
269 } else if(tag->id == ST_DEFINEFONT) {
270 swf_FontExtract_DefineFont(0, font, tag);
272 printf("%sCan't parse %s yet\n", prefix,swf_TagGetName(tag));
274 printf("%sID: %d\n", prefix,font->id);
275 printf("%sVersion: %d\n", prefix,font->version);
276 printf("%sname: %s\n", prefix,font->name);
277 printf("%scharacters: %d\n", prefix,font->numchars);
278 printf("%shightest mapped unicode value: %d\n", prefix,font->maxascii);
281 printf("%sascent:%.2f\n", prefix,font->layout->ascent / 20.0);
282 printf("%sdescent:%.2f\n", prefix,font->layout->descent / 20.0);
283 printf("%sleading:%.2f\n", prefix,font->layout->leading / 20.0);
284 printf("%skerning records:%d\n", prefix,font->layout->kerningcount);
286 printf("%sstyle: %d\n", prefix,font->style);
287 printf("%sencoding: %02x\n", prefix,font->encoding);
288 printf("%slanguage: %02x\n", prefix,font->language);
290 for(t=0;t<font->numchars;t++) {
291 int u = font->glyph2ascii?font->glyph2ascii[t]:-1;
292 printf("%s== Glyph %d: advance=%d encoding=%d ==\n", prefix, t, font->glyph[t].advance, u);
293 SHAPE2* shape = swf_ShapeToShape2(font->glyph[t].shape);
294 SHAPELINE*line = shape->lines;
297 if(line->type == moveTo) {
298 printf("%smoveTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
299 } else if(line->type == lineTo) {
300 printf("%slineTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
301 } else if(line->type == splineTo) {
302 printf("%ssplineTo (%.2f %.2f) %.2f %.2f\n", prefix,
303 line->sx/20.0, line->sy/20.0,
304 line->x/20.0, line->y/20.0
309 swf_Shape2Free(shape);
319 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
322 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
323 for(t=0;t<fontnum;t++)
325 if(fonts[t]->id == fontid) {
335 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
336 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
339 if(fonts[font]->glyph2ascii[glyphs[t]])
340 a = fonts[font]->glyph2ascii[glyphs[t]];
350 printf("\\x%x", (int)a);
355 void handleText(TAG*tag)
358 swf_ParseDefineText(tag,textcallback, 0);
361 void handleDefineSound(TAG*tag)
363 U16 id = swf_GetU16(tag);
364 U8 flags = swf_GetU8(tag);
365 int compression = (flags>>4)&7;
366 int rate = (flags>>2)&3;
367 int bits = flags&2?16:8;
368 int stereo = flags&1;
370 if(compression == 0) printf("Raw ");
371 else if(compression == 1) printf("ADPCM ");
372 else if(compression == 2) printf("MP3 ");
373 else if(compression == 3) printf("Raw little-endian ");
374 else if(compression == 6) printf("ASAO ");
376 if(rate == 0) printf("5.5Khz ");
377 if(rate == 1) printf("11Khz ");
378 if(rate == 2) printf("22Khz ");
379 if(rate == 3) printf("44Khz ");
380 printf("%dBit ", bits);
381 if(stereo) printf("stereo");
386 void handleDefineBits(TAG*tag)
392 id = swf_GetU16(tag);
393 mode = swf_GetU8(tag);
394 width = swf_GetU16(tag);
395 height = swf_GetU16(tag);
396 printf(" image %dx%d",width,height);
397 if(mode == 3) printf(" (8 bpp)");
398 else if(mode == 4) printf(" (16 bpp)");
399 else if(mode == 5) printf(" (32 bpp)");
400 else printf(" (? bpp)");
403 void handleEditText(TAG*tag)
408 id = swf_GetU16(tag);
411 //swf_ResetReadBits(tag);
417 flags = swf_GetBits(tag,16);
418 if(flags & ET_HASFONT) {
419 swf_GetU16(tag); //font
420 swf_GetU16(tag); //fontheight
422 if(flags & ET_HASTEXTCOLOR) {
423 swf_GetU8(tag); //rgba
428 if(flags & ET_HASMAXLENGTH) {
429 swf_GetU16(tag); //maxlength
431 if(flags & ET_HASLAYOUT) {
432 swf_GetU8(tag); //align
433 swf_GetU16(tag); //left margin
434 swf_GetU16(tag); //right margin
435 swf_GetU16(tag); //indent
436 swf_GetU16(tag); //leading
438 printf(" variable \"%s\" ", &tag->data[tag->pos]);
439 if(flags & ET_HTML) printf("(html)");
440 if(flags & ET_NOSELECT) printf("(noselect)");
441 if(flags & ET_PASSWORD) printf("(password)");
442 if(flags & ET_READONLY) printf("(readonly)");
444 if(flags & (ET_X1 | ET_X3 ))
446 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
449 while(tag->data[tag->pos++]);
450 if(flags & ET_HASTEXT)
451 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
454 void printhandlerflags(U32 handlerflags)
456 if(handlerflags&1) printf("[on load]");
457 if(handlerflags&2) printf("[enter frame]");
458 if(handlerflags&4) printf("[unload]");
459 if(handlerflags&8) printf("[mouse move]");
460 if(handlerflags&16) printf("[mouse down]");
461 if(handlerflags&32) printf("[mouse up]");
462 if(handlerflags&64) printf("[key down]");
463 if(handlerflags&128) printf("[key up]");
465 if(handlerflags&256) printf("[data]");
466 if(handlerflags&512) printf("[initialize]");
467 if(handlerflags&1024) printf("[mouse press]");
468 if(handlerflags&2048) printf("[mouse release]");
469 if(handlerflags&4096) printf("[mouse release outside]");
470 if(handlerflags&8192) printf("[mouse rollover]");
471 if(handlerflags&16384) printf("[mouse rollout]");
472 if(handlerflags&32768) printf("[mouse drag over]");
474 if(handlerflags&0x10000) printf("[mouse drag out]");
475 if(handlerflags&0x20000) printf("[key press]");
476 if(handlerflags&0x40000) printf("[construct even]");
477 if(handlerflags&0xfff80000) printf("[???]");
479 void handleVideoStream(TAG*tag, char*prefix)
481 U16 id = swf_GetU16(tag);
482 U16 frames = swf_GetU16(tag);
483 U16 width = swf_GetU16(tag);
484 U16 height = swf_GetU16(tag);
485 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
486 U8 codec = swf_GetU8(tag);
487 printf(" (%d frames, %dx%d", frames, width, height);
491 printf(" sorenson h.263)");
493 printf(" codec 0x%02x)", codec);
495 void handleVideoFrame(TAG*tag, char*prefix)
497 U32 code, version, reference, sizeflags;
498 U32 width=0, height=0;
500 U16 id = swf_GetU16(tag);
501 U16 frame = swf_GetU16(tag);
502 U8 deblock,flags, tmp, bit;
504 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
505 printf(" (frame %d) ", frame);
507 /* video packet follows */
508 code = swf_GetBits(tag, 17);
509 version = swf_GetBits(tag, 5);
510 reference = swf_GetBits(tag, 8);
512 sizeflags = swf_GetBits(tag, 3);
515 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
516 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
517 case 2: width = 352; height = 288; break;
518 case 3: width = 176; height = 144; break;
519 case 4: width = 128; height = 96; break;
520 case 5: width = 320; height = 240; break;
521 case 6: width = 160; height = 120; break;
522 case 7: width = -1; height = -1;/*reserved*/ break;
524 printf("%dx%d ", width, height);
525 type = swf_GetBits(tag, 2);
526 printf("%s", types[type]);
528 deblock = swf_GetBits(tag, 1);
530 printf(" deblock ", deblock);
531 quantizer = swf_GetBits(tag, 5);
532 printf(" quant: %d ", quantizer);
535 void dumpFilter(FILTER*filter)
537 if(filter->type == FILTERTYPE_BLUR) {
538 FILTER_BLUR*f = (FILTER_BLUR*)filter;
539 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
540 printf("passes: %d\n", f->passes);
541 } if(filter->type == FILTERTYPE_DROPSHADOW) {
542 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)filter;
543 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
544 printf("passes: %d\n", f->passes);
545 printf("angle: %f distance: %f\n", f->angle, f->distance);
546 printf("strength: %f passes: %d\n", f->strength, f->passes);
547 printf("flags: %s%s%s\n",
548 f->knockout?"knockout ":"",
549 f->composite?"composite ":"",
550 f->innershadow?"innershadow ":"");
551 } if(filter->type == FILTERTYPE_BEVEL) {
552 FILTER_BEVEL*f = (FILTER_BEVEL*)filter;
553 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
554 printf("passes: %d\n", f->passes);
555 printf("angle: %f distance: %f\n", f->angle, f->distance);
556 printf("strength: %f passes: %d\n", f->strength, f->passes);
557 printf("flags: %s%s%s%s\n",
559 f->knockout?"knockout ":"",
560 f->composite?"composite ":"",
561 f->innershadow?"innershadow ":"");
562 } if(filter->type == FILTERTYPE_GRADIENTGLOW) {
563 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)filter;
564 swf_DumpGradient(stdout, f->gradient);
565 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
566 printf("angle: %f distance: %f\n", f->angle, f->distance);
567 printf("strength: %f passes: %d\n", f->strength, f->passes);
568 printf("flags: %s%s%s%s\n",
569 f->knockout?"knockout ":"",
570 f->ontop?"ontop ":"",
571 f->composite?"composite ":"",
572 f->innershadow?"innershadow ":"");
577 void handlePlaceObject23(TAG*tag, char*prefix)
583 int ppos[3] = {0,0,0};
584 swf_SetTagPos(tag, 0);
585 flags = swf_GetU8(tag);
586 if(tag->id == ST_PLACEOBJECT3)
587 flags2 = swf_GetU8(tag);
588 swf_GetU16(tag); //depth
591 if(flags&2) swf_GetU16(tag); //id
593 swf_GetMatrix(tag,&m);
595 ppos[0] += sprintf(pstr[0], "| Matrix ");
596 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
597 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
601 swf_GetCXForm(tag, &cx, 1);
603 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
604 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);
605 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
609 U16 ratio = swf_GetU16(tag); //ratio
611 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
612 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
613 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
617 U16 clip = swf_GetU16(tag); //clip
619 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
620 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-4d ", clip);
621 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
624 if(flags&32) { while(swf_GetU8(tag)); }
626 if(flags2&1) { // filter list
627 U8 num = swf_GetU8(tag);
629 printf("\n%d filters\n", num);
630 char*filtername[] = {"dropshadow","blur","glow","bevel","gradientglow","convolution","colormatrix","gradientbevel"};
633 FILTER*filter = swf_GetFilter(tag);
639 printf("filter %d: %02x (%s)\n", t, filter->type, (filter->type<sizeof(filtername)/sizeof(filtername[0]))?filtername[filter->type]:"?");
644 if(flags2&2) { // blend mode
645 U8 blendmode = swf_GetU8(tag);
649 sprintf(name, "%-5d", blendmode);
650 for(t=0;blendModeNames[t];t++) {
652 sprintf(name, "%-5s", blendModeNames[t]);
656 ppos[0] += sprintf(pstr[0]+ppos[0], "| Blend ");
657 ppos[1] += sprintf(pstr[1]+ppos[1], "| %s ", name);
658 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
662 if(placements && ppos[0]) {
664 printf("%s %s\n", prefix, pstr[0]);
665 printf("%s %s\n", prefix, pstr[1]);
666 printf("%s %s", prefix, pstr[2]);
675 reserved = swf_GetU16(tag); // must be 0
676 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
678 printf("Unknown parameter field not zero: %04x\n", reserved);
681 printf("global flags: %04x\n", globalflags);
683 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
685 handlerflags = swf_GetU32(tag);
688 while(handlerflags) {
693 globalflags &= ~handlerflags;
694 printf("%s flags %08x ",prefix, handlerflags);
695 printhandlerflags(handlerflags);
696 length = swf_GetU32(tag);
697 printf(", %d bytes actioncode\n",length);
698 a = swf_ActionGet(tag);
699 swf_DumpActions(a,prefix);
702 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
704 if(globalflags) // should go to sterr.
705 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
707 printf(" has action code\n");
712 void handlePlaceObject(TAG*tag, char*prefix)
714 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
719 swf_SetTagPos(tag, 0);
720 id = swf_GetU16(tag);
721 depth = swf_GetU16(tag);
722 swf_GetMatrix(tag, &matrix);
723 swf_GetCXForm(tag, &cxform, 0);
725 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
726 swf_SetU16(tag2, depth);
727 swf_SetU16(tag2, id);
728 swf_SetMatrix(tag2, &matrix);
729 swf_SetCXForm(tag2, &cxform, 1);
731 handlePlaceObject23(tag2, prefix);
734 char* fillstyle2str(FILLSTYLE*style)
736 switch(style->type) {
738 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
740 case 0x10: case 0x11: case 0x12: case 0x13:
741 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
743 case 0x40: case 0x42:
744 /* TODO: display information about that bitmap */
745 sprintf(stylebuf, "BITMAPt%s %d", (style->type&2)?"n":"", style->id_bitmap);
746 /* TODO: show matrix */
748 case 0x41: case 0x43:
749 /* TODO: display information about that bitmap */
750 sprintf(stylebuf, "BITMAPc%s %d", (style->type&2)?"n":"", style->id_bitmap);
751 /* TODO: show matrix */
754 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
758 char* linestyle2str(LINESTYLE*style)
760 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
764 void handleShape(TAG*tag, char*prefix)
772 swf_ParseDefineShape(tag, &shape);
774 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
776 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
781 else printf("%s | (Neither line nor fill styles)\n", prefix);
784 printf("%s", prefix);
785 if(t < shape.numfillstyles) {
786 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
790 if(t < shape.numlinestyles) {
791 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
796 printf("%s |\n", prefix);
800 printf("%s | fill: %02d/%02d line:%02d - ",
805 if(line->type == moveTo) {
806 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
807 } else if(line->type == lineTo) {
808 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
809 } else if(line->type == splineTo) {
810 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
811 line->sx/20.0, line->sy/20.0,
812 line->x/20.0, line->y/20.0
817 printf("%s |\n", prefix);
820 void fontcallback1(void*self, U16 id,U8 * name)
824 void fontcallback2(void*self, U16 id,U8 * name)
826 swf_FontExtract(&swf,id,&fonts[fontnum]);
830 static U8 printable(U8 a)
832 if(a<32 || a==127) return '.';
835 void hexdumpTag(TAG*tag, char* prefix)
839 printf(" %s-=> ",prefix);
840 for(t=0;t<tag->len;t++) {
841 printf("%02x ", tag->data[t]);
842 ascii[t&15] = printable(tag->data[t]);
843 if((t && ((t&15)==15)) || (t==tag->len-1))
847 for(s=p-1;s<16;s++) {
851 printf(" %s\n", ascii);
853 printf(" %s\n %s-=> ",ascii,prefix);
858 void handleExportAssets(TAG*tag, char* prefix)
864 num = swf_GetU16(tag);
867 id = swf_GetU16(tag);
868 name = swf_GetString(tag);
869 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
873 void dumperror(const char* format, ...)
878 va_start(arglist, format);
879 vsprintf(buf, format, arglist);
883 printf("==== Error: %s ====\n", buf);
886 static char strbuf[800];
889 char* timestring(double f)
891 int hours = (int)(f/3600);
892 int minutes = (int)((f-hours*3600)/60);
893 int seconds = (int)((f-hours*3600-minutes*60));
894 int useconds = (int)((f-(int)f)*1000+0.5);
897 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
898 return &strbuf[bufpos];
901 int main (int argc,char ** argv)
909 char issprite = 0; // are we inside a sprite definition?
912 char* spriteframelabel = 0;
913 char* framelabel = 0;
918 memset(idtab,0,65536);
920 processargs(argc, argv);
924 fprintf(stderr, "You must supply a filename.\n");
928 f = open(filename,O_RDONLY|O_BINARY);
933 sprintf(buffer, "Couldn't open %s", filename);
937 if FAILED(swf_ReadSWF(f,&swf))
939 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
946 if(statbuf.st_size != swf.fileSize && !swf.compressed)
947 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
948 statbuf.st_size, swf.fileSize);
949 filesize = statbuf.st_size;
954 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
955 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
959 printf("-X %d", xsize);
965 printf("-Y %d", ysize);
971 printf("-r %.2f", swf.frameRate/256.0);
977 printf("-f %d", swf.frameCount);
984 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
985 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
986 if(swf.fileVersion>9) {
987 fprintf(stderr, "Fileversion>9\n");
992 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
993 "<param name=\"movie\" value=\"%s\"/>\n"
994 "<param name=\"play\" value=\"true\"/>\n"
995 "<param name=\"loop\" value=\"false\"/>\n"
996 "<param name=\"quality\" value=\"high\"/>\n"
997 "<param name=\"loop\" value=\"false\"/>\n"
998 "</object>\n\n", filename, xsize, ysize, filename);
1000 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
1002 //" BGCOLOR=#ffffffff\n"?
1004 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
1005 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
1006 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
1007 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
1008 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
1009 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
1010 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
1011 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
1012 " TYPE=\"application/x-shockwave-flash\"\n"
1013 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
1015 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
1016 filename, filename, xsize, ysize);
1020 printf("[HEADER] File version: %d\n", swf.fileVersion);
1021 if(swf.compressed) {
1022 printf("[HEADER] File is zlib compressed.");
1023 if(filesize && swf.fileSize)
1024 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
1028 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
1029 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
1030 printf("[HEADER] Frame count: %d\n",swf.frameCount);
1031 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
1032 if(swf.movieSize.xmin)
1033 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
1036 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
1037 if(swf.movieSize.ymin)
1038 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
1046 swf_FontEnumerate(&swf,&fontcallback1, 0);
1047 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
1049 swf_FontEnumerate(&swf,&fontcallback2, 0);
1053 char*name = swf_TagGetName(tag);
1056 dumperror("Unknown tag:0x%03x", tag->id);
1061 name = "UNKNOWN TAG";
1064 filepos += tag->len;
1065 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
1067 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
1070 if(swf_isDefiningTag(tag)) {
1071 U16 id = swf_GetDefineID(tag);
1072 printf(" defines id %04d", id);
1074 dumperror("Id %04d is defined more than once.", id);
1077 else if(swf_isPseudoDefiningTag(tag)) {
1078 U16 id = swf_GetDefineID(tag);
1079 printf(" adds information to id %04d", id);
1081 dumperror("Id %04d is not yet defined.\n", id);
1083 else if(tag->id == ST_PLACEOBJECT) {
1084 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
1085 if(swf_GetName(tag))
1086 printf(" name \"%s\"",swf_GetName(tag));
1088 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1095 printf(" id %04d",swf_GetPlaceID(tag));
1099 printf(" at depth %04d", swf_GetDepth(tag));
1101 if(tag->id == ST_PLACEOBJECT3 && tag->data[1]&4)
1102 printf(" as bitmap");
1104 swf_SetTagPos(tag, 0);
1105 if(tag->data[0]&64) {
1107 swf_GetPlaceObject(tag, &po);
1108 printf(" (clip to %04d)", po.clipdepth);
1109 swf_PlaceObjectFree(&po);
1111 if(swf_GetName(tag))
1112 printf(" name \"%s\"",swf_GetName(tag));
1115 else if(tag->id == ST_REMOVEOBJECT) {
1116 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
1118 else if(tag->id == ST_REMOVEOBJECT2) {
1119 printf(" removes object from depth %04d", swf_GetDepth(tag));
1121 else if(tag->id == ST_FREECHARACTER) {
1122 printf(" frees object %04d", swf_GetPlaceID(tag));
1124 else if(tag->id == ST_STARTSOUND) {
1127 id = swf_GetU16(tag);
1128 flags = swf_GetU8(tag);
1130 printf(" stops sound with id %04d", id);
1132 printf(" starts sound with id %04d", id);
1134 printf(" (if not already playing)");
1140 printf(" looping %d times", swf_GetU16(tag));
1143 else if(tag->id == ST_FRAMELABEL) {
1144 int l = strlen(tag->data);
1145 printf(" \"%s\"", tag->data);
1146 if((l+1) < tag->len) {
1147 printf(" has %d extra bytes", tag->len-1-l);
1148 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1149 printf(" (ANCHOR)");
1151 if((framelabel && !issprite) ||
1152 (spriteframelabel && issprite)) {
1153 dumperror("Frame %d has more than one label",
1154 issprite?spriteframe:mainframe);
1156 if(issprite) spriteframelabel = tag->data;
1157 else framelabel = tag->data;
1159 else if(tag->id == ST_SHOWFRAME) {
1160 char*label = issprite?spriteframelabel:framelabel;
1161 int frame = issprite?spriteframe:mainframe;
1164 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1166 if(issprite) spriteframe++;
1172 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1174 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1175 timestring(frame*(256.0/(swf.frameRate+0.1))),
1176 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1179 printf(" (label \"%s\")", label);
1180 if(issprite) {spriteframe++; spriteframelabel = 0;}
1181 if(!issprite) {mainframe++; framelabel = 0;}
1184 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1185 U8 r = swf_GetU8(tag);
1186 U8 g = swf_GetU8(tag);
1187 U8 b = swf_GetU8(tag);
1188 printf(" (%02x/%02x/%02x)\n",r,g,b);
1190 else if(tag->id == ST_PROTECT) {
1192 printf(" %s\n", swf_GetString(tag));
1197 else if(tag->id == ST_CSMTEXTSETTINGS) {
1198 U16 id = swf_GetU16(tag);
1199 U8 flags = swf_GetU8(tag);
1202 printf("flashtype,");
1204 switch(((flags>>3)&7)) {
1205 case 0:printf("no grid,");break;
1206 case 1:printf("pixel grid,");break;
1207 case 2:printf("subpixel grid,");break;
1208 case 3:printf("unknown grid,");break;
1211 printf("unknown[%08x],", flags);
1212 float thickness = swf_GetFixed(tag);
1213 float sharpness = swf_GetFixed(tag);
1214 printf("s=%.2f,t=%.2f)\n", thickness, sharpness);
1217 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1218 tag->id == ST_DEFINEBITSLOSSLESS2) {
1219 handleDefineBits(tag);
1222 else if(tag->id == ST_DEFINESOUND) {
1223 handleDefineSound(tag);
1226 else if(tag->id == ST_VIDEOFRAME) {
1227 handleVideoFrame(tag, myprefix);
1230 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1231 handleVideoStream(tag, myprefix);
1234 else if(tag->id == ST_DEFINEEDITTEXT) {
1235 handleEditText(tag);
1238 else if(tag->id == ST_DEFINEMOVIE) {
1239 U16 id = swf_GetU16(tag);
1240 char*s = swf_GetString(tag);
1241 printf(" URL: %s\n", s);
1243 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1249 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1251 else if(tag->id == ST_NAMECHARACTER || tag->id==ST_DEFINEFONTNAME) {
1253 printf(" \"%s\"\n", swf_GetString(tag));
1259 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1260 SRECT r = swf_GetDefineBBox(tag);
1261 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1268 sprintf(myprefix, " %s", prefix);
1270 if(tag->id == ST_DEFINESPRITE) {
1271 sprintf(prefix, " ");
1273 dumperror("Sprite definition inside a sprite definition");
1277 spriteframelabel = 0;
1279 else if(tag->id == ST_END) {
1282 spriteframelabel = 0;
1284 dumperror("End Tag not empty");
1286 else if(tag->id == ST_EXPORTASSETS || tag->id == ST_SYMBOLCLASS) {
1287 handleExportAssets(tag, myprefix);
1289 else if(tag->id == ST_DOACTION && action) {
1291 actions = swf_ActionGet(tag);
1292 swf_DumpActions(actions, myprefix);
1294 else if(tag->id == ST_DOINITACTION && action) {
1296 swf_GetU16(tag); // id
1297 actions = swf_ActionGet(tag);
1298 swf_DumpActions(actions, myprefix);
1300 else if(tag->id == ST_DEFINEBUTTON && action) {
1301 dumpButtonActions(tag, myprefix);
1303 else if(swf_isFontTag(tag) && showfonts) {
1304 dumpFont(tag, myprefix);
1306 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1307 dumpButton2Actions(tag, myprefix);
1309 else if(tag->id == ST_PLACEOBJECT) {
1310 handlePlaceObject(tag, myprefix);
1312 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1313 handlePlaceObject23(tag, myprefix);
1315 else if(tag->id == ST_DEFINEFONTNAME) {
1316 swf_SetTagPos(tag, 0);
1317 swf_GetU16(tag); //id
1318 swf_GetString(tag); //name
1319 char* copyright = swf_GetString(tag);
1320 printf("%s%s\n", myprefix, copyright);
1322 else if(tag->id == ST_DEFINESHAPE ||
1323 tag->id == ST_DEFINESHAPE2 ||
1324 tag->id == ST_DEFINESHAPE3 ||
1325 tag->id == ST_DEFINESHAPE4) {
1327 handleShape(tag, myprefix);
1330 if(tag->len && used) {
1331 int num = swf_GetNumUsedIDs(tag);
1335 used = (int*)malloc(sizeof(int)*num);
1336 swf_GetUsedIDs(tag, used);
1337 printf("%s%suses IDs: ", indent, prefix);
1338 for(t=0;t<num;t++) {
1340 swf_SetTagPos(tag, used[t]);
1341 id = swf_GetU16(tag);
1342 printf("%d%s", id, t<num-1?", ":"");
1344 dumperror("Id %04d is not yet defined.\n", id);
1351 if(tag->id == ST_FREECHARACTER) {
1353 swf_SetTagPos(tag, 0);
1354 id = swf_GetU16(tag);
1358 if(tag->len && hex) {
1359 hexdumpTag(tag, prefix);