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 handlePlaceObject23(TAG*tag, char*prefix)
482 int ppos[3] = {0,0,0};
483 swf_SetTagPos(tag, 0);
484 flags = swf_GetU8(tag);
485 if(tag->id == ST_PLACEOBJECT3)
486 flags2 = swf_GetU8(tag);
487 swf_GetU16(tag); //depth
490 if(flags&2) swf_GetU16(tag); //id
492 swf_GetMatrix(tag,&m);
494 ppos[0] += sprintf(pstr[0], "| Matrix ");
495 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
496 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
500 swf_GetCXForm(tag, &cx, 1);
502 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
503 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);
504 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
508 U16 ratio = swf_GetU16(tag); //ratio
510 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
511 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
512 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
516 U16 clip = swf_GetU16(tag); //clip
518 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
519 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-4d ", clip);
520 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
523 if(flags&32) { while(swf_GetU8(tag)); }
525 if(flags2&1) { // filter list
526 U8 num = swf_GetU8(tag);
527 printf("%d filters\n");
528 char*filtername[] = {"dropshadow","blur","glow","bevel","gradientglow","convolution","colormatrix","gradientbevel"};
530 U8 type = swf_GetU8(tag);
531 printf("filter %d: %02x (%s)\n", type, type<sizeof(filtername)/sizeof(filtername[0])?filtername[type]:"?");
535 if(flags2&2) { // blend mode
536 U8 blendmode = swf_GetU8(tag);
540 sprintf(name, "%-5d", blendmode);
541 for(t=0;blendModeNames[t];t++) {
543 sprintf(name, "%-5s", blendModeNames[t]);
547 ppos[0] += sprintf(pstr[0]+ppos[0], "| Blend ");
548 ppos[1] += sprintf(pstr[1]+ppos[1], "| %s ", name);
549 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
553 if(placements && ppos[0]) {
555 printf("%s %s\n", prefix, pstr[0]);
556 printf("%s %s\n", prefix, pstr[1]);
557 printf("%s %s", prefix, pstr[2]);
566 reserved = swf_GetU16(tag); // must be 0
567 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
569 printf("Unknown parameter field not zero: %04x\n", reserved);
572 printf("global flags: %04x\n", globalflags);
574 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
576 handlerflags = swf_GetU32(tag);
579 while(handlerflags) {
584 globalflags &= ~handlerflags;
585 printf("%s flags %08x ",prefix, handlerflags);
586 printhandlerflags(handlerflags);
587 length = swf_GetU32(tag);
588 printf(", %d bytes actioncode\n",length);
589 a = swf_ActionGet(tag);
590 swf_DumpActions(a,prefix);
593 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
595 if(globalflags) // should go to sterr.
596 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
598 printf(" has action code\n");
603 void handlePlaceObject(TAG*tag, char*prefix)
605 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
610 swf_SetTagPos(tag, 0);
611 id = swf_GetU16(tag);
612 depth = swf_GetU16(tag);
613 swf_GetMatrix(tag, &matrix);
614 swf_GetCXForm(tag, &cxform, 0);
616 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
617 swf_SetU16(tag2, depth);
618 swf_SetU16(tag2, id);
619 swf_SetMatrix(tag2, &matrix);
620 swf_SetCXForm(tag2, &cxform, 1);
622 handlePlaceObject23(tag2, prefix);
625 char* fillstyle2str(FILLSTYLE*style)
627 switch(style->type) {
629 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
631 case 0x10: case 0x12:
632 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
634 case 0x40: case 0x42:
635 /* TODO: display information about that bitmap */
636 sprintf(stylebuf, "BITMAPt%s %d", (style->type&2)?"n":"", style->id_bitmap);
637 /* TODO: show matrix */
639 case 0x41: case 0x43:
640 /* TODO: display information about that bitmap */
641 sprintf(stylebuf, "BITMAPc%s %d", (style->type&2)?"n":"", style->id_bitmap);
642 /* TODO: show matrix */
645 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
649 char* linestyle2str(LINESTYLE*style)
651 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
655 void handleShape(TAG*tag, char*prefix)
663 swf_ParseDefineShape(tag, &shape);
665 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
667 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
672 else printf("%s | (Neither line nor fill styles)\n", prefix);
675 printf("%s", prefix);
676 if(t < shape.numfillstyles) {
677 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
681 if(t < shape.numlinestyles) {
682 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
687 printf("%s |\n", prefix);
691 printf("%s | fill: %02d/%02d line:%02d - ",
696 if(line->type == moveTo) {
697 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
698 } else if(line->type == lineTo) {
699 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
700 } else if(line->type == splineTo) {
701 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
702 line->sx/20.0, line->sy/20.0,
703 line->x/20.0, line->y/20.0
708 printf("%s |\n", prefix);
711 void fontcallback1(void*self, U16 id,U8 * name)
715 void fontcallback2(void*self, U16 id,U8 * name)
717 swf_FontExtract(&swf,id,&fonts[fontnum]);
721 static U8 printable(U8 a)
723 if(a<32 || a==127) return '.';
726 void hexdumpTag(TAG*tag, char* prefix)
730 printf(" %s-=> ",prefix);
731 for(t=0;t<tag->len;t++) {
732 printf("%02x ", tag->data[t]);
733 ascii[t&15] = printable(tag->data[t]);
734 if((t && ((t&15)==15)) || (t==tag->len-1))
738 for(s=p-1;s<16;s++) {
742 printf(" %s\n", ascii);
744 printf(" %s\n %s-=> ",ascii,prefix);
749 void handleExportAssets(TAG*tag, char* prefix)
755 num = swf_GetU16(tag);
758 id = swf_GetU16(tag);
759 name = swf_GetString(tag);
760 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
764 void dumperror(const char* format, ...)
769 va_start(arglist, format);
770 vsprintf(buf, format, arglist);
774 printf("==== Error: %s ====\n", buf);
777 static char strbuf[800];
780 char* timestring(double f)
782 int hours = (int)(f/3600);
783 int minutes = (int)((f-hours*3600)/60);
784 int seconds = (int)((f-hours*3600-minutes*60));
785 int useconds = (int)((f-(int)f)*1000+0.5);
788 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
789 return &strbuf[bufpos];
792 int main (int argc,char ** argv)
800 char issprite = 0; // are we inside a sprite definition?
803 char* spriteframelabel = 0;
804 char* framelabel = 0;
809 memset(idtab,0,65536);
811 processargs(argc, argv);
815 fprintf(stderr, "You must supply a filename.\n");
819 f = open(filename,O_RDONLY|O_BINARY);
824 sprintf(buffer, "Couldn't open %s", filename);
828 if FAILED(swf_ReadSWF(f,&swf))
830 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
837 if(statbuf.st_size != swf.fileSize && !swf.compressed)
838 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
839 statbuf.st_size, swf.fileSize);
840 filesize = statbuf.st_size;
845 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
846 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
850 printf("-X %d", xsize);
856 printf("-Y %d", ysize);
862 printf("-r %.2f", swf.frameRate/256.0);
868 printf("-f %d", swf.frameCount);
875 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
876 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
877 if(swf.fileVersion>9) {
878 fprintf(stderr, "Fileversion>9\n");
883 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
884 "<param name=\"movie\" value=\"%s\"/>\n"
885 "<param name=\"play\" value=\"true\"/>\n"
886 "<param name=\"loop\" value=\"false\"/>\n"
887 "<param name=\"quality\" value=\"high\"/>\n"
888 "<param name=\"loop\" value=\"false\"/>\n"
889 "</object>\n\n", filename, xsize, ysize, filename);
891 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
893 //" BGCOLOR=#ffffffff\n"?
895 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
896 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
897 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
898 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
899 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
900 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
901 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
902 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
903 " TYPE=\"application/x-shockwave-flash\"\n"
904 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
906 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
907 filename, filename, xsize, ysize);
911 printf("[HEADER] File version: %d\n", swf.fileVersion);
913 printf("[HEADER] File is zlib compressed.");
914 if(filesize && swf.fileSize)
915 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
919 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
920 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
921 printf("[HEADER] Frame count: %d\n",swf.frameCount);
922 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
923 if(swf.movieSize.xmin)
924 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
927 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
928 if(swf.movieSize.ymin)
929 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
937 swf_FontEnumerate(&swf,&fontcallback1, 0);
938 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
940 swf_FontEnumerate(&swf,&fontcallback2, 0);
944 char*name = swf_TagGetName(tag);
947 dumperror("Unknown tag:0x%03x", tag->id);
952 name = "UNKNOWN TAG";
956 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
958 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
961 if(swf_isDefiningTag(tag)) {
962 U16 id = swf_GetDefineID(tag);
963 printf(" defines id %04d", id);
965 dumperror("Id %04d is defined more than once.", id);
968 else if(swf_isPseudoDefiningTag(tag)) {
969 U16 id = swf_GetDefineID(tag);
970 printf(" adds information to id %04d", id);
972 dumperror("Id %04d is not yet defined.\n", id);
974 else if(tag->id == ST_PLACEOBJECT) {
975 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
977 printf(" name \"%s\"",swf_GetName(tag));
979 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
986 printf(" id %04d",swf_GetPlaceID(tag));
990 printf(" at depth %04d", swf_GetDepth(tag));
993 printf(" as bitmap");
995 swf_SetTagPos(tag, 0);
996 if(tag->data[0]&64) {
998 swf_GetPlaceObject(tag, &po);
999 printf(" (clip to %04d)", po.clipdepth);
1000 swf_PlaceObjectFree(&po);
1002 if(swf_GetName(tag))
1003 printf(" name \"%s\"",swf_GetName(tag));
1006 else if(tag->id == ST_REMOVEOBJECT) {
1007 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
1009 else if(tag->id == ST_REMOVEOBJECT2) {
1010 printf(" removes object from depth %04d", swf_GetDepth(tag));
1012 else if(tag->id == ST_FREECHARACTER) {
1013 printf(" frees object %04d", swf_GetPlaceID(tag));
1015 else if(tag->id == ST_STARTSOUND) {
1018 id = swf_GetU16(tag);
1019 flags = swf_GetU8(tag);
1021 printf(" stops sound with id %04d", id);
1023 printf(" starts sound with id %04d", id);
1025 printf(" (if not already playing)");
1031 printf(" looping %d times", swf_GetU16(tag));
1034 else if(tag->id == ST_FRAMELABEL) {
1035 int l = strlen(tag->data);
1036 printf(" \"%s\"", tag->data);
1037 if((l+1) < tag->len) {
1038 printf(" has %d extra bytes", tag->len-1-l);
1039 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1040 printf(" (ANCHOR)");
1042 if((framelabel && !issprite) ||
1043 (spriteframelabel && issprite)) {
1044 dumperror("Frame %d has more than one label",
1045 issprite?spriteframe:mainframe);
1047 if(issprite) spriteframelabel = tag->data;
1048 else framelabel = tag->data;
1050 else if(tag->id == ST_SHOWFRAME) {
1051 char*label = issprite?spriteframelabel:framelabel;
1052 int frame = issprite?spriteframe:mainframe;
1055 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1057 if(issprite) spriteframe++;
1063 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1065 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1066 timestring(frame*(256.0/(swf.frameRate+0.1))),
1067 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1070 printf(" (label \"%s\")", label);
1071 if(issprite) {spriteframe++; spriteframelabel = 0;}
1072 if(!issprite) {mainframe++; framelabel = 0;}
1075 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1076 U8 r = swf_GetU8(tag);
1077 U8 g = swf_GetU8(tag);
1078 U8 b = swf_GetU8(tag);
1079 printf(" (%02x/%02x/%02x)\n",r,g,b);
1081 else if(tag->id == ST_PROTECT) {
1083 printf(" %s\n", swf_GetString(tag));
1088 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1089 tag->id == ST_DEFINEBITSLOSSLESS2) {
1090 handleDefineBits(tag);
1093 else if(tag->id == ST_DEFINESOUND) {
1094 handleDefineSound(tag);
1097 else if(tag->id == ST_VIDEOFRAME) {
1098 handleVideoFrame(tag, myprefix);
1101 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1102 handleVideoStream(tag, myprefix);
1105 else if(tag->id == ST_DEFINEEDITTEXT) {
1106 handleEditText(tag);
1109 else if(tag->id == ST_DEFINEMOVIE) {
1110 U16 id = swf_GetU16(tag);
1111 char*s = swf_GetString(tag);
1112 printf(" URL: %s\n", s);
1114 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1120 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1122 else if(tag->id == ST_NAMECHARACTER) {
1124 printf(" \"%s\"\n", swf_GetString(tag));
1130 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1131 SRECT r = swf_GetDefineBBox(tag);
1132 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1139 sprintf(myprefix, " %s", prefix);
1141 if(tag->id == ST_DEFINESPRITE) {
1142 sprintf(prefix, " ");
1144 dumperror("Sprite definition inside a sprite definition");
1148 spriteframelabel = 0;
1150 else if(tag->id == ST_END) {
1153 spriteframelabel = 0;
1155 dumperror("End Tag not empty");
1157 else if(tag->id == ST_EXPORTASSETS) {
1158 handleExportAssets(tag, myprefix);
1160 else if(tag->id == ST_DOACTION && action) {
1162 actions = swf_ActionGet(tag);
1163 swf_DumpActions(actions, myprefix);
1165 else if(tag->id == ST_DOINITACTION && action) {
1167 swf_GetU16(tag); // id
1168 actions = swf_ActionGet(tag);
1169 swf_DumpActions(actions, myprefix);
1171 else if(tag->id == ST_DEFINEBUTTON && action) {
1172 dumpButtonActions(tag, myprefix);
1174 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1175 dumpButton2Actions(tag, myprefix);
1177 else if(tag->id == ST_PLACEOBJECT) {
1178 handlePlaceObject(tag, myprefix);
1180 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1181 handlePlaceObject23(tag, myprefix);
1183 else if(tag->id == ST_DEFINESHAPE ||
1184 tag->id == ST_DEFINESHAPE2 ||
1185 tag->id == ST_DEFINESHAPE3) {
1187 handleShape(tag, myprefix);
1190 if(tag->len && used) {
1191 int num = swf_GetNumUsedIDs(tag);
1195 used = (int*)malloc(sizeof(int)*num);
1196 swf_GetUsedIDs(tag, used);
1197 printf("%s%suses IDs: ", indent, prefix);
1198 for(t=0;t<num;t++) {
1200 swf_SetTagPos(tag, used[t]);
1201 id = swf_GetU16(tag);
1202 printf("%d%s", id, t<num-1?", ":"");
1204 dumperror("Id %04d is not yet defined.\n", id);
1211 if(tag->id == ST_FREECHARACTER) {
1213 swf_SetTagPos(tag, 0);
1214 id = swf_GetU16(tag);
1218 if(tag->len && hex) {
1219 hexdumpTag(tag, prefix);