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;
55 static int showtext = 0;
56 static int showshapes = 0;
60 static struct options_t options[] = {
78 int args_callback_option(char*name,char*val)
80 if(!strcmp(name, "V")) {
81 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
84 else if(name[0]=='a') {
88 else if(name[0]=='p') {
92 else if(name[0]=='t') {
96 else if(name[0]=='s') {
100 else if(name[0]=='e') {
104 else if(name[0]=='X') {
108 else if(name[0]=='Y') {
112 else if(name[0]=='r') {
116 else if(name[0]=='f') {
120 else if(name[0]=='d') {
124 else if(name[0]=='u') {
128 else if(name[0]=='D') {
129 action = placements = showtext = showshapes = 1;
133 printf("Unknown option: -%s\n", name);
139 int args_callback_longoption(char*name,char*val)
141 return args_long2shortoption(options, name, val);
143 void args_callback_usage(char *name)
146 printf("Usage: %s [-atpdu] file.swf\n", name);
148 printf("-h , --help Print short help message and exit\n");
149 printf("-D , --full Show everything. Same as -atp\n");
150 printf("-V , --version Print version info and exit\n");
151 printf("-e , --html Print out html code for embedding the file\n");
152 printf("-a , --action Disassemble action tags\n");
153 printf("-t , --text Show text fields (like swfstrings).\n");
154 printf("-s , --shapes Show shape coordinates/styles\n");
155 printf("-p , --placements Show placement information\n");
156 printf("-X , --width Prints out a string of the form \"-X width\".\n");
157 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
158 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
159 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
160 printf("-d , --hex Print hex output of tag data, too.\n");
161 printf("-u , --used Show referred IDs for each Tag.\n");
164 int args_callback_command(char*name,char*val)
167 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
175 char* testfunc(char*str)
177 printf("%s: %s\n", what, str);
181 void dumpButton2Actions(TAG*tag, char*prefix)
187 oldTagPos = swf_GetTagPos(tag);
189 // scan DefineButton2 Record
191 swf_GetU16(tag); // Character ID
192 swf_GetU8(tag); // Flags;
194 offsetpos = swf_GetTagPos(tag); // first offset
197 while (swf_GetU8(tag)) // state -> parse ButtonRecord
198 { swf_GetU16(tag); // id
199 swf_GetU16(tag); // layer
200 swf_GetMatrix(tag,NULL); // matrix
201 swf_GetCXForm(tag,NULL,1); // cxform
208 if(tag->pos >= tag->len)
211 offsetpos = swf_GetU16(tag);
212 condition = swf_GetU16(tag); // condition
214 actions = swf_ActionGet(tag);
215 printf("%s condition %04x\n", prefix, condition);
216 swf_DumpActions(actions, prefix);
219 swf_SetTagPos(tag,oldTagPos);
223 void dumpButtonActions(TAG*tag, char*prefix)
226 swf_GetU16(tag); // id
227 while (swf_GetU8(tag)) // state -> parse ButtonRecord
228 { swf_GetU16(tag); // id
229 swf_GetU16(tag); // layer
230 swf_GetMatrix(tag,NULL); // matrix
232 actions = swf_ActionGet(tag);
233 swf_DumpActions(actions, prefix);
236 #define ET_HASTEXT 32768
237 #define ET_WORDWRAP 16384
238 #define ET_MULTILINE 8192
239 #define ET_PASSWORD 4096
240 #define ET_READONLY 2048
241 #define ET_HASTEXTCOLOR 1024
242 #define ET_HASMAXLENGTH 512
243 #define ET_HASFONT 256
246 #define ET_HASLAYOUT 32
247 #define ET_NOSELECT 16
251 #define ET_USEOUTLINES 1
257 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
260 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
261 for(t=0;t<fontnum;t++)
263 if(fonts[t]->id == fontid) {
273 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
274 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
277 a = fonts[font]->glyph2ascii[glyphs[t]];
284 printf("\\x%x", (int)a);
289 void handleText(TAG*tag)
292 swf_ParseDefineText(tag,textcallback, 0);
295 void handleDefineSound(TAG*tag)
297 U16 id = swf_GetU16(tag);
298 U8 flags = swf_GetU8(tag);
299 int compression = (flags>>4)&3;
300 int rate = (flags>>2)&3;
301 int bits = flags&2?16:8;
302 int stereo = flags&1;
304 if(compression == 0) printf("Raw ");
305 else if(compression == 1) printf("ADPCM ");
306 else if(compression == 2) printf("MP3 ");
308 if(rate == 0) printf("5.5Khz ");
309 if(rate == 1) printf("11Khz ");
310 if(rate == 2) printf("22Khz ");
311 if(rate == 3) printf("44Khz ");
312 printf("%dBit ", bits);
313 if(stereo) printf("stereo");
318 void handleDefineBits(TAG*tag)
324 id = swf_GetU16(tag);
325 mode = swf_GetU8(tag);
326 width = swf_GetU16(tag);
327 height = swf_GetU16(tag);
328 printf(" image %dx%d",width,height);
329 if(mode == 3) printf(" (8 bpp)");
330 else if(mode == 4) printf(" (16 bpp)");
331 else if(mode == 5) printf(" (32 bpp)");
332 else printf(" (? bpp)");
335 void handleEditText(TAG*tag)
340 id = swf_GetU16(tag);
342 //swf_ResetReadBits(tag);
347 flags = swf_GetBits(tag,16);
348 if(flags & ET_HASFONT) {
349 swf_GetU16(tag); //font
350 swf_GetU16(tag); //fontheight
352 if(flags & ET_HASTEXTCOLOR) {
353 swf_GetU8(tag); //rgba
358 if(flags & ET_HASMAXLENGTH) {
359 swf_GetU16(tag); //maxlength
361 if(flags & ET_HASLAYOUT) {
362 swf_GetU8(tag); //align
363 swf_GetU16(tag); //left margin
364 swf_GetU16(tag); //right margin
365 swf_GetU16(tag); //indent
366 swf_GetU16(tag); //leading
368 printf(" variable \"%s\"", &tag->data[tag->pos]);
370 if(flags & (ET_X1 | ET_X2 | ET_X3 | ET_X0))
372 printf(" undefined flags: %d%d%d%d",
379 while(tag->data[tag->pos++]);
380 if(flags & ET_HASTEXT)
381 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
384 void printhandlerflags(U32 handlerflags)
386 if(handlerflags&1) printf("[on load]");
387 if(handlerflags&2) printf("[enter frame]");
388 if(handlerflags&4) printf("[unload]");
389 if(handlerflags&8) printf("[mouse move]");
390 if(handlerflags&16) printf("[mouse down]");
391 if(handlerflags&32) printf("[mouse up]");
392 if(handlerflags&64) printf("[key down]");
393 if(handlerflags&128) printf("[key up]");
395 if(handlerflags&256) printf("[data]");
396 if(handlerflags&512) printf("[initialize]");
397 if(handlerflags&1024) printf("[mouse press]");
398 if(handlerflags&2048) printf("[mouse release]");
399 if(handlerflags&4096) printf("[mouse release outside]");
400 if(handlerflags&8192) printf("[mouse rollover]");
401 if(handlerflags&16384) printf("[mouse rollout]");
402 if(handlerflags&32768) printf("[mouse drag over]");
404 if(handlerflags&0x10000) printf("[mouse drag out]");
405 if(handlerflags&0x20000) printf("[key press]");
406 if(handlerflags&0x40000) printf("[construct even]");
407 if(handlerflags&0xfff80000) printf("[???]");
409 void handleVideoStream(TAG*tag, char*prefix)
411 U16 id = swf_GetU16(tag);
412 U16 frames = swf_GetU16(tag);
413 U16 width = swf_GetU16(tag);
414 U16 height = swf_GetU16(tag);
415 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
416 U8 codec = swf_GetU8(tag);
417 printf(" (%d frames, %dx%d", frames, width, height);
421 printf(" sorenson h.263)");
423 printf(" codec 0x%02x)", codec);
425 void handleVideoFrame(TAG*tag, char*prefix)
427 U32 code, version, reference, sizeflags;
428 U32 width=0, height=0;
430 U16 id = swf_GetU16(tag);
431 U16 frame = swf_GetU16(tag);
432 U8 deblock,flags, tmp, bit;
434 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
435 printf(" (frame %d) ", frame);
437 /* video packet follows */
438 code = swf_GetBits(tag, 17);
439 version = swf_GetBits(tag, 5);
440 reference = swf_GetBits(tag, 8);
442 sizeflags = swf_GetBits(tag, 3);
445 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
446 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
447 case 2: width = 352; height = 288; break;
448 case 3: width = 176; height = 144; break;
449 case 4: width = 128; height = 96; break;
450 case 5: width = 320; height = 240; break;
451 case 6: width = 160; height = 120; break;
452 case 7: width = -1; height = -1;/*reserved*/ break;
454 printf("%dx%d ", width, height);
455 type = swf_GetBits(tag, 2);
456 printf("%s", types[type]);
458 deblock = swf_GetBits(tag, 1);
460 printf(" deblock ", deblock);
461 quantizer = swf_GetBits(tag, 5);
462 printf(" quant: %d ", quantizer);
465 void handlePlaceObject2(TAG*tag, char*prefix)
467 U8 flags = swf_GetU8(tag);
471 int ppos[3] = {0,0,0};
472 swf_GetU16(tag); //depth
475 if(flags&2) swf_GetU16(tag); //id
477 swf_GetMatrix(tag,&m);
479 ppos[0] += sprintf(pstr[0], "| Matrix ");
480 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
481 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
485 swf_GetCXForm(tag, &cx, 1);
487 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
488 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);
489 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
493 U16 ratio = swf_GetU16(tag); //ratio
495 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
496 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
497 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
501 U16 clip = swf_GetU16(tag); //clip
503 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
504 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
505 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
508 if(flags&32) { while(swf_GetU8(tag)); }
509 if(placements && ppos[0]) {
511 printf("%s %s\n", prefix, pstr[0]);
512 printf("%s %s\n", prefix, pstr[1]);
513 printf("%s %s", prefix, pstr[2]);
522 reserved = swf_GetU16(tag); // must be 0
523 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
525 printf("Unknown parameter field not zero: %04x\n", reserved);
528 printf("global flags: %04x\n", globalflags);
530 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
532 handlerflags = swf_GetU32(tag);
535 while(handlerflags) {
540 globalflags &= ~handlerflags;
541 printf("%s flags %08x ",prefix, handlerflags);
542 printhandlerflags(handlerflags);
543 length = swf_GetU32(tag);
544 printf(", %d bytes actioncode\n",length);
545 a = swf_ActionGet(tag);
546 swf_DumpActions(a,prefix);
549 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
551 if(globalflags) // should go to sterr.
552 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
554 printf(" has action code\n");
559 void handlePlaceObject(TAG*tag, char*prefix)
561 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
563 U16 id = swf_GetU16(tag);
564 U16 depth = swf_GetU16(tag);
567 swf_GetMatrix(tag, &matrix);
568 swf_GetCXForm(tag, &cxform, 0);
571 swf_SetU16(tag2, depth);
572 swf_SetMatrix(tag2, &matrix);
573 swf_SetCXForm(tag2, &cxform, 1);
575 handlePlaceObject2(tag2, prefix);
578 char* fillstyle2str(FILLSTYLE*style)
580 switch(style->type) {
582 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
584 case 0x10: case 0x12:
585 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
587 case 0x40: case 0x41:
588 /* TODO: display information about that bitmap */
589 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
592 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
596 char* linestyle2str(LINESTYLE*style)
598 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
602 void handleShape(TAG*tag, char*prefix)
610 swf_ParseDefineShape(tag, &shape);
612 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
614 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
619 else printf("%s | (Neither line nor fill styles)\n", prefix);
622 printf("%s", prefix);
623 if(t < shape.numfillstyles) {
624 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
628 if(t < shape.numlinestyles) {
629 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
634 printf("%s |\n", prefix);
638 printf("%s | fill: %02d/%02d line:%02d - ",
643 if(line->type == moveTo) {
644 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
645 } else if(line->type == lineTo) {
646 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
647 } else if(line->type == splineTo) {
648 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
649 line->sx/20.0, line->sy/20.0,
650 line->x/20.0, line->y/20.0
655 printf("%s |\n", prefix);
658 void fontcallback1(U16 id,U8 * name)
662 void fontcallback2(U16 id,U8 * name)
664 swf_FontExtract(&swf,id,&fonts[fontnum]);
668 static U8 printable(U8 a)
670 if(a<32 || a==127) return '.';
673 void hexdumpTag(TAG*tag, char* prefix)
677 printf(" %s-=> ",prefix);
678 for(t=0;t<tag->len;t++) {
679 printf("%02x ", tag->data[t]);
680 ascii[t&15] = printable(tag->data[t]);
681 if((t && ((t&15)==15)) || (t==tag->len-1))
685 for(s=p-1;s<16;s++) {
689 printf(" %s\n", ascii);
691 printf(" %s\n %s-=> ",ascii,prefix);
696 void handleExportAssets(TAG*tag, char* prefix)
702 num = swf_GetU16(tag);
705 id = swf_GetU16(tag);
706 name = swf_GetString(tag);
707 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
711 void dumperror(const char* format, ...)
716 va_start(arglist, format);
717 vsprintf(buf, format, arglist);
721 printf("==== Error: %s ====\n", buf);
724 static char strbuf[800];
727 char* timestring(double f)
729 int hours = (int)(f/3600);
730 int minutes = (int)((f-hours*3600)/60);
731 int seconds = (int)((f-hours*3600-minutes*60));
732 int useconds = (int)((f-(int)f)*1000+0.5);
735 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
736 return &strbuf[bufpos];
739 int main (int argc,char ** argv)
747 char issprite = 0; // are we inside a sprite definition?
750 char* spriteframelabel = 0;
751 char* framelabel = 0;
755 memset(idtab,0,65536);
757 processargs(argc, argv);
761 fprintf(stderr, "You must supply a filename.\n");
765 f = open(filename,O_RDONLY|O_BINARY);
770 sprintf(buffer, "Couldn't open %s", filename);
774 if FAILED(swf_ReadSWF(f,&swf))
776 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
783 if(statbuf.st_size != swf.fileSize && !swf.compressed)
784 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
785 statbuf.st_size, swf.fileSize);
786 filesize = statbuf.st_size;
791 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
792 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
796 printf("-X %d", xsize);
802 printf("-Y %d", ysize);
808 printf("-r %.2f", swf.frameRate/256.0);
814 printf("-f %d", swf.frameCount);
821 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
822 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
823 if(swf.fileVersion>9) {
824 fprintf(stderr, "Fileversion>9\n");
827 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
829 //" BGCOLOR=#ffffffff\n"?
831 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
832 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
833 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
834 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
835 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
836 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
837 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
838 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
839 " TYPE=\"application/x-shockwave-flash\"\n"
840 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
842 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
843 filename, filename, xsize, ysize);
846 printf("[HEADER] File version: %d\n", swf.fileVersion);
848 printf("[HEADER] File is zlib compressed.");
849 if(filesize && swf.fileSize)
850 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
854 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
855 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
856 printf("[HEADER] Frame count: %d\n",swf.frameCount);
857 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
858 if(swf.movieSize.xmin)
859 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
862 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
863 if(swf.movieSize.ymin)
864 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
872 swf_FontEnumerate(&swf,&fontcallback1);
873 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
875 swf_FontEnumerate(&swf,&fontcallback2);
879 char*name = swf_TagGetName(tag);
882 dumperror("Unknown tag:0x%03x", tag->id);
886 if(swf_TagGetName(tag)) {
887 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
889 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
892 if(tag->id == ST_FREECHARACTER) {
893 U16 id = swf_GetU16(tag);
897 if(swf_isDefiningTag(tag)) {
898 U16 id = swf_GetDefineID(tag);
899 printf(" defines id %04d", id);
901 dumperror("Id %04d is defined more than once.", id);
904 else if(swf_isPseudoDefiningTag(tag)) {
905 U16 id = swf_GetDefineID(tag);
906 printf(" adds information to id %04d", id);
908 dumperror("Id %04d is not yet defined.\n", id);
910 else if(tag->id == ST_PLACEOBJECT) {
911 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
913 printf(" name \"%s\"",swf_GetName(tag));
915 else if(tag->id == ST_PLACEOBJECT2) {
922 printf(" id %04d",swf_GetPlaceID(tag));
926 printf(" at depth %04d", swf_GetDepth(tag));
928 printf(" name \"%s\"",swf_GetName(tag));
930 else if(tag->id == ST_REMOVEOBJECT) {
931 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
933 else if(tag->id == ST_REMOVEOBJECT2) {
934 printf(" removes object from depth %04d", swf_GetDepth(tag));
936 else if(tag->id == ST_FREECHARACTER) {
937 printf(" frees object %04d", swf_GetPlaceID(tag));
939 else if(tag->id == ST_STARTSOUND) {
942 id = swf_GetU16(tag);
943 flags = swf_GetU8(tag);
945 printf(" stops sound with id %04d", id);
947 printf(" starts sound with id %04d", id);
949 printf(" (if not already playing)");
955 printf(" looping %d times", swf_GetU16(tag));
958 else if(tag->id == ST_FRAMELABEL) {
959 int l = strlen(tag->data);
960 printf(" \"%s\"", tag->data);
962 printf(" has %d extra bytes", tag->len-1-l);
963 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
966 if((framelabel && !issprite) ||
967 (spriteframelabel && issprite)) {
968 dumperror("Frame %d has more than one label",
969 issprite?spriteframe:mainframe);
971 if(issprite) spriteframelabel = tag->data;
972 else framelabel = tag->data;
974 else if(tag->id == ST_SHOWFRAME) {
975 char*label = issprite?spriteframelabel:framelabel;
976 int frame = issprite?spriteframe:mainframe;
979 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
981 if(issprite) spriteframe++;
987 printf(" %d (%s)", frame, timestring(frame*(256.0/(swf.frameRate+0.1))));
989 printf(" %d-%d (%s-%s)", frame, nframe,
990 timestring(frame*(256.0/(swf.frameRate+0.1))),
991 timestring(nframe*(256.0/(swf.frameRate+0.1)))
994 printf(" (label \"%s\")", label);
995 if(issprite) {spriteframe++; spriteframelabel = 0;}
996 if(!issprite) {mainframe++; framelabel = 0;}
999 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1000 U8 r = swf_GetU8(tag);
1001 U8 g = swf_GetU8(tag);
1002 U8 b = swf_GetU8(tag);
1003 printf(" (%02x/%02x/%02x)\n",r,g,b);
1005 else if(tag->id == ST_PROTECT) {
1007 printf(" %s\n", swf_GetString(tag));
1012 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1013 tag->id == ST_DEFINEBITSLOSSLESS2) {
1014 handleDefineBits(tag);
1017 else if(tag->id == ST_DEFINESOUND) {
1018 handleDefineSound(tag);
1021 else if(tag->id == ST_VIDEOFRAME) {
1022 handleVideoFrame(tag, myprefix);
1025 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1026 handleVideoStream(tag, myprefix);
1029 else if(tag->id == ST_DEFINEEDITTEXT) {
1030 handleEditText(tag);
1033 else if(tag->id == ST_DEFINEMOVIE) {
1034 U16 id = swf_GetU16(tag);
1035 char*s = swf_GetString(tag);
1036 printf(" URL: %s\n", s);
1038 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1044 else if(tag->id == ST_PLACEOBJECT2) {
1046 else if(tag->id == ST_NAMECHARACTER) {
1048 printf(" \"%s\"\n", swf_GetString(tag));
1054 sprintf(myprefix, " %s", prefix);
1056 if(tag->id == ST_DEFINESPRITE) {
1057 sprintf(prefix, " ");
1059 dumperror("Sprite definition inside a sprite definition");
1063 spriteframelabel = 0;
1065 else if(tag->id == ST_END) {
1068 spriteframelabel = 0;
1070 dumperror("End Tag not empty");
1072 else if(tag->id == ST_EXPORTASSETS) {
1073 handleExportAssets(tag, myprefix);
1075 else if(tag->id == ST_DOACTION && action) {
1077 actions = swf_ActionGet(tag);
1078 swf_DumpActions(actions, myprefix);
1080 else if(tag->id == ST_DOINITACTION && action) {
1082 swf_GetU16(tag); // id
1083 actions = swf_ActionGet(tag);
1084 swf_DumpActions(actions, myprefix);
1086 else if(tag->id == ST_DEFINEBUTTON && action) {
1087 dumpButtonActions(tag, myprefix);
1089 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1090 dumpButton2Actions(tag, myprefix);
1092 else if(tag->id == ST_PLACEOBJECT) {
1093 handlePlaceObject(tag, myprefix);
1095 else if(tag->id == ST_PLACEOBJECT2) {
1096 handlePlaceObject2(tag, myprefix);
1098 else if(tag->id == ST_DEFINESHAPE ||
1099 tag->id == ST_DEFINESHAPE2 ||
1100 tag->id == ST_DEFINESHAPE3) {
1102 handleShape(tag, myprefix);
1105 if(tag->len && used) {
1106 int num = swf_GetNumUsedIDs(tag);
1110 used = (int*)malloc(sizeof(int)*num);
1111 swf_GetUsedIDs(tag, used);
1112 printf("%s%suses IDs: ", indent, prefix);
1113 for(t=0;t<num;t++) {
1115 swf_SetTagPos(tag, used[t]);
1116 id = swf_GetU16(tag);
1117 printf("%d%s", id, t<num-1?", ":"");
1119 dumperror("Id %04d is not yet defined.\n", id);
1126 if(tag->len && hex) {
1127 hexdumpTag(tag, prefix);