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);
565 swf_SetTagPos(tag, 0);
566 id = swf_GetU16(tag);
567 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);
591 case 0x40: case 0x41:
592 /* TODO: display information about that bitmap */
593 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
596 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
600 char* linestyle2str(LINESTYLE*style)
602 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
606 void handleShape(TAG*tag, char*prefix)
614 swf_ParseDefineShape(tag, &shape);
616 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
618 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
623 else printf("%s | (Neither line nor fill styles)\n", prefix);
626 printf("%s", prefix);
627 if(t < shape.numfillstyles) {
628 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
632 if(t < shape.numlinestyles) {
633 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
638 printf("%s |\n", prefix);
642 printf("%s | fill: %02d/%02d line:%02d - ",
647 if(line->type == moveTo) {
648 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
649 } else if(line->type == lineTo) {
650 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
651 } else if(line->type == splineTo) {
652 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
653 line->sx/20.0, line->sy/20.0,
654 line->x/20.0, line->y/20.0
659 printf("%s |\n", prefix);
662 void fontcallback1(void*self, U16 id,U8 * name)
666 void fontcallback2(void*self, U16 id,U8 * name)
668 swf_FontExtract(&swf,id,&fonts[fontnum]);
672 static U8 printable(U8 a)
674 if(a<32 || a==127) return '.';
677 void hexdumpTag(TAG*tag, char* prefix)
681 printf(" %s-=> ",prefix);
682 for(t=0;t<tag->len;t++) {
683 printf("%02x ", tag->data[t]);
684 ascii[t&15] = printable(tag->data[t]);
685 if((t && ((t&15)==15)) || (t==tag->len-1))
689 for(s=p-1;s<16;s++) {
693 printf(" %s\n", ascii);
695 printf(" %s\n %s-=> ",ascii,prefix);
700 void handleExportAssets(TAG*tag, char* prefix)
706 num = swf_GetU16(tag);
709 id = swf_GetU16(tag);
710 name = swf_GetString(tag);
711 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
715 void dumperror(const char* format, ...)
720 va_start(arglist, format);
721 vsprintf(buf, format, arglist);
725 printf("==== Error: %s ====\n", buf);
728 static char strbuf[800];
731 char* timestring(double f)
733 int hours = (int)(f/3600);
734 int minutes = (int)((f-hours*3600)/60);
735 int seconds = (int)((f-hours*3600-minutes*60));
736 int useconds = (int)((f-(int)f)*1000+0.5);
739 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
740 return &strbuf[bufpos];
743 int main (int argc,char ** argv)
751 char issprite = 0; // are we inside a sprite definition?
754 char* spriteframelabel = 0;
755 char* framelabel = 0;
759 memset(idtab,0,65536);
761 processargs(argc, argv);
765 fprintf(stderr, "You must supply a filename.\n");
769 f = open(filename,O_RDONLY|O_BINARY);
774 sprintf(buffer, "Couldn't open %s", filename);
778 if FAILED(swf_ReadSWF(f,&swf))
780 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
787 if(statbuf.st_size != swf.fileSize && !swf.compressed)
788 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
789 statbuf.st_size, swf.fileSize);
790 filesize = statbuf.st_size;
795 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
796 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
800 printf("-X %d", xsize);
806 printf("-Y %d", ysize);
812 printf("-r %.2f", swf.frameRate/256.0);
818 printf("-f %d", swf.frameCount);
825 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
826 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
827 if(swf.fileVersion>9) {
828 fprintf(stderr, "Fileversion>9\n");
833 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
834 "<param name=\"movie\" value=\"%s\"/>\n"
835 "<param name=\"play\" value=\"true\"/>\n"
836 "<param name=\"loop\" value=\"false\"/>\n"
837 "<param name=\"quality\" value=\"high\"/>\n"
838 "<param name=\"loop\" value=\"false\"/>\n"
839 "</object>\n\n", filename, xsize, ysize, filename);
841 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
843 //" BGCOLOR=#ffffffff\n"?
845 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
846 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
847 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
848 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
849 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
850 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
851 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
852 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
853 " TYPE=\"application/x-shockwave-flash\"\n"
854 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
856 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
857 filename, filename, xsize, ysize);
861 printf("[HEADER] File version: %d\n", swf.fileVersion);
863 printf("[HEADER] File is zlib compressed.");
864 if(filesize && swf.fileSize)
865 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
869 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
870 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
871 printf("[HEADER] Frame count: %d\n",swf.frameCount);
872 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
873 if(swf.movieSize.xmin)
874 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
877 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
878 if(swf.movieSize.ymin)
879 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
887 swf_FontEnumerate(&swf,&fontcallback1, 0);
888 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
890 swf_FontEnumerate(&swf,&fontcallback2, 0);
894 char*name = swf_TagGetName(tag);
897 dumperror("Unknown tag:0x%03x", tag->id);
901 if(swf_TagGetName(tag)) {
902 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
904 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
907 if(tag->id == ST_FREECHARACTER) {
908 U16 id = swf_GetU16(tag);
912 if(swf_isDefiningTag(tag)) {
913 U16 id = swf_GetDefineID(tag);
914 printf(" defines id %04d", id);
916 dumperror("Id %04d is defined more than once.", id);
919 else if(swf_isPseudoDefiningTag(tag)) {
920 U16 id = swf_GetDefineID(tag);
921 printf(" adds information to id %04d", id);
923 dumperror("Id %04d is not yet defined.\n", id);
925 else if(tag->id == ST_PLACEOBJECT) {
926 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
928 printf(" name \"%s\"",swf_GetName(tag));
930 else if(tag->id == ST_PLACEOBJECT2) {
937 printf(" id %04d",swf_GetPlaceID(tag));
941 printf(" at depth %04d", swf_GetDepth(tag));
943 swf_SetTagPos(tag, 0);
944 if(tag->data[0]&64) {
946 swf_GetPlaceObject(tag, &po);
947 printf(" (clip to %04d)", po.clipdepth);
948 swf_PlaceObjectFree(&po);
951 printf(" name \"%s\"",swf_GetName(tag));
954 else if(tag->id == ST_REMOVEOBJECT) {
955 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
957 else if(tag->id == ST_REMOVEOBJECT2) {
958 printf(" removes object from depth %04d", swf_GetDepth(tag));
960 else if(tag->id == ST_FREECHARACTER) {
961 printf(" frees object %04d", swf_GetPlaceID(tag));
963 else if(tag->id == ST_STARTSOUND) {
966 id = swf_GetU16(tag);
967 flags = swf_GetU8(tag);
969 printf(" stops sound with id %04d", id);
971 printf(" starts sound with id %04d", id);
973 printf(" (if not already playing)");
979 printf(" looping %d times", swf_GetU16(tag));
982 else if(tag->id == ST_FRAMELABEL) {
983 int l = strlen(tag->data);
984 printf(" \"%s\"", tag->data);
986 printf(" has %d extra bytes", tag->len-1-l);
987 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
990 if((framelabel && !issprite) ||
991 (spriteframelabel && issprite)) {
992 dumperror("Frame %d has more than one label",
993 issprite?spriteframe:mainframe);
995 if(issprite) spriteframelabel = tag->data;
996 else framelabel = tag->data;
998 else if(tag->id == ST_SHOWFRAME) {
999 char*label = issprite?spriteframelabel:framelabel;
1000 int frame = issprite?spriteframe:mainframe;
1003 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1005 if(issprite) spriteframe++;
1011 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1013 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1014 timestring(frame*(256.0/(swf.frameRate+0.1))),
1015 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1018 printf(" (label \"%s\")", label);
1019 if(issprite) {spriteframe++; spriteframelabel = 0;}
1020 if(!issprite) {mainframe++; framelabel = 0;}
1023 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1024 U8 r = swf_GetU8(tag);
1025 U8 g = swf_GetU8(tag);
1026 U8 b = swf_GetU8(tag);
1027 printf(" (%02x/%02x/%02x)\n",r,g,b);
1029 else if(tag->id == ST_PROTECT) {
1031 printf(" %s\n", swf_GetString(tag));
1036 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1037 tag->id == ST_DEFINEBITSLOSSLESS2) {
1038 handleDefineBits(tag);
1041 else if(tag->id == ST_DEFINESOUND) {
1042 handleDefineSound(tag);
1045 else if(tag->id == ST_VIDEOFRAME) {
1046 handleVideoFrame(tag, myprefix);
1049 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1050 handleVideoStream(tag, myprefix);
1053 else if(tag->id == ST_DEFINEEDITTEXT) {
1054 handleEditText(tag);
1057 else if(tag->id == ST_DEFINEMOVIE) {
1058 U16 id = swf_GetU16(tag);
1059 char*s = swf_GetString(tag);
1060 printf(" URL: %s\n", s);
1062 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1068 else if(tag->id == ST_PLACEOBJECT2) {
1070 else if(tag->id == ST_NAMECHARACTER) {
1072 printf(" \"%s\"\n", swf_GetString(tag));
1078 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1079 SRECT r = swf_GetDefineBBox(tag);
1080 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1087 sprintf(myprefix, " %s", prefix);
1089 if(tag->id == ST_DEFINESPRITE) {
1090 sprintf(prefix, " ");
1092 dumperror("Sprite definition inside a sprite definition");
1096 spriteframelabel = 0;
1098 else if(tag->id == ST_END) {
1101 spriteframelabel = 0;
1103 dumperror("End Tag not empty");
1105 else if(tag->id == ST_EXPORTASSETS) {
1106 handleExportAssets(tag, myprefix);
1108 else if(tag->id == ST_DOACTION && action) {
1110 actions = swf_ActionGet(tag);
1111 swf_DumpActions(actions, myprefix);
1113 else if(tag->id == ST_DOINITACTION && action) {
1115 swf_GetU16(tag); // id
1116 actions = swf_ActionGet(tag);
1117 swf_DumpActions(actions, myprefix);
1119 else if(tag->id == ST_DEFINEBUTTON && action) {
1120 dumpButtonActions(tag, myprefix);
1122 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1123 dumpButton2Actions(tag, myprefix);
1125 else if(tag->id == ST_PLACEOBJECT) {
1126 handlePlaceObject(tag, myprefix);
1128 else if(tag->id == ST_PLACEOBJECT2) {
1129 handlePlaceObject2(tag, myprefix);
1131 else if(tag->id == ST_DEFINESHAPE ||
1132 tag->id == ST_DEFINESHAPE2 ||
1133 tag->id == ST_DEFINESHAPE3) {
1135 handleShape(tag, myprefix);
1138 if(tag->len && used) {
1139 int num = swf_GetNumUsedIDs(tag);
1143 used = (int*)malloc(sizeof(int)*num);
1144 swf_GetUsedIDs(tag, used);
1145 printf("%s%suses IDs: ", indent, prefix);
1146 for(t=0;t<num;t++) {
1148 swf_SetTagPos(tag, used[t]);
1149 id = swf_GetU16(tag);
1150 printf("%d%s", id, t<num-1?", ":"");
1152 dumperror("Id %04d is not yet defined.\n", id);
1159 if(tag->len && hex) {
1160 hexdumpTag(tag, prefix);