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("-p , --placements Show placement information\n");
155 printf("-X , --width Prints out a string of the form \"-X width\".\n");
156 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
157 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
158 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
159 printf("-d , --hex Print hex output of tag data, too.\n");
160 printf("-u , --used Show referred IDs for each Tag.\n");
163 int args_callback_command(char*name,char*val)
166 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
174 char* testfunc(char*str)
176 printf("%s: %s\n", what, str);
180 void dumpButton2Actions(TAG*tag, char*prefix)
186 oldTagPos = swf_GetTagPos(tag);
188 // scan DefineButton2 Record
190 swf_GetU16(tag); // Character ID
191 swf_GetU8(tag); // Flags;
193 offsetpos = swf_GetTagPos(tag); // first offset
196 while (swf_GetU8(tag)) // state -> parse ButtonRecord
197 { swf_GetU16(tag); // id
198 swf_GetU16(tag); // layer
199 swf_GetMatrix(tag,NULL); // matrix
200 swf_GetCXForm(tag,NULL,1); // cxform
207 if(tag->pos >= tag->len)
210 offsetpos = swf_GetU16(tag);
211 condition = swf_GetU16(tag); // condition
213 actions = swf_ActionGet(tag);
214 printf("%s condition %04x\n", prefix, condition);
215 swf_DumpActions(actions, prefix);
218 swf_SetTagPos(tag,oldTagPos);
222 void dumpButtonActions(TAG*tag, char*prefix)
225 swf_GetU16(tag); // id
226 while (swf_GetU8(tag)) // state -> parse ButtonRecord
227 { swf_GetU16(tag); // id
228 swf_GetU16(tag); // layer
229 swf_GetMatrix(tag,NULL); // matrix
231 actions = swf_ActionGet(tag);
232 swf_DumpActions(actions, prefix);
235 #define ET_HASTEXT 32768
236 #define ET_WORDWRAP 16384
237 #define ET_MULTILINE 8192
238 #define ET_PASSWORD 4096
239 #define ET_READONLY 2048
240 #define ET_HASTEXTCOLOR 1024
241 #define ET_HASMAXLENGTH 512
242 #define ET_HASFONT 256
245 #define ET_HASLAYOUT 32
246 #define ET_NOSELECT 16
250 #define ET_USEOUTLINES 1
256 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
259 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
260 for(t=0;t<fontnum;t++)
262 if(fonts[t]->id == fontid) {
272 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
273 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
276 a = fonts[font]->glyph2ascii[glyphs[t]];
283 printf("\\x%x", (int)a);
288 void handleText(TAG*tag)
291 swf_ParseDefineText(tag,textcallback, 0);
294 void handleDefineSound(TAG*tag)
296 U16 id = swf_GetU16(tag);
297 U8 flags = swf_GetU8(tag);
298 int compression = (flags>>4)&3;
299 int rate = (flags>>2)&3;
300 int bits = flags&2?16:8;
301 int stereo = flags&1;
303 if(compression == 0) printf("Raw ");
304 else if(compression == 1) printf("ADPCM ");
305 else if(compression == 2) printf("MP3 ");
307 if(rate == 0) printf("5.5Khz ");
308 if(rate == 1) printf("11Khz ");
309 if(rate == 2) printf("22Khz ");
310 if(rate == 3) printf("44Khz ");
311 printf("%dBit ", bits);
312 if(stereo) printf("stereo");
317 void handleDefineBits(TAG*tag)
323 id = swf_GetU16(tag);
324 mode = swf_GetU8(tag);
325 width = swf_GetU16(tag);
326 height = swf_GetU16(tag);
327 printf(" image %dx%d",width,height);
328 if(mode == 3) printf(" (8 bpp)");
329 else if(mode == 4) printf(" (16 bpp)");
330 else if(mode == 5) printf(" (32 bpp)");
331 else printf(" (? bpp)");
334 void handleEditText(TAG*tag)
339 id = swf_GetU16(tag);
341 //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]);
369 if(flags & (ET_X1 | ET_X2 | ET_X3 | ET_X0))
371 printf(" undefined flags: %d%d%d%d",
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)
466 U8 flags = swf_GetU8(tag);
470 int ppos[3] = {0,0,0};
471 swf_GetU16(tag); //depth
474 if(flags&2) swf_GetU16(tag); //id
476 swf_GetMatrix(tag,&m);
478 ppos[0] += sprintf(pstr[0], "| Matrix ");
479 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
480 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
484 swf_GetCXForm(tag, &cx, 1);
486 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
487 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);
488 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
492 U16 ratio = swf_GetU16(tag); //ratio
494 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
495 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
496 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
500 U16 clip = swf_GetU16(tag); //clip
502 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
503 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
504 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
507 if(flags&32) { while(swf_GetU8(tag)); }
508 if(placements && ppos[0]) {
510 printf("%s %s\n", prefix, pstr[0]);
511 printf("%s %s\n", prefix, pstr[1]);
512 printf("%s %s", prefix, pstr[2]);
521 reserved = swf_GetU16(tag); // must be 0
522 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
524 printf("Unknown parameter field not zero: %04x\n", reserved);
527 printf("global flags: %04x\n", globalflags);
529 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
531 handlerflags = swf_GetU32(tag);
534 while(handlerflags) {
539 globalflags &= ~handlerflags;
540 printf("%s flags %08x ",prefix, handlerflags);
541 printhandlerflags(handlerflags);
542 length = swf_GetU32(tag);
543 printf(", %d bytes actioncode\n",length);
544 a = swf_ActionGet(tag);
545 swf_DumpActions(a,prefix);
548 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
550 if(globalflags) // should go to sterr.
551 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
553 printf(" has action code\n");
558 void handlePlaceObject(TAG*tag, char*prefix)
560 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
562 U16 id = swf_GetU16(tag);
563 U16 depth = swf_GetU16(tag);
566 swf_GetMatrix(tag, &matrix);
567 swf_GetCXForm(tag, &cxform, 0);
570 swf_SetU16(tag2, depth);
571 swf_SetMatrix(tag2, &matrix);
572 swf_SetCXForm(tag2, &cxform, 1);
574 handlePlaceObject2(tag2, prefix);
577 char* fillstyle2str(FILLSTYLE*style)
579 switch(style->type) {
581 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
583 case 0x10: case 0x12:
584 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
586 case 0x40: case 0x41:
587 /* TODO: display information about that bitmap */
588 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
591 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
595 char* linestyle2str(LINESTYLE*style)
597 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
601 void handleShape(TAG*tag, char*prefix)
609 swf_ParseDefineShape(tag, &shape);
611 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
613 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
618 else printf("%s | (Neither line nor fill styles)\n", prefix);
621 printf("%s", prefix);
622 if(t < shape.numfillstyles) {
623 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
627 if(t < shape.numlinestyles) {
628 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
633 printf("%s |\n", prefix);
637 printf("%s | fill: %02d/%02d line:%02d - ",
642 if(line->type == moveTo) {
643 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
644 } else if(line->type == lineTo) {
645 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
646 } else if(line->type == splineTo) {
647 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
648 line->sx/20.0, line->sy/20.0,
649 line->x/20.0, line->y/20.0
654 printf("%s |\n", prefix);
657 void fontcallback1(U16 id,U8 * name)
661 void fontcallback2(U16 id,U8 * name)
663 swf_FontExtract(&swf,id,&fonts[fontnum]);
667 static U8 printable(U8 a)
669 if(a<32 || a==127) return '.';
672 void hexdumpTag(TAG*tag, char* prefix)
676 printf(" %s-=> ",prefix);
677 for(t=0;t<tag->len;t++) {
678 printf("%02x ", tag->data[t]);
679 ascii[t&15] = printable(tag->data[t]);
680 if((t && ((t&15)==15)) || (t==tag->len-1))
684 for(s=p-1;s<16;s++) {
688 printf(" %s\n", ascii);
690 printf(" %s\n %s-=> ",ascii,prefix);
695 void handleExportAssets(TAG*tag, char* prefix)
701 num = swf_GetU16(tag);
704 id = swf_GetU16(tag);
705 name = swf_GetString(tag);
706 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
710 void dumperror(const char* format, ...)
715 va_start(arglist, format);
716 vsprintf(buf, format, arglist);
720 printf("==== Error: %s ====\n", buf);
723 static char strbuf[800];
726 char* timestring(double f)
728 int hours = (int)(f/3600);
729 int minutes = (int)((f-hours*3600)/60);
730 int seconds = (int)((f-hours*3600-minutes*60));
731 int useconds = (int)((f-(int)f)*1000+0.5);
734 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
735 return &strbuf[bufpos];
738 int main (int argc,char ** argv)
746 char issprite = 0; // are we inside a sprite definition?
749 char* spriteframelabel = 0;
750 char* framelabel = 0;
754 memset(idtab,0,65536);
756 processargs(argc, argv);
760 fprintf(stderr, "You must supply a filename.\n");
764 f = open(filename,O_RDONLY|O_BINARY);
769 sprintf(buffer, "Couldn't open %s", filename);
773 if FAILED(swf_ReadSWF(f,&swf))
775 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
782 if(statbuf.st_size != swf.fileSize && !swf.compressed)
783 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
784 statbuf.st_size, swf.fileSize);
785 filesize = statbuf.st_size;
790 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
791 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
795 printf("-X %d", xsize);
801 printf("-Y %d", ysize);
807 printf("-r %.2f", swf.frameRate/256.0);
813 printf("-f %d", swf.frameCount);
820 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
821 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
822 if(swf.fileVersion>9) {
823 fprintf(stderr, "Fileversion>9\n");
826 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
828 //" BGCOLOR=#ffffffff\n"?
830 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
831 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
832 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
833 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
834 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
835 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
836 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
837 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
838 " TYPE=\"application/x-shockwave-flash\"\n"
839 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
841 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
842 filename, filename, xsize, ysize);
845 printf("[HEADER] File version: %d\n", swf.fileVersion);
847 printf("[HEADER] File is zlib compressed.");
848 if(filesize && swf.fileSize)
849 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
853 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
854 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
855 printf("[HEADER] Frame count: %d\n",swf.frameCount);
856 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
857 if(swf.movieSize.xmin)
858 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
861 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
862 if(swf.movieSize.ymin)
863 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
871 swf_FontEnumerate(&swf,&fontcallback1);
872 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
874 swf_FontEnumerate(&swf,&fontcallback2);
878 char*name = swf_TagGetName(tag);
881 dumperror("Unknown tag:0x%03x", tag->id);
885 if(swf_TagGetName(tag)) {
886 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
888 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
891 if(tag->id == ST_FREECHARACTER) {
892 U16 id = swf_GetU16(tag);
896 if(swf_isDefiningTag(tag)) {
897 U16 id = swf_GetDefineID(tag);
898 printf(" defines id %04d", id);
900 dumperror("Id %04d is defined more than once.", id);
903 else if(swf_isPseudoDefiningTag(tag)) {
904 U16 id = swf_GetDefineID(tag);
905 printf(" adds information to id %04d", id);
907 dumperror("Id %04d is not yet defined.\n", id);
909 else if(tag->id == ST_PLACEOBJECT) {
910 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
912 printf(" name \"%s\"",swf_GetName(tag));
914 else if(tag->id == ST_PLACEOBJECT2) {
921 printf(" id %04d",swf_GetPlaceID(tag));
925 printf(" at depth %04d", swf_GetDepth(tag));
927 printf(" name \"%s\"",swf_GetName(tag));
929 else if(tag->id == ST_REMOVEOBJECT) {
930 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
932 else if(tag->id == ST_REMOVEOBJECT2) {
933 printf(" removes object from depth %04d", swf_GetDepth(tag));
935 else if(tag->id == ST_FREECHARACTER) {
936 printf(" frees object %04d", swf_GetPlaceID(tag));
938 else if(tag->id == ST_STARTSOUND) {
941 id = swf_GetU16(tag);
942 flags = swf_GetU8(tag);
944 printf(" stops sound with id %04d", id);
946 printf(" starts sound with id %04d", id);
948 printf(" (if not already playing)");
954 printf(" looping %d times", swf_GetU16(tag));
957 else if(tag->id == ST_FRAMELABEL) {
958 int l = strlen(tag->data);
959 printf(" \"%s\"", tag->data);
961 printf(" has %d extra bytes", tag->len-1-l);
962 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
965 if((framelabel && !issprite) ||
966 (spriteframelabel && issprite)) {
967 dumperror("Frame %d has more than one label",
968 issprite?spriteframe:mainframe);
970 if(issprite) spriteframelabel = tag->data;
971 else framelabel = tag->data;
973 else if(tag->id == ST_SHOWFRAME) {
974 char*label = issprite?spriteframelabel:framelabel;
975 int frame = issprite?spriteframe:mainframe;
978 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
980 if(issprite) spriteframe++;
986 printf(" %d (%s)", frame, timestring(frame*(256.0/(swf.frameRate+0.1))));
988 printf(" %d-%d (%s-%s)", frame, nframe,
989 timestring(frame*(256.0/(swf.frameRate+0.1))),
990 timestring(nframe*(256.0/(swf.frameRate+0.1)))
993 printf(" (label \"%s\")", label);
994 if(issprite) {spriteframe++; spriteframelabel = 0;}
995 if(!issprite) {mainframe++; framelabel = 0;}
998 if(tag->id == ST_SETBACKGROUNDCOLOR) {
999 U8 r = swf_GetU8(tag);
1000 U8 g = swf_GetU8(tag);
1001 U8 b = swf_GetU8(tag);
1002 printf(" (%02x/%02x/%02x)\n",r,g,b);
1004 else if(tag->id == ST_PROTECT) {
1006 printf(" %s\n", swf_GetString(tag));
1011 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1012 tag->id == ST_DEFINEBITSLOSSLESS2) {
1013 handleDefineBits(tag);
1016 else if(tag->id == ST_DEFINESOUND) {
1017 handleDefineSound(tag);
1020 else if(tag->id == ST_VIDEOFRAME) {
1021 handleVideoFrame(tag, myprefix);
1024 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1025 handleVideoStream(tag, myprefix);
1028 else if(tag->id == ST_DEFINEEDITTEXT) {
1029 handleEditText(tag);
1032 else if(tag->id == ST_DEFINEMOVIE) {
1033 U16 id = swf_GetU16(tag);
1034 char*s = swf_GetString(tag);
1035 printf(" URL: %s\n", s);
1037 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1043 else if(tag->id == ST_PLACEOBJECT2) {
1045 else if(tag->id == ST_NAMECHARACTER) {
1047 printf(" \"%s\"\n", swf_GetString(tag));
1053 sprintf(myprefix, " %s", prefix);
1055 if(tag->id == ST_DEFINESPRITE) {
1056 sprintf(prefix, " ");
1058 dumperror("Sprite definition inside a sprite definition");
1062 spriteframelabel = 0;
1064 else if(tag->id == ST_END) {
1067 spriteframelabel = 0;
1069 dumperror("End Tag not empty");
1071 else if(tag->id == ST_EXPORTASSETS) {
1072 handleExportAssets(tag, myprefix);
1074 else if(tag->id == ST_DOACTION && action) {
1076 actions = swf_ActionGet(tag);
1077 swf_DumpActions(actions, myprefix);
1079 else if(tag->id == ST_DOINITACTION && action) {
1081 swf_GetU16(tag); // id
1082 actions = swf_ActionGet(tag);
1083 swf_DumpActions(actions, myprefix);
1085 else if(tag->id == ST_DEFINEBUTTON && action) {
1086 dumpButtonActions(tag, myprefix);
1088 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1089 dumpButton2Actions(tag, myprefix);
1091 else if(tag->id == ST_PLACEOBJECT) {
1092 handlePlaceObject(tag, myprefix);
1094 else if(tag->id == ST_PLACEOBJECT2) {
1095 handlePlaceObject2(tag, myprefix);
1097 else if(tag->id == ST_DEFINESHAPE ||
1098 tag->id == ST_DEFINESHAPE2 ||
1099 tag->id == ST_DEFINESHAPE3) {
1101 handleShape(tag, myprefix);
1104 if(tag->len && used) {
1105 int num = swf_GetNumUsedIDs(tag);
1109 used = (int*)malloc(sizeof(int)*num);
1110 swf_GetUsedIDs(tag, used);
1111 printf("%s%suses IDs: ", indent, prefix);
1112 for(t=0;t<num;t++) {
1114 swf_SetTagPos(tag, used[t]);
1115 id = swf_GetU16(tag);
1116 printf("%d%s", id, t<num-1?", ":"");
1118 dumperror("Id %04d is not yet defined.\n", id);
1125 if(tag->len && hex) {
1126 hexdumpTag(tag, prefix);