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);
240 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
243 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
244 for(t=0;t<fontnum;t++)
246 if(fonts[t]->id == fontid) {
256 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
257 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
260 a = fonts[font]->glyph2ascii[glyphs[t]];
267 printf("\\x%x", (int)a);
272 void handleText(TAG*tag)
275 swf_ParseDefineText(tag,textcallback, 0);
278 void handleDefineSound(TAG*tag)
280 U16 id = swf_GetU16(tag);
281 U8 flags = swf_GetU8(tag);
282 int compression = (flags>>4)&3;
283 int rate = (flags>>2)&3;
284 int bits = flags&2?16:8;
285 int stereo = flags&1;
287 if(compression == 0) printf("Raw ");
288 else if(compression == 1) printf("ADPCM ");
289 else if(compression == 2) printf("MP3 ");
291 if(rate == 0) printf("5.5Khz ");
292 if(rate == 1) printf("11Khz ");
293 if(rate == 2) printf("22Khz ");
294 if(rate == 3) printf("44Khz ");
295 printf("%dBit ", bits);
296 if(stereo) printf("stereo");
301 void handleDefineBits(TAG*tag)
307 id = swf_GetU16(tag);
308 mode = swf_GetU8(tag);
309 width = swf_GetU16(tag);
310 height = swf_GetU16(tag);
311 printf(" image %dx%d",width,height);
312 if(mode == 3) printf(" (8 bpp)");
313 else if(mode == 4) printf(" (16 bpp)");
314 else if(mode == 5) printf(" (32 bpp)");
315 else printf(" (? bpp)");
318 void handleEditText(TAG*tag)
323 id = swf_GetU16(tag);
326 //swf_ResetReadBits(tag);
332 flags = swf_GetBits(tag,16);
333 if(flags & ET_HASFONT) {
334 swf_GetU16(tag); //font
335 swf_GetU16(tag); //fontheight
337 if(flags & ET_HASTEXTCOLOR) {
338 swf_GetU8(tag); //rgba
343 if(flags & ET_HASMAXLENGTH) {
344 swf_GetU16(tag); //maxlength
346 if(flags & ET_HASLAYOUT) {
347 swf_GetU8(tag); //align
348 swf_GetU16(tag); //left margin
349 swf_GetU16(tag); //right margin
350 swf_GetU16(tag); //indent
351 swf_GetU16(tag); //leading
353 printf(" variable \"%s\" ", &tag->data[tag->pos]);
354 if(flags & ET_HTML) printf("(html)");
355 if(flags & ET_NOSELECT) printf("(noselect)");
356 if(flags & ET_PASSWORD) printf("(password)");
357 if(flags & ET_READONLY) printf("(readonly)");
359 if(flags & (ET_X1 | ET_X3 ))
361 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
364 while(tag->data[tag->pos++]);
365 if(flags & ET_HASTEXT)
366 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
369 void printhandlerflags(U32 handlerflags)
371 if(handlerflags&1) printf("[on load]");
372 if(handlerflags&2) printf("[enter frame]");
373 if(handlerflags&4) printf("[unload]");
374 if(handlerflags&8) printf("[mouse move]");
375 if(handlerflags&16) printf("[mouse down]");
376 if(handlerflags&32) printf("[mouse up]");
377 if(handlerflags&64) printf("[key down]");
378 if(handlerflags&128) printf("[key up]");
380 if(handlerflags&256) printf("[data]");
381 if(handlerflags&512) printf("[initialize]");
382 if(handlerflags&1024) printf("[mouse press]");
383 if(handlerflags&2048) printf("[mouse release]");
384 if(handlerflags&4096) printf("[mouse release outside]");
385 if(handlerflags&8192) printf("[mouse rollover]");
386 if(handlerflags&16384) printf("[mouse rollout]");
387 if(handlerflags&32768) printf("[mouse drag over]");
389 if(handlerflags&0x10000) printf("[mouse drag out]");
390 if(handlerflags&0x20000) printf("[key press]");
391 if(handlerflags&0x40000) printf("[construct even]");
392 if(handlerflags&0xfff80000) printf("[???]");
394 void handleVideoStream(TAG*tag, char*prefix)
396 U16 id = swf_GetU16(tag);
397 U16 frames = swf_GetU16(tag);
398 U16 width = swf_GetU16(tag);
399 U16 height = swf_GetU16(tag);
400 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
401 U8 codec = swf_GetU8(tag);
402 printf(" (%d frames, %dx%d", frames, width, height);
406 printf(" sorenson h.263)");
408 printf(" codec 0x%02x)", codec);
410 void handleVideoFrame(TAG*tag, char*prefix)
412 U32 code, version, reference, sizeflags;
413 U32 width=0, height=0;
415 U16 id = swf_GetU16(tag);
416 U16 frame = swf_GetU16(tag);
417 U8 deblock,flags, tmp, bit;
419 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
420 printf(" (frame %d) ", frame);
422 /* video packet follows */
423 code = swf_GetBits(tag, 17);
424 version = swf_GetBits(tag, 5);
425 reference = swf_GetBits(tag, 8);
427 sizeflags = swf_GetBits(tag, 3);
430 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
431 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
432 case 2: width = 352; height = 288; break;
433 case 3: width = 176; height = 144; break;
434 case 4: width = 128; height = 96; break;
435 case 5: width = 320; height = 240; break;
436 case 6: width = 160; height = 120; break;
437 case 7: width = -1; height = -1;/*reserved*/ break;
439 printf("%dx%d ", width, height);
440 type = swf_GetBits(tag, 2);
441 printf("%s", types[type]);
443 deblock = swf_GetBits(tag, 1);
445 printf(" deblock ", deblock);
446 quantizer = swf_GetBits(tag, 5);
447 printf(" quant: %d ", quantizer);
450 void handlePlaceObject2(TAG*tag, char*prefix)
452 U8 flags = swf_GetU8(tag);
456 int ppos[3] = {0,0,0};
457 swf_GetU16(tag); //depth
460 if(flags&2) swf_GetU16(tag); //id
462 swf_GetMatrix(tag,&m);
464 ppos[0] += sprintf(pstr[0], "| Matrix ");
465 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
466 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
470 swf_GetCXForm(tag, &cx, 1);
472 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
473 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);
474 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
478 U16 ratio = swf_GetU16(tag); //ratio
480 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
481 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
482 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
486 U16 clip = swf_GetU16(tag); //clip
488 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
489 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
490 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
493 if(flags&32) { while(swf_GetU8(tag)); }
494 if(placements && ppos[0]) {
496 printf("%s %s\n", prefix, pstr[0]);
497 printf("%s %s\n", prefix, pstr[1]);
498 printf("%s %s", prefix, pstr[2]);
507 reserved = swf_GetU16(tag); // must be 0
508 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
510 printf("Unknown parameter field not zero: %04x\n", reserved);
513 printf("global flags: %04x\n", globalflags);
515 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
517 handlerflags = swf_GetU32(tag);
520 while(handlerflags) {
525 globalflags &= ~handlerflags;
526 printf("%s flags %08x ",prefix, handlerflags);
527 printhandlerflags(handlerflags);
528 length = swf_GetU32(tag);
529 printf(", %d bytes actioncode\n",length);
530 a = swf_ActionGet(tag);
531 swf_DumpActions(a,prefix);
534 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
536 if(globalflags) // should go to sterr.
537 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
539 printf(" has action code\n");
544 void handlePlaceObject(TAG*tag, char*prefix)
546 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
548 U16 id = swf_GetU16(tag);
549 U16 depth = swf_GetU16(tag);
552 swf_GetMatrix(tag, &matrix);
553 swf_GetCXForm(tag, &cxform, 0);
556 swf_SetU16(tag2, depth);
557 swf_SetMatrix(tag2, &matrix);
558 swf_SetCXForm(tag2, &cxform, 1);
560 handlePlaceObject2(tag2, prefix);
563 char* fillstyle2str(FILLSTYLE*style)
565 switch(style->type) {
567 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
569 case 0x10: case 0x12:
570 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
572 case 0x40: case 0x41:
573 /* TODO: display information about that bitmap */
574 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
577 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
581 char* linestyle2str(LINESTYLE*style)
583 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
587 void handleShape(TAG*tag, char*prefix)
595 swf_ParseDefineShape(tag, &shape);
597 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
599 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
604 else printf("%s | (Neither line nor fill styles)\n", prefix);
607 printf("%s", prefix);
608 if(t < shape.numfillstyles) {
609 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
613 if(t < shape.numlinestyles) {
614 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
619 printf("%s |\n", prefix);
623 printf("%s | fill: %02d/%02d line:%02d - ",
628 if(line->type == moveTo) {
629 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
630 } else if(line->type == lineTo) {
631 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
632 } else if(line->type == splineTo) {
633 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
634 line->sx/20.0, line->sy/20.0,
635 line->x/20.0, line->y/20.0
640 printf("%s |\n", prefix);
643 void fontcallback1(void*self, U16 id,U8 * name)
647 void fontcallback2(void*self, U16 id,U8 * name)
649 swf_FontExtract(&swf,id,&fonts[fontnum]);
653 static U8 printable(U8 a)
655 if(a<32 || a==127) return '.';
658 void hexdumpTag(TAG*tag, char* prefix)
662 printf(" %s-=> ",prefix);
663 for(t=0;t<tag->len;t++) {
664 printf("%02x ", tag->data[t]);
665 ascii[t&15] = printable(tag->data[t]);
666 if((t && ((t&15)==15)) || (t==tag->len-1))
670 for(s=p-1;s<16;s++) {
674 printf(" %s\n", ascii);
676 printf(" %s\n %s-=> ",ascii,prefix);
681 void handleExportAssets(TAG*tag, char* prefix)
687 num = swf_GetU16(tag);
690 id = swf_GetU16(tag);
691 name = swf_GetString(tag);
692 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
696 void dumperror(const char* format, ...)
701 va_start(arglist, format);
702 vsprintf(buf, format, arglist);
706 printf("==== Error: %s ====\n", buf);
709 static char strbuf[800];
712 char* timestring(double f)
714 int hours = (int)(f/3600);
715 int minutes = (int)((f-hours*3600)/60);
716 int seconds = (int)((f-hours*3600-minutes*60));
717 int useconds = (int)((f-(int)f)*1000+0.5);
720 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
721 return &strbuf[bufpos];
724 int main (int argc,char ** argv)
732 char issprite = 0; // are we inside a sprite definition?
735 char* spriteframelabel = 0;
736 char* framelabel = 0;
740 memset(idtab,0,65536);
742 processargs(argc, argv);
746 fprintf(stderr, "You must supply a filename.\n");
750 f = open(filename,O_RDONLY|O_BINARY);
755 sprintf(buffer, "Couldn't open %s", filename);
759 if FAILED(swf_ReadSWF(f,&swf))
761 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
768 if(statbuf.st_size != swf.fileSize && !swf.compressed)
769 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
770 statbuf.st_size, swf.fileSize);
771 filesize = statbuf.st_size;
776 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
777 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
781 printf("-X %d", xsize);
787 printf("-Y %d", ysize);
793 printf("-r %.2f", swf.frameRate/256.0);
799 printf("-f %d", swf.frameCount);
806 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
807 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
808 if(swf.fileVersion>9) {
809 fprintf(stderr, "Fileversion>9\n");
812 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
814 //" BGCOLOR=#ffffffff\n"?
816 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
817 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
818 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
819 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
820 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
821 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
822 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
823 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
824 " TYPE=\"application/x-shockwave-flash\"\n"
825 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
827 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
828 filename, filename, xsize, ysize);
831 printf("[HEADER] File version: %d\n", swf.fileVersion);
833 printf("[HEADER] File is zlib compressed.");
834 if(filesize && swf.fileSize)
835 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
839 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
840 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
841 printf("[HEADER] Frame count: %d\n",swf.frameCount);
842 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
843 if(swf.movieSize.xmin)
844 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
847 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
848 if(swf.movieSize.ymin)
849 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
857 swf_FontEnumerate(&swf,&fontcallback1, 0);
858 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
860 swf_FontEnumerate(&swf,&fontcallback2, 0);
864 char*name = swf_TagGetName(tag);
867 dumperror("Unknown tag:0x%03x", tag->id);
871 if(swf_TagGetName(tag)) {
872 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
874 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
877 if(tag->id == ST_FREECHARACTER) {
878 U16 id = swf_GetU16(tag);
882 if(swf_isDefiningTag(tag)) {
883 U16 id = swf_GetDefineID(tag);
884 printf(" defines id %04d", id);
886 dumperror("Id %04d is defined more than once.", id);
889 else if(swf_isPseudoDefiningTag(tag)) {
890 U16 id = swf_GetDefineID(tag);
891 printf(" adds information to id %04d", id);
893 dumperror("Id %04d is not yet defined.\n", id);
895 else if(tag->id == ST_PLACEOBJECT) {
896 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
898 printf(" name \"%s\"",swf_GetName(tag));
900 else if(tag->id == ST_PLACEOBJECT2) {
907 printf(" id %04d",swf_GetPlaceID(tag));
911 printf(" at depth %04d", swf_GetDepth(tag));
913 printf(" name \"%s\"",swf_GetName(tag));
915 else if(tag->id == ST_REMOVEOBJECT) {
916 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
918 else if(tag->id == ST_REMOVEOBJECT2) {
919 printf(" removes object from depth %04d", swf_GetDepth(tag));
921 else if(tag->id == ST_FREECHARACTER) {
922 printf(" frees object %04d", swf_GetPlaceID(tag));
924 else if(tag->id == ST_STARTSOUND) {
927 id = swf_GetU16(tag);
928 flags = swf_GetU8(tag);
930 printf(" stops sound with id %04d", id);
932 printf(" starts sound with id %04d", id);
934 printf(" (if not already playing)");
940 printf(" looping %d times", swf_GetU16(tag));
943 else if(tag->id == ST_FRAMELABEL) {
944 int l = strlen(tag->data);
945 printf(" \"%s\"", tag->data);
947 printf(" has %d extra bytes", tag->len-1-l);
948 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
951 if((framelabel && !issprite) ||
952 (spriteframelabel && issprite)) {
953 dumperror("Frame %d has more than one label",
954 issprite?spriteframe:mainframe);
956 if(issprite) spriteframelabel = tag->data;
957 else framelabel = tag->data;
959 else if(tag->id == ST_SHOWFRAME) {
960 char*label = issprite?spriteframelabel:framelabel;
961 int frame = issprite?spriteframe:mainframe;
964 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
966 if(issprite) spriteframe++;
972 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
974 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
975 timestring(frame*(256.0/(swf.frameRate+0.1))),
976 timestring(nframe*(256.0/(swf.frameRate+0.1)))
979 printf(" (label \"%s\")", label);
980 if(issprite) {spriteframe++; spriteframelabel = 0;}
981 if(!issprite) {mainframe++; framelabel = 0;}
984 if(tag->id == ST_SETBACKGROUNDCOLOR) {
985 U8 r = swf_GetU8(tag);
986 U8 g = swf_GetU8(tag);
987 U8 b = swf_GetU8(tag);
988 printf(" (%02x/%02x/%02x)\n",r,g,b);
990 else if(tag->id == ST_PROTECT) {
992 printf(" %s\n", swf_GetString(tag));
997 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
998 tag->id == ST_DEFINEBITSLOSSLESS2) {
999 handleDefineBits(tag);
1002 else if(tag->id == ST_DEFINESOUND) {
1003 handleDefineSound(tag);
1006 else if(tag->id == ST_VIDEOFRAME) {
1007 handleVideoFrame(tag, myprefix);
1010 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1011 handleVideoStream(tag, myprefix);
1014 else if(tag->id == ST_DEFINEEDITTEXT) {
1015 handleEditText(tag);
1018 else if(tag->id == ST_DEFINEMOVIE) {
1019 U16 id = swf_GetU16(tag);
1020 char*s = swf_GetString(tag);
1021 printf(" URL: %s\n", s);
1023 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1029 else if(tag->id == ST_PLACEOBJECT2) {
1031 else if(tag->id == ST_NAMECHARACTER) {
1033 printf(" \"%s\"\n", swf_GetString(tag));
1039 sprintf(myprefix, " %s", prefix);
1041 if(tag->id == ST_DEFINESPRITE) {
1042 sprintf(prefix, " ");
1044 dumperror("Sprite definition inside a sprite definition");
1048 spriteframelabel = 0;
1050 else if(tag->id == ST_END) {
1053 spriteframelabel = 0;
1055 dumperror("End Tag not empty");
1057 else if(tag->id == ST_EXPORTASSETS) {
1058 handleExportAssets(tag, myprefix);
1060 else if(tag->id == ST_DOACTION && action) {
1062 actions = swf_ActionGet(tag);
1063 swf_DumpActions(actions, myprefix);
1065 else if(tag->id == ST_DOINITACTION && action) {
1067 swf_GetU16(tag); // id
1068 actions = swf_ActionGet(tag);
1069 swf_DumpActions(actions, myprefix);
1071 else if(tag->id == ST_DEFINEBUTTON && action) {
1072 dumpButtonActions(tag, myprefix);
1074 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1075 dumpButton2Actions(tag, myprefix);
1077 else if(tag->id == ST_PLACEOBJECT) {
1078 handlePlaceObject(tag, myprefix);
1080 else if(tag->id == ST_PLACEOBJECT2) {
1081 handlePlaceObject2(tag, myprefix);
1083 else if(tag->id == ST_DEFINESHAPE ||
1084 tag->id == ST_DEFINESHAPE2 ||
1085 tag->id == ST_DEFINESHAPE3) {
1087 handleShape(tag, myprefix);
1090 if(tag->len && used) {
1091 int num = swf_GetNumUsedIDs(tag);
1095 used = (int*)malloc(sizeof(int)*num);
1096 swf_GetUsedIDs(tag, used);
1097 printf("%s%suses IDs: ", indent, prefix);
1098 for(t=0;t<num;t++) {
1100 swf_SetTagPos(tag, used[t]);
1101 id = swf_GetU16(tag);
1102 printf("%d%s", id, t<num-1?", ":"");
1104 dumperror("Id %04d is not yet defined.\n", id);
1111 if(tag->len && hex) {
1112 hexdumpTag(tag, prefix);