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("-a , --action Disassemble action tags\n");
171 printf("-t , --text Show text fields (like swfstrings).\n");
172 printf("-s , --shapes Show shape coordinates/styles\n");
173 printf("-p , --placements Show placement information\n");
174 printf("-b , --bbox Print tag's bounding boxes\n");
175 printf("-X , --width Prints out a string of the form \"-X width\".\n");
176 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
177 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
178 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
179 printf("-d , --hex Print hex output of tag data, too.\n");
180 printf("-u , --used Show referred IDs for each Tag.\n");
183 int args_callback_command(char*name,char*val)
186 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
194 char* testfunc(char*str)
196 printf("%s: %s\n", what, str);
200 void dumpButton2Actions(TAG*tag, char*prefix)
206 oldTagPos = swf_GetTagPos(tag);
208 // scan DefineButton2 Record
210 swf_GetU16(tag); // Character ID
211 swf_GetU8(tag); // Flags;
213 offsetpos = swf_GetTagPos(tag); // first offset
216 while (swf_GetU8(tag)) // state -> parse ButtonRecord
217 { swf_GetU16(tag); // id
218 swf_GetU16(tag); // layer
219 swf_GetMatrix(tag,NULL); // matrix
220 swf_GetCXForm(tag,NULL,1); // cxform
227 if(tag->pos >= tag->len)
230 offsetpos = swf_GetU16(tag);
231 condition = swf_GetU16(tag); // condition
233 actions = swf_ActionGet(tag);
234 printf("%s condition %04x\n", prefix, condition);
235 swf_DumpActions(actions, prefix);
238 swf_SetTagPos(tag,oldTagPos);
242 void dumpButtonActions(TAG*tag, char*prefix)
245 swf_GetU16(tag); // id
246 while (swf_GetU8(tag)) // state -> parse ButtonRecord
247 { swf_GetU16(tag); // id
248 swf_GetU16(tag); // layer
249 swf_GetMatrix(tag,NULL); // matrix
251 actions = swf_ActionGet(tag);
252 swf_DumpActions(actions, prefix);
259 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
262 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
263 for(t=0;t<fontnum;t++)
265 if(fonts[t]->id == fontid) {
275 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
276 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
279 a = fonts[font]->glyph2ascii[glyphs[t]];
286 printf("\\x%x", (int)a);
291 void handleText(TAG*tag)
294 swf_ParseDefineText(tag,textcallback, 0);
297 void handleDefineSound(TAG*tag)
299 U16 id = swf_GetU16(tag);
300 U8 flags = swf_GetU8(tag);
301 int compression = (flags>>4)&3;
302 int rate = (flags>>2)&3;
303 int bits = flags&2?16:8;
304 int stereo = flags&1;
306 if(compression == 0) printf("Raw ");
307 else if(compression == 1) printf("ADPCM ");
308 else if(compression == 2) printf("MP3 ");
310 if(rate == 0) printf("5.5Khz ");
311 if(rate == 1) printf("11Khz ");
312 if(rate == 2) printf("22Khz ");
313 if(rate == 3) printf("44Khz ");
314 printf("%dBit ", bits);
315 if(stereo) printf("stereo");
320 void handleDefineBits(TAG*tag)
326 id = swf_GetU16(tag);
327 mode = swf_GetU8(tag);
328 width = swf_GetU16(tag);
329 height = swf_GetU16(tag);
330 printf(" image %dx%d",width,height);
331 if(mode == 3) printf(" (8 bpp)");
332 else if(mode == 4) printf(" (16 bpp)");
333 else if(mode == 5) printf(" (32 bpp)");
334 else printf(" (? bpp)");
337 void handleEditText(TAG*tag)
342 id = swf_GetU16(tag);
345 //swf_ResetReadBits(tag);
351 flags = swf_GetBits(tag,16);
352 if(flags & ET_HASFONT) {
353 swf_GetU16(tag); //font
354 swf_GetU16(tag); //fontheight
356 if(flags & ET_HASTEXTCOLOR) {
357 swf_GetU8(tag); //rgba
362 if(flags & ET_HASMAXLENGTH) {
363 swf_GetU16(tag); //maxlength
365 if(flags & ET_HASLAYOUT) {
366 swf_GetU8(tag); //align
367 swf_GetU16(tag); //left margin
368 swf_GetU16(tag); //right margin
369 swf_GetU16(tag); //indent
370 swf_GetU16(tag); //leading
372 printf(" variable \"%s\" ", &tag->data[tag->pos]);
373 if(flags & ET_HTML) printf("(html)");
374 if(flags & ET_NOSELECT) printf("(noselect)");
375 if(flags & ET_PASSWORD) printf("(password)");
376 if(flags & ET_READONLY) printf("(readonly)");
378 if(flags & (ET_X1 | ET_X3 ))
380 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
383 while(tag->data[tag->pos++]);
384 if(flags & ET_HASTEXT)
385 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
388 void printhandlerflags(U32 handlerflags)
390 if(handlerflags&1) printf("[on load]");
391 if(handlerflags&2) printf("[enter frame]");
392 if(handlerflags&4) printf("[unload]");
393 if(handlerflags&8) printf("[mouse move]");
394 if(handlerflags&16) printf("[mouse down]");
395 if(handlerflags&32) printf("[mouse up]");
396 if(handlerflags&64) printf("[key down]");
397 if(handlerflags&128) printf("[key up]");
399 if(handlerflags&256) printf("[data]");
400 if(handlerflags&512) printf("[initialize]");
401 if(handlerflags&1024) printf("[mouse press]");
402 if(handlerflags&2048) printf("[mouse release]");
403 if(handlerflags&4096) printf("[mouse release outside]");
404 if(handlerflags&8192) printf("[mouse rollover]");
405 if(handlerflags&16384) printf("[mouse rollout]");
406 if(handlerflags&32768) printf("[mouse drag over]");
408 if(handlerflags&0x10000) printf("[mouse drag out]");
409 if(handlerflags&0x20000) printf("[key press]");
410 if(handlerflags&0x40000) printf("[construct even]");
411 if(handlerflags&0xfff80000) printf("[???]");
413 void handleVideoStream(TAG*tag, char*prefix)
415 U16 id = swf_GetU16(tag);
416 U16 frames = swf_GetU16(tag);
417 U16 width = swf_GetU16(tag);
418 U16 height = swf_GetU16(tag);
419 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
420 U8 codec = swf_GetU8(tag);
421 printf(" (%d frames, %dx%d", frames, width, height);
425 printf(" sorenson h.263)");
427 printf(" codec 0x%02x)", codec);
429 void handleVideoFrame(TAG*tag, char*prefix)
431 U32 code, version, reference, sizeflags;
432 U32 width=0, height=0;
434 U16 id = swf_GetU16(tag);
435 U16 frame = swf_GetU16(tag);
436 U8 deblock,flags, tmp, bit;
438 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
439 printf(" (frame %d) ", frame);
441 /* video packet follows */
442 code = swf_GetBits(tag, 17);
443 version = swf_GetBits(tag, 5);
444 reference = swf_GetBits(tag, 8);
446 sizeflags = swf_GetBits(tag, 3);
449 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
450 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
451 case 2: width = 352; height = 288; break;
452 case 3: width = 176; height = 144; break;
453 case 4: width = 128; height = 96; break;
454 case 5: width = 320; height = 240; break;
455 case 6: width = 160; height = 120; break;
456 case 7: width = -1; height = -1;/*reserved*/ break;
458 printf("%dx%d ", width, height);
459 type = swf_GetBits(tag, 2);
460 printf("%s", types[type]);
462 deblock = swf_GetBits(tag, 1);
464 printf(" deblock ", deblock);
465 quantizer = swf_GetBits(tag, 5);
466 printf(" quant: %d ", quantizer);
469 void handlePlaceObject2(TAG*tag, char*prefix)
475 int ppos[3] = {0,0,0};
476 swf_SetTagPos(tag, 0);
477 flags = swf_GetU8(tag);
478 swf_GetU16(tag); //depth
481 if(flags&2) swf_GetU16(tag); //id
483 swf_GetMatrix(tag,&m);
485 ppos[0] += sprintf(pstr[0], "| Matrix ");
486 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
487 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
491 swf_GetCXForm(tag, &cx, 1);
493 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
494 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);
495 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
499 U16 ratio = swf_GetU16(tag); //ratio
501 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
502 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
503 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
507 U16 clip = swf_GetU16(tag); //clip
509 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
510 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
511 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
514 if(flags&32) { while(swf_GetU8(tag)); }
515 if(placements && ppos[0]) {
517 printf("%s %s\n", prefix, pstr[0]);
518 printf("%s %s\n", prefix, pstr[1]);
519 printf("%s %s", prefix, pstr[2]);
528 reserved = swf_GetU16(tag); // must be 0
529 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
531 printf("Unknown parameter field not zero: %04x\n", reserved);
534 printf("global flags: %04x\n", globalflags);
536 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
538 handlerflags = swf_GetU32(tag);
541 while(handlerflags) {
546 globalflags &= ~handlerflags;
547 printf("%s flags %08x ",prefix, handlerflags);
548 printhandlerflags(handlerflags);
549 length = swf_GetU32(tag);
550 printf(", %d bytes actioncode\n",length);
551 a = swf_ActionGet(tag);
552 swf_DumpActions(a,prefix);
555 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
557 if(globalflags) // should go to sterr.
558 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
560 printf(" has action code\n");
565 void handlePlaceObject(TAG*tag, char*prefix)
567 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
572 swf_SetTagPos(tag, 0);
573 id = swf_GetU16(tag);
574 depth = swf_GetU16(tag);
575 swf_GetMatrix(tag, &matrix);
576 swf_GetCXForm(tag, &cxform, 0);
578 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
579 swf_SetU16(tag2, depth);
580 swf_SetU16(tag2, id);
581 swf_SetMatrix(tag2, &matrix);
582 swf_SetCXForm(tag2, &cxform, 1);
584 handlePlaceObject2(tag2, prefix);
587 char* fillstyle2str(FILLSTYLE*style)
589 switch(style->type) {
591 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
593 case 0x10: case 0x12:
594 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
597 /* TODO: display information about that bitmap */
598 sprintf(stylebuf, "BITMAPt %d", style->id_bitmap);
599 /* TODO: show matrix */
602 /* TODO: display information about that bitmap */
603 sprintf(stylebuf, "BITMAPc %d", style->id_bitmap);
604 /* TODO: show matrix */
607 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
611 char* linestyle2str(LINESTYLE*style)
613 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
617 void handleShape(TAG*tag, char*prefix)
625 swf_ParseDefineShape(tag, &shape);
627 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
629 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
634 else printf("%s | (Neither line nor fill styles)\n", prefix);
637 printf("%s", prefix);
638 if(t < shape.numfillstyles) {
639 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
643 if(t < shape.numlinestyles) {
644 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
649 printf("%s |\n", prefix);
653 printf("%s | fill: %02d/%02d line:%02d - ",
658 if(line->type == moveTo) {
659 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
660 } else if(line->type == lineTo) {
661 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
662 } else if(line->type == splineTo) {
663 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
664 line->sx/20.0, line->sy/20.0,
665 line->x/20.0, line->y/20.0
670 printf("%s |\n", prefix);
673 void fontcallback1(void*self, U16 id,U8 * name)
677 void fontcallback2(void*self, U16 id,U8 * name)
679 swf_FontExtract(&swf,id,&fonts[fontnum]);
683 static U8 printable(U8 a)
685 if(a<32 || a==127) return '.';
688 void hexdumpTag(TAG*tag, char* prefix)
692 printf(" %s-=> ",prefix);
693 for(t=0;t<tag->len;t++) {
694 printf("%02x ", tag->data[t]);
695 ascii[t&15] = printable(tag->data[t]);
696 if((t && ((t&15)==15)) || (t==tag->len-1))
700 for(s=p-1;s<16;s++) {
704 printf(" %s\n", ascii);
706 printf(" %s\n %s-=> ",ascii,prefix);
711 void handleExportAssets(TAG*tag, char* prefix)
717 num = swf_GetU16(tag);
720 id = swf_GetU16(tag);
721 name = swf_GetString(tag);
722 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
726 void dumperror(const char* format, ...)
731 va_start(arglist, format);
732 vsprintf(buf, format, arglist);
736 printf("==== Error: %s ====\n", buf);
739 static char strbuf[800];
742 char* timestring(double f)
744 int hours = (int)(f/3600);
745 int minutes = (int)((f-hours*3600)/60);
746 int seconds = (int)((f-hours*3600-minutes*60));
747 int useconds = (int)((f-(int)f)*1000+0.5);
750 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
751 return &strbuf[bufpos];
754 int main (int argc,char ** argv)
762 char issprite = 0; // are we inside a sprite definition?
765 char* spriteframelabel = 0;
766 char* framelabel = 0;
771 memset(idtab,0,65536);
773 processargs(argc, argv);
777 fprintf(stderr, "You must supply a filename.\n");
781 f = open(filename,O_RDONLY|O_BINARY);
786 sprintf(buffer, "Couldn't open %s", filename);
790 if FAILED(swf_ReadSWF(f,&swf))
792 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
799 if(statbuf.st_size != swf.fileSize && !swf.compressed)
800 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
801 statbuf.st_size, swf.fileSize);
802 filesize = statbuf.st_size;
807 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
808 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
812 printf("-X %d", xsize);
818 printf("-Y %d", ysize);
824 printf("-r %.2f", swf.frameRate/256.0);
830 printf("-f %d", swf.frameCount);
837 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
838 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
839 if(swf.fileVersion>9) {
840 fprintf(stderr, "Fileversion>9\n");
845 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
846 "<param name=\"movie\" value=\"%s\"/>\n"
847 "<param name=\"play\" value=\"true\"/>\n"
848 "<param name=\"loop\" value=\"false\"/>\n"
849 "<param name=\"quality\" value=\"high\"/>\n"
850 "<param name=\"loop\" value=\"false\"/>\n"
851 "</object>\n\n", filename, xsize, ysize, filename);
853 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
855 //" BGCOLOR=#ffffffff\n"?
857 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
858 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
859 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
860 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
861 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
862 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
863 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
864 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
865 " TYPE=\"application/x-shockwave-flash\"\n"
866 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
868 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
869 filename, filename, xsize, ysize);
873 printf("[HEADER] File version: %d\n", swf.fileVersion);
875 printf("[HEADER] File is zlib compressed.");
876 if(filesize && swf.fileSize)
877 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
881 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
882 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
883 printf("[HEADER] Frame count: %d\n",swf.frameCount);
884 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
885 if(swf.movieSize.xmin)
886 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
889 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
890 if(swf.movieSize.ymin)
891 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
899 swf_FontEnumerate(&swf,&fontcallback1, 0);
900 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
902 swf_FontEnumerate(&swf,&fontcallback2, 0);
906 char*name = swf_TagGetName(tag);
909 dumperror("Unknown tag:0x%03x", tag->id);
914 name = "UNKNOWN TAG";
918 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
920 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
923 if(tag->id == ST_FREECHARACTER) {
924 U16 id = swf_GetU16(tag);
928 if(swf_isDefiningTag(tag)) {
929 U16 id = swf_GetDefineID(tag);
930 printf(" defines id %04d", id);
932 dumperror("Id %04d is defined more than once.", id);
935 else if(swf_isPseudoDefiningTag(tag)) {
936 U16 id = swf_GetDefineID(tag);
937 printf(" adds information to id %04d", id);
939 dumperror("Id %04d is not yet defined.\n", id);
941 else if(tag->id == ST_PLACEOBJECT) {
942 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
944 printf(" name \"%s\"",swf_GetName(tag));
946 else if(tag->id == ST_PLACEOBJECT2) {
953 printf(" id %04d",swf_GetPlaceID(tag));
957 printf(" at depth %04d", swf_GetDepth(tag));
959 swf_SetTagPos(tag, 0);
960 if(tag->data[0]&64) {
962 swf_GetPlaceObject(tag, &po);
963 printf(" (clip to %04d)", po.clipdepth);
964 swf_PlaceObjectFree(&po);
967 printf(" name \"%s\"",swf_GetName(tag));
970 else if(tag->id == ST_REMOVEOBJECT) {
971 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
973 else if(tag->id == ST_REMOVEOBJECT2) {
974 printf(" removes object from depth %04d", swf_GetDepth(tag));
976 else if(tag->id == ST_FREECHARACTER) {
977 printf(" frees object %04d", swf_GetPlaceID(tag));
979 else if(tag->id == ST_STARTSOUND) {
982 id = swf_GetU16(tag);
983 flags = swf_GetU8(tag);
985 printf(" stops sound with id %04d", id);
987 printf(" starts sound with id %04d", id);
989 printf(" (if not already playing)");
995 printf(" looping %d times", swf_GetU16(tag));
998 else if(tag->id == ST_FRAMELABEL) {
999 int l = strlen(tag->data);
1000 printf(" \"%s\"", tag->data);
1001 if((l+1) < tag->len) {
1002 printf(" has %d extra bytes", tag->len-1-l);
1003 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1004 printf(" (ANCHOR)");
1006 if((framelabel && !issprite) ||
1007 (spriteframelabel && issprite)) {
1008 dumperror("Frame %d has more than one label",
1009 issprite?spriteframe:mainframe);
1011 if(issprite) spriteframelabel = tag->data;
1012 else framelabel = tag->data;
1014 else if(tag->id == ST_SHOWFRAME) {
1015 char*label = issprite?spriteframelabel:framelabel;
1016 int frame = issprite?spriteframe:mainframe;
1019 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1021 if(issprite) spriteframe++;
1027 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1029 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1030 timestring(frame*(256.0/(swf.frameRate+0.1))),
1031 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1034 printf(" (label \"%s\")", label);
1035 if(issprite) {spriteframe++; spriteframelabel = 0;}
1036 if(!issprite) {mainframe++; framelabel = 0;}
1039 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1040 U8 r = swf_GetU8(tag);
1041 U8 g = swf_GetU8(tag);
1042 U8 b = swf_GetU8(tag);
1043 printf(" (%02x/%02x/%02x)\n",r,g,b);
1045 else if(tag->id == ST_PROTECT) {
1047 printf(" %s\n", swf_GetString(tag));
1052 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1053 tag->id == ST_DEFINEBITSLOSSLESS2) {
1054 handleDefineBits(tag);
1057 else if(tag->id == ST_DEFINESOUND) {
1058 handleDefineSound(tag);
1061 else if(tag->id == ST_VIDEOFRAME) {
1062 handleVideoFrame(tag, myprefix);
1065 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1066 handleVideoStream(tag, myprefix);
1069 else if(tag->id == ST_DEFINEEDITTEXT) {
1070 handleEditText(tag);
1073 else if(tag->id == ST_DEFINEMOVIE) {
1074 U16 id = swf_GetU16(tag);
1075 char*s = swf_GetString(tag);
1076 printf(" URL: %s\n", s);
1078 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1084 else if(tag->id == ST_PLACEOBJECT2) {
1086 else if(tag->id == ST_NAMECHARACTER) {
1088 printf(" \"%s\"\n", swf_GetString(tag));
1094 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1095 SRECT r = swf_GetDefineBBox(tag);
1096 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1103 sprintf(myprefix, " %s", prefix);
1105 if(tag->id == ST_DEFINESPRITE) {
1106 sprintf(prefix, " ");
1108 dumperror("Sprite definition inside a sprite definition");
1112 spriteframelabel = 0;
1114 else if(tag->id == ST_END) {
1117 spriteframelabel = 0;
1119 dumperror("End Tag not empty");
1121 else if(tag->id == ST_EXPORTASSETS) {
1122 handleExportAssets(tag, myprefix);
1124 else if(tag->id == ST_DOACTION && action) {
1126 actions = swf_ActionGet(tag);
1127 swf_DumpActions(actions, myprefix);
1129 else if(tag->id == ST_DOINITACTION && action) {
1131 swf_GetU16(tag); // id
1132 actions = swf_ActionGet(tag);
1133 swf_DumpActions(actions, myprefix);
1135 else if(tag->id == ST_DEFINEBUTTON && action) {
1136 dumpButtonActions(tag, myprefix);
1138 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1139 dumpButton2Actions(tag, myprefix);
1141 else if(tag->id == ST_PLACEOBJECT) {
1142 handlePlaceObject(tag, myprefix);
1144 else if(tag->id == ST_PLACEOBJECT2) {
1145 handlePlaceObject2(tag, myprefix);
1147 else if(tag->id == ST_DEFINESHAPE ||
1148 tag->id == ST_DEFINESHAPE2 ||
1149 tag->id == ST_DEFINESHAPE3) {
1151 handleShape(tag, myprefix);
1154 if(tag->len && used) {
1155 int num = swf_GetNumUsedIDs(tag);
1159 used = (int*)malloc(sizeof(int)*num);
1160 swf_GetUsedIDs(tag, used);
1161 printf("%s%suses IDs: ", indent, prefix);
1162 for(t=0;t<num;t++) {
1164 swf_SetTagPos(tag, used[t]);
1165 id = swf_GetU16(tag);
1166 printf("%d%s", id, t<num-1?", ":"");
1168 dumperror("Id %04d is not yet defined.\n", id);
1175 if(tag->len && hex) {
1176 hexdumpTag(tag, prefix);