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;
62 static struct options_t options[] = {
82 int args_callback_option(char*name,char*val)
84 if(!strcmp(name, "V")) {
85 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
88 else if(name[0]=='a') {
92 else if(name[0]=='p') {
96 else if(name[0]=='t') {
100 else if(name[0]=='s') {
104 else if(name[0]=='e') {
108 else if(name[0]=='E') {
113 else if(name[0]=='X') {
117 else if(name[0]=='Y') {
121 else if(name[0]=='r') {
125 else if(name[0]=='f') {
129 else if(name[0]=='d') {
133 else if(name[0]=='u') {
137 else if(name[0]=='b') {
141 else if(name[0]=='D') {
142 action = placements = showtext = showshapes = 1;
146 printf("Unknown option: -%s\n", name);
152 int args_callback_longoption(char*name,char*val)
154 return args_long2shortoption(options, name, val);
156 void args_callback_usage(char *name)
159 printf("Usage: %s [-atpdu] file.swf\n", name);
161 printf("-h , --help Print short help message and exit\n");
162 printf("-D , --full Show everything. Same as -atp\n");
163 printf("-V , --version Print version info and exit\n");
164 printf("-e , --html Print out html code for embedding the file\n");
165 printf("-a , --action Disassemble action tags\n");
166 printf("-t , --text Show text fields (like swfstrings).\n");
167 printf("-s , --shapes Show shape coordinates/styles\n");
168 printf("-p , --placements Show placement information\n");
169 printf("-b , --bbox Print tag's bounding boxes\n");
170 printf("-X , --width Prints out a string of the form \"-X width\".\n");
171 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
172 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
173 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
174 printf("-d , --hex Print hex output of tag data, too.\n");
175 printf("-u , --used Show referred IDs for each Tag.\n");
178 int args_callback_command(char*name,char*val)
181 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
189 char* testfunc(char*str)
191 printf("%s: %s\n", what, str);
195 void dumpButton2Actions(TAG*tag, char*prefix)
201 oldTagPos = swf_GetTagPos(tag);
203 // scan DefineButton2 Record
205 swf_GetU16(tag); // Character ID
206 swf_GetU8(tag); // Flags;
208 offsetpos = swf_GetTagPos(tag); // first offset
211 while (swf_GetU8(tag)) // state -> parse ButtonRecord
212 { swf_GetU16(tag); // id
213 swf_GetU16(tag); // layer
214 swf_GetMatrix(tag,NULL); // matrix
215 swf_GetCXForm(tag,NULL,1); // cxform
222 if(tag->pos >= tag->len)
225 offsetpos = swf_GetU16(tag);
226 condition = swf_GetU16(tag); // condition
228 actions = swf_ActionGet(tag);
229 printf("%s condition %04x\n", prefix, condition);
230 swf_DumpActions(actions, prefix);
233 swf_SetTagPos(tag,oldTagPos);
237 void dumpButtonActions(TAG*tag, char*prefix)
240 swf_GetU16(tag); // id
241 while (swf_GetU8(tag)) // state -> parse ButtonRecord
242 { swf_GetU16(tag); // id
243 swf_GetU16(tag); // layer
244 swf_GetMatrix(tag,NULL); // matrix
246 actions = swf_ActionGet(tag);
247 swf_DumpActions(actions, prefix);
254 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
257 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
258 for(t=0;t<fontnum;t++)
260 if(fonts[t]->id == fontid) {
270 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
271 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
274 a = fonts[font]->glyph2ascii[glyphs[t]];
281 printf("\\x%x", (int)a);
286 void handleText(TAG*tag)
289 swf_ParseDefineText(tag,textcallback, 0);
292 void handleDefineSound(TAG*tag)
294 U16 id = swf_GetU16(tag);
295 U8 flags = swf_GetU8(tag);
296 int compression = (flags>>4)&3;
297 int rate = (flags>>2)&3;
298 int bits = flags&2?16:8;
299 int stereo = flags&1;
301 if(compression == 0) printf("Raw ");
302 else if(compression == 1) printf("ADPCM ");
303 else if(compression == 2) printf("MP3 ");
305 if(rate == 0) printf("5.5Khz ");
306 if(rate == 1) printf("11Khz ");
307 if(rate == 2) printf("22Khz ");
308 if(rate == 3) printf("44Khz ");
309 printf("%dBit ", bits);
310 if(stereo) printf("stereo");
315 void handleDefineBits(TAG*tag)
321 id = swf_GetU16(tag);
322 mode = swf_GetU8(tag);
323 width = swf_GetU16(tag);
324 height = swf_GetU16(tag);
325 printf(" image %dx%d",width,height);
326 if(mode == 3) printf(" (8 bpp)");
327 else if(mode == 4) printf(" (16 bpp)");
328 else if(mode == 5) printf(" (32 bpp)");
329 else printf(" (? bpp)");
332 void handleEditText(TAG*tag)
337 id = swf_GetU16(tag);
340 //swf_ResetReadBits(tag);
346 flags = swf_GetBits(tag,16);
347 if(flags & ET_HASFONT) {
348 swf_GetU16(tag); //font
349 swf_GetU16(tag); //fontheight
351 if(flags & ET_HASTEXTCOLOR) {
352 swf_GetU8(tag); //rgba
357 if(flags & ET_HASMAXLENGTH) {
358 swf_GetU16(tag); //maxlength
360 if(flags & ET_HASLAYOUT) {
361 swf_GetU8(tag); //align
362 swf_GetU16(tag); //left margin
363 swf_GetU16(tag); //right margin
364 swf_GetU16(tag); //indent
365 swf_GetU16(tag); //leading
367 printf(" variable \"%s\" ", &tag->data[tag->pos]);
368 if(flags & ET_HTML) printf("(html)");
369 if(flags & ET_NOSELECT) printf("(noselect)");
370 if(flags & ET_PASSWORD) printf("(password)");
371 if(flags & ET_READONLY) printf("(readonly)");
373 if(flags & (ET_X1 | ET_X3 ))
375 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
378 while(tag->data[tag->pos++]);
379 if(flags & ET_HASTEXT)
380 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
383 void printhandlerflags(U32 handlerflags)
385 if(handlerflags&1) printf("[on load]");
386 if(handlerflags&2) printf("[enter frame]");
387 if(handlerflags&4) printf("[unload]");
388 if(handlerflags&8) printf("[mouse move]");
389 if(handlerflags&16) printf("[mouse down]");
390 if(handlerflags&32) printf("[mouse up]");
391 if(handlerflags&64) printf("[key down]");
392 if(handlerflags&128) printf("[key up]");
394 if(handlerflags&256) printf("[data]");
395 if(handlerflags&512) printf("[initialize]");
396 if(handlerflags&1024) printf("[mouse press]");
397 if(handlerflags&2048) printf("[mouse release]");
398 if(handlerflags&4096) printf("[mouse release outside]");
399 if(handlerflags&8192) printf("[mouse rollover]");
400 if(handlerflags&16384) printf("[mouse rollout]");
401 if(handlerflags&32768) printf("[mouse drag over]");
403 if(handlerflags&0x10000) printf("[mouse drag out]");
404 if(handlerflags&0x20000) printf("[key press]");
405 if(handlerflags&0x40000) printf("[construct even]");
406 if(handlerflags&0xfff80000) printf("[???]");
408 void handleVideoStream(TAG*tag, char*prefix)
410 U16 id = swf_GetU16(tag);
411 U16 frames = swf_GetU16(tag);
412 U16 width = swf_GetU16(tag);
413 U16 height = swf_GetU16(tag);
414 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
415 U8 codec = swf_GetU8(tag);
416 printf(" (%d frames, %dx%d", frames, width, height);
420 printf(" sorenson h.263)");
422 printf(" codec 0x%02x)", codec);
424 void handleVideoFrame(TAG*tag, char*prefix)
426 U32 code, version, reference, sizeflags;
427 U32 width=0, height=0;
429 U16 id = swf_GetU16(tag);
430 U16 frame = swf_GetU16(tag);
431 U8 deblock,flags, tmp, bit;
433 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
434 printf(" (frame %d) ", frame);
436 /* video packet follows */
437 code = swf_GetBits(tag, 17);
438 version = swf_GetBits(tag, 5);
439 reference = swf_GetBits(tag, 8);
441 sizeflags = swf_GetBits(tag, 3);
444 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
445 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
446 case 2: width = 352; height = 288; break;
447 case 3: width = 176; height = 144; break;
448 case 4: width = 128; height = 96; break;
449 case 5: width = 320; height = 240; break;
450 case 6: width = 160; height = 120; break;
451 case 7: width = -1; height = -1;/*reserved*/ break;
453 printf("%dx%d ", width, height);
454 type = swf_GetBits(tag, 2);
455 printf("%s", types[type]);
457 deblock = swf_GetBits(tag, 1);
459 printf(" deblock ", deblock);
460 quantizer = swf_GetBits(tag, 5);
461 printf(" quant: %d ", quantizer);
464 void handlePlaceObject2(TAG*tag, char*prefix)
470 int ppos[3] = {0,0,0};
471 swf_SetTagPos(tag, 0);
472 flags = swf_GetU8(tag);
473 swf_GetU16(tag); //depth
476 if(flags&2) swf_GetU16(tag); //id
478 swf_GetMatrix(tag,&m);
480 ppos[0] += sprintf(pstr[0], "| Matrix ");
481 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
482 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
486 swf_GetCXForm(tag, &cx, 1);
488 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
489 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);
490 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
494 U16 ratio = swf_GetU16(tag); //ratio
496 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
497 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
498 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
502 U16 clip = swf_GetU16(tag); //clip
504 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
505 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
506 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
509 if(flags&32) { while(swf_GetU8(tag)); }
510 if(placements && ppos[0]) {
512 printf("%s %s\n", prefix, pstr[0]);
513 printf("%s %s\n", prefix, pstr[1]);
514 printf("%s %s", prefix, pstr[2]);
523 reserved = swf_GetU16(tag); // must be 0
524 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
526 printf("Unknown parameter field not zero: %04x\n", reserved);
529 printf("global flags: %04x\n", globalflags);
531 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
533 handlerflags = swf_GetU32(tag);
536 while(handlerflags) {
541 globalflags &= ~handlerflags;
542 printf("%s flags %08x ",prefix, handlerflags);
543 printhandlerflags(handlerflags);
544 length = swf_GetU32(tag);
545 printf(", %d bytes actioncode\n",length);
546 a = swf_ActionGet(tag);
547 swf_DumpActions(a,prefix);
550 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
552 if(globalflags) // should go to sterr.
553 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
555 printf(" has action code\n");
560 void handlePlaceObject(TAG*tag, char*prefix)
562 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
567 swf_SetTagPos(tag, 0);
568 id = swf_GetU16(tag);
569 depth = swf_GetU16(tag);
570 swf_GetMatrix(tag, &matrix);
571 swf_GetCXForm(tag, &cxform, 0);
573 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
574 swf_SetU16(tag2, depth);
575 swf_SetU16(tag2, id);
576 swf_SetMatrix(tag2, &matrix);
577 swf_SetCXForm(tag2, &cxform, 1);
579 handlePlaceObject2(tag2, prefix);
582 char* fillstyle2str(FILLSTYLE*style)
584 switch(style->type) {
586 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
588 case 0x10: case 0x12:
589 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
592 /* TODO: display information about that bitmap */
593 sprintf(stylebuf, "BITMAPt %d", style->id_bitmap);
594 /* TODO: show matrix */
597 /* TODO: display information about that bitmap */
598 sprintf(stylebuf, "BITMAPc %d", style->id_bitmap);
599 /* TODO: show matrix */
602 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
606 char* linestyle2str(LINESTYLE*style)
608 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
612 void handleShape(TAG*tag, char*prefix)
620 swf_ParseDefineShape(tag, &shape);
622 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
624 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
629 else printf("%s | (Neither line nor fill styles)\n", prefix);
632 printf("%s", prefix);
633 if(t < shape.numfillstyles) {
634 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
638 if(t < shape.numlinestyles) {
639 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
644 printf("%s |\n", prefix);
648 printf("%s | fill: %02d/%02d line:%02d - ",
653 if(line->type == moveTo) {
654 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
655 } else if(line->type == lineTo) {
656 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
657 } else if(line->type == splineTo) {
658 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
659 line->sx/20.0, line->sy/20.0,
660 line->x/20.0, line->y/20.0
665 printf("%s |\n", prefix);
668 void fontcallback1(void*self, U16 id,U8 * name)
672 void fontcallback2(void*self, U16 id,U8 * name)
674 swf_FontExtract(&swf,id,&fonts[fontnum]);
678 static U8 printable(U8 a)
680 if(a<32 || a==127) return '.';
683 void hexdumpTag(TAG*tag, char* prefix)
687 printf(" %s-=> ",prefix);
688 for(t=0;t<tag->len;t++) {
689 printf("%02x ", tag->data[t]);
690 ascii[t&15] = printable(tag->data[t]);
691 if((t && ((t&15)==15)) || (t==tag->len-1))
695 for(s=p-1;s<16;s++) {
699 printf(" %s\n", ascii);
701 printf(" %s\n %s-=> ",ascii,prefix);
706 void handleExportAssets(TAG*tag, char* prefix)
712 num = swf_GetU16(tag);
715 id = swf_GetU16(tag);
716 name = swf_GetString(tag);
717 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
721 void dumperror(const char* format, ...)
726 va_start(arglist, format);
727 vsprintf(buf, format, arglist);
731 printf("==== Error: %s ====\n", buf);
734 static char strbuf[800];
737 char* timestring(double f)
739 int hours = (int)(f/3600);
740 int minutes = (int)((f-hours*3600)/60);
741 int seconds = (int)((f-hours*3600-minutes*60));
742 int useconds = (int)((f-(int)f)*1000+0.5);
745 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
746 return &strbuf[bufpos];
749 int main (int argc,char ** argv)
757 char issprite = 0; // are we inside a sprite definition?
760 char* spriteframelabel = 0;
761 char* framelabel = 0;
765 memset(idtab,0,65536);
767 processargs(argc, argv);
771 fprintf(stderr, "You must supply a filename.\n");
775 f = open(filename,O_RDONLY|O_BINARY);
780 sprintf(buffer, "Couldn't open %s", filename);
784 if FAILED(swf_ReadSWF(f,&swf))
786 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
793 if(statbuf.st_size != swf.fileSize && !swf.compressed)
794 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
795 statbuf.st_size, swf.fileSize);
796 filesize = statbuf.st_size;
801 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
802 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
806 printf("-X %d", xsize);
812 printf("-Y %d", ysize);
818 printf("-r %.2f", swf.frameRate/256.0);
824 printf("-f %d", swf.frameCount);
831 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
832 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
833 if(swf.fileVersion>9) {
834 fprintf(stderr, "Fileversion>9\n");
839 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
840 "<param name=\"movie\" value=\"%s\"/>\n"
841 "<param name=\"play\" value=\"true\"/>\n"
842 "<param name=\"loop\" value=\"false\"/>\n"
843 "<param name=\"quality\" value=\"high\"/>\n"
844 "<param name=\"loop\" value=\"false\"/>\n"
845 "</object>\n\n", filename, xsize, ysize, filename);
847 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
849 //" BGCOLOR=#ffffffff\n"?
851 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
852 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
853 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
854 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
855 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
856 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
857 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
858 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
859 " TYPE=\"application/x-shockwave-flash\"\n"
860 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
862 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
863 filename, filename, xsize, ysize);
867 printf("[HEADER] File version: %d\n", swf.fileVersion);
869 printf("[HEADER] File is zlib compressed.");
870 if(filesize && swf.fileSize)
871 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
875 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
876 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
877 printf("[HEADER] Frame count: %d\n",swf.frameCount);
878 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
879 if(swf.movieSize.xmin)
880 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
883 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
884 if(swf.movieSize.ymin)
885 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
893 swf_FontEnumerate(&swf,&fontcallback1, 0);
894 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
896 swf_FontEnumerate(&swf,&fontcallback2, 0);
900 char*name = swf_TagGetName(tag);
903 dumperror("Unknown tag:0x%03x", tag->id);
907 if(swf_TagGetName(tag)) {
908 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
910 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
913 if(tag->id == ST_FREECHARACTER) {
914 U16 id = swf_GetU16(tag);
918 if(swf_isDefiningTag(tag)) {
919 U16 id = swf_GetDefineID(tag);
920 printf(" defines id %04d", id);
922 dumperror("Id %04d is defined more than once.", id);
925 else if(swf_isPseudoDefiningTag(tag)) {
926 U16 id = swf_GetDefineID(tag);
927 printf(" adds information to id %04d", id);
929 dumperror("Id %04d is not yet defined.\n", id);
931 else if(tag->id == ST_PLACEOBJECT) {
932 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
934 printf(" name \"%s\"",swf_GetName(tag));
936 else if(tag->id == ST_PLACEOBJECT2) {
943 printf(" id %04d",swf_GetPlaceID(tag));
947 printf(" at depth %04d", swf_GetDepth(tag));
949 swf_SetTagPos(tag, 0);
950 if(tag->data[0]&64) {
952 swf_GetPlaceObject(tag, &po);
953 printf(" (clip to %04d)", po.clipdepth);
954 swf_PlaceObjectFree(&po);
957 printf(" name \"%s\"",swf_GetName(tag));
960 else if(tag->id == ST_REMOVEOBJECT) {
961 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
963 else if(tag->id == ST_REMOVEOBJECT2) {
964 printf(" removes object from depth %04d", swf_GetDepth(tag));
966 else if(tag->id == ST_FREECHARACTER) {
967 printf(" frees object %04d", swf_GetPlaceID(tag));
969 else if(tag->id == ST_STARTSOUND) {
972 id = swf_GetU16(tag);
973 flags = swf_GetU8(tag);
975 printf(" stops sound with id %04d", id);
977 printf(" starts sound with id %04d", id);
979 printf(" (if not already playing)");
985 printf(" looping %d times", swf_GetU16(tag));
988 else if(tag->id == ST_FRAMELABEL) {
989 int l = strlen(tag->data);
990 printf(" \"%s\"", tag->data);
991 if((l+1) < tag->len) {
992 printf(" has %d extra bytes", tag->len-1-l);
993 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
996 if((framelabel && !issprite) ||
997 (spriteframelabel && issprite)) {
998 dumperror("Frame %d has more than one label",
999 issprite?spriteframe:mainframe);
1001 if(issprite) spriteframelabel = tag->data;
1002 else framelabel = tag->data;
1004 else if(tag->id == ST_SHOWFRAME) {
1005 char*label = issprite?spriteframelabel:framelabel;
1006 int frame = issprite?spriteframe:mainframe;
1009 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1011 if(issprite) spriteframe++;
1017 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1019 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1020 timestring(frame*(256.0/(swf.frameRate+0.1))),
1021 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1024 printf(" (label \"%s\")", label);
1025 if(issprite) {spriteframe++; spriteframelabel = 0;}
1026 if(!issprite) {mainframe++; framelabel = 0;}
1029 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1030 U8 r = swf_GetU8(tag);
1031 U8 g = swf_GetU8(tag);
1032 U8 b = swf_GetU8(tag);
1033 printf(" (%02x/%02x/%02x)\n",r,g,b);
1035 else if(tag->id == ST_PROTECT) {
1037 printf(" %s\n", swf_GetString(tag));
1042 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1043 tag->id == ST_DEFINEBITSLOSSLESS2) {
1044 handleDefineBits(tag);
1047 else if(tag->id == ST_DEFINESOUND) {
1048 handleDefineSound(tag);
1051 else if(tag->id == ST_VIDEOFRAME) {
1052 handleVideoFrame(tag, myprefix);
1055 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1056 handleVideoStream(tag, myprefix);
1059 else if(tag->id == ST_DEFINEEDITTEXT) {
1060 handleEditText(tag);
1063 else if(tag->id == ST_DEFINEMOVIE) {
1064 U16 id = swf_GetU16(tag);
1065 char*s = swf_GetString(tag);
1066 printf(" URL: %s\n", s);
1068 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1074 else if(tag->id == ST_PLACEOBJECT2) {
1076 else if(tag->id == ST_NAMECHARACTER) {
1078 printf(" \"%s\"\n", swf_GetString(tag));
1084 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1085 SRECT r = swf_GetDefineBBox(tag);
1086 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1093 sprintf(myprefix, " %s", prefix);
1095 if(tag->id == ST_DEFINESPRITE) {
1096 sprintf(prefix, " ");
1098 dumperror("Sprite definition inside a sprite definition");
1102 spriteframelabel = 0;
1104 else if(tag->id == ST_END) {
1107 spriteframelabel = 0;
1109 dumperror("End Tag not empty");
1111 else if(tag->id == ST_EXPORTASSETS) {
1112 handleExportAssets(tag, myprefix);
1114 else if(tag->id == ST_DOACTION && action) {
1116 actions = swf_ActionGet(tag);
1117 swf_DumpActions(actions, myprefix);
1119 else if(tag->id == ST_DOINITACTION && action) {
1121 swf_GetU16(tag); // id
1122 actions = swf_ActionGet(tag);
1123 swf_DumpActions(actions, myprefix);
1125 else if(tag->id == ST_DEFINEBUTTON && action) {
1126 dumpButtonActions(tag, myprefix);
1128 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1129 dumpButton2Actions(tag, myprefix);
1131 else if(tag->id == ST_PLACEOBJECT) {
1132 handlePlaceObject(tag, myprefix);
1134 else if(tag->id == ST_PLACEOBJECT2) {
1135 handlePlaceObject2(tag, myprefix);
1137 else if(tag->id == ST_DEFINESHAPE ||
1138 tag->id == ST_DEFINESHAPE2 ||
1139 tag->id == ST_DEFINESHAPE3) {
1141 handleShape(tag, myprefix);
1144 if(tag->len && used) {
1145 int num = swf_GetNumUsedIDs(tag);
1149 used = (int*)malloc(sizeof(int)*num);
1150 swf_GetUsedIDs(tag, used);
1151 printf("%s%suses IDs: ", indent, prefix);
1152 for(t=0;t<num;t++) {
1154 swf_SetTagPos(tag, used[t]);
1155 id = swf_GetU16(tag);
1156 printf("%d%s", id, t<num-1?", ":"");
1158 dumperror("Id %04d is not yet defined.\n", id);
1165 if(tag->len && hex) {
1166 hexdumpTag(tag, prefix);