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;
61 static struct options_t options[] = {
80 int args_callback_option(char*name,char*val)
82 if(!strcmp(name, "V")) {
83 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
86 else if(name[0]=='a') {
90 else if(name[0]=='p') {
94 else if(name[0]=='t') {
98 else if(name[0]=='s') {
102 else if(name[0]=='e') {
106 else if(name[0]=='X') {
110 else if(name[0]=='Y') {
114 else if(name[0]=='r') {
118 else if(name[0]=='f') {
122 else if(name[0]=='d') {
126 else if(name[0]=='u') {
130 else if(name[0]=='b') {
134 else if(name[0]=='D') {
135 action = placements = showtext = showshapes = 1;
139 printf("Unknown option: -%s\n", name);
145 int args_callback_longoption(char*name,char*val)
147 return args_long2shortoption(options, name, val);
149 void args_callback_usage(char *name)
152 printf("Usage: %s [-atpdu] file.swf\n", name);
154 printf("-h , --help Print short help message and exit\n");
155 printf("-D , --full Show everything. Same as -atp\n");
156 printf("-V , --version Print version info and exit\n");
157 printf("-e , --html Print out html code for embedding the file\n");
158 printf("-a , --action Disassemble action tags\n");
159 printf("-t , --text Show text fields (like swfstrings).\n");
160 printf("-s , --shapes Show shape coordinates/styles\n");
161 printf("-p , --placements Show placement information\n");
162 printf("-b , --bbox Print tag's bounding boxes\n");
163 printf("-X , --width Prints out a string of the form \"-X width\".\n");
164 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
165 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
166 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
167 printf("-d , --hex Print hex output of tag data, too.\n");
168 printf("-u , --used Show referred IDs for each Tag.\n");
171 int args_callback_command(char*name,char*val)
174 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
182 char* testfunc(char*str)
184 printf("%s: %s\n", what, str);
188 void dumpButton2Actions(TAG*tag, char*prefix)
194 oldTagPos = swf_GetTagPos(tag);
196 // scan DefineButton2 Record
198 swf_GetU16(tag); // Character ID
199 swf_GetU8(tag); // Flags;
201 offsetpos = swf_GetTagPos(tag); // first offset
204 while (swf_GetU8(tag)) // state -> parse ButtonRecord
205 { swf_GetU16(tag); // id
206 swf_GetU16(tag); // layer
207 swf_GetMatrix(tag,NULL); // matrix
208 swf_GetCXForm(tag,NULL,1); // cxform
215 if(tag->pos >= tag->len)
218 offsetpos = swf_GetU16(tag);
219 condition = swf_GetU16(tag); // condition
221 actions = swf_ActionGet(tag);
222 printf("%s condition %04x\n", prefix, condition);
223 swf_DumpActions(actions, prefix);
226 swf_SetTagPos(tag,oldTagPos);
230 void dumpButtonActions(TAG*tag, char*prefix)
233 swf_GetU16(tag); // id
234 while (swf_GetU8(tag)) // state -> parse ButtonRecord
235 { swf_GetU16(tag); // id
236 swf_GetU16(tag); // layer
237 swf_GetMatrix(tag,NULL); // matrix
239 actions = swf_ActionGet(tag);
240 swf_DumpActions(actions, prefix);
247 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
250 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
251 for(t=0;t<fontnum;t++)
253 if(fonts[t]->id == fontid) {
263 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
264 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
267 a = fonts[font]->glyph2ascii[glyphs[t]];
274 printf("\\x%x", (int)a);
279 void handleText(TAG*tag)
282 swf_ParseDefineText(tag,textcallback, 0);
285 void handleDefineSound(TAG*tag)
287 U16 id = swf_GetU16(tag);
288 U8 flags = swf_GetU8(tag);
289 int compression = (flags>>4)&3;
290 int rate = (flags>>2)&3;
291 int bits = flags&2?16:8;
292 int stereo = flags&1;
294 if(compression == 0) printf("Raw ");
295 else if(compression == 1) printf("ADPCM ");
296 else if(compression == 2) printf("MP3 ");
298 if(rate == 0) printf("5.5Khz ");
299 if(rate == 1) printf("11Khz ");
300 if(rate == 2) printf("22Khz ");
301 if(rate == 3) printf("44Khz ");
302 printf("%dBit ", bits);
303 if(stereo) printf("stereo");
308 void handleDefineBits(TAG*tag)
314 id = swf_GetU16(tag);
315 mode = swf_GetU8(tag);
316 width = swf_GetU16(tag);
317 height = swf_GetU16(tag);
318 printf(" image %dx%d",width,height);
319 if(mode == 3) printf(" (8 bpp)");
320 else if(mode == 4) printf(" (16 bpp)");
321 else if(mode == 5) printf(" (32 bpp)");
322 else printf(" (? bpp)");
325 void handleEditText(TAG*tag)
330 id = swf_GetU16(tag);
333 //swf_ResetReadBits(tag);
339 flags = swf_GetBits(tag,16);
340 if(flags & ET_HASFONT) {
341 swf_GetU16(tag); //font
342 swf_GetU16(tag); //fontheight
344 if(flags & ET_HASTEXTCOLOR) {
345 swf_GetU8(tag); //rgba
350 if(flags & ET_HASMAXLENGTH) {
351 swf_GetU16(tag); //maxlength
353 if(flags & ET_HASLAYOUT) {
354 swf_GetU8(tag); //align
355 swf_GetU16(tag); //left margin
356 swf_GetU16(tag); //right margin
357 swf_GetU16(tag); //indent
358 swf_GetU16(tag); //leading
360 printf(" variable \"%s\" ", &tag->data[tag->pos]);
361 if(flags & ET_HTML) printf("(html)");
362 if(flags & ET_NOSELECT) printf("(noselect)");
363 if(flags & ET_PASSWORD) printf("(password)");
364 if(flags & ET_READONLY) printf("(readonly)");
366 if(flags & (ET_X1 | ET_X3 ))
368 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
371 while(tag->data[tag->pos++]);
372 if(flags & ET_HASTEXT)
373 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
376 void printhandlerflags(U32 handlerflags)
378 if(handlerflags&1) printf("[on load]");
379 if(handlerflags&2) printf("[enter frame]");
380 if(handlerflags&4) printf("[unload]");
381 if(handlerflags&8) printf("[mouse move]");
382 if(handlerflags&16) printf("[mouse down]");
383 if(handlerflags&32) printf("[mouse up]");
384 if(handlerflags&64) printf("[key down]");
385 if(handlerflags&128) printf("[key up]");
387 if(handlerflags&256) printf("[data]");
388 if(handlerflags&512) printf("[initialize]");
389 if(handlerflags&1024) printf("[mouse press]");
390 if(handlerflags&2048) printf("[mouse release]");
391 if(handlerflags&4096) printf("[mouse release outside]");
392 if(handlerflags&8192) printf("[mouse rollover]");
393 if(handlerflags&16384) printf("[mouse rollout]");
394 if(handlerflags&32768) printf("[mouse drag over]");
396 if(handlerflags&0x10000) printf("[mouse drag out]");
397 if(handlerflags&0x20000) printf("[key press]");
398 if(handlerflags&0x40000) printf("[construct even]");
399 if(handlerflags&0xfff80000) printf("[???]");
401 void handleVideoStream(TAG*tag, char*prefix)
403 U16 id = swf_GetU16(tag);
404 U16 frames = swf_GetU16(tag);
405 U16 width = swf_GetU16(tag);
406 U16 height = swf_GetU16(tag);
407 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
408 U8 codec = swf_GetU8(tag);
409 printf(" (%d frames, %dx%d", frames, width, height);
413 printf(" sorenson h.263)");
415 printf(" codec 0x%02x)", codec);
417 void handleVideoFrame(TAG*tag, char*prefix)
419 U32 code, version, reference, sizeflags;
420 U32 width=0, height=0;
422 U16 id = swf_GetU16(tag);
423 U16 frame = swf_GetU16(tag);
424 U8 deblock,flags, tmp, bit;
426 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
427 printf(" (frame %d) ", frame);
429 /* video packet follows */
430 code = swf_GetBits(tag, 17);
431 version = swf_GetBits(tag, 5);
432 reference = swf_GetBits(tag, 8);
434 sizeflags = swf_GetBits(tag, 3);
437 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
438 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
439 case 2: width = 352; height = 288; break;
440 case 3: width = 176; height = 144; break;
441 case 4: width = 128; height = 96; break;
442 case 5: width = 320; height = 240; break;
443 case 6: width = 160; height = 120; break;
444 case 7: width = -1; height = -1;/*reserved*/ break;
446 printf("%dx%d ", width, height);
447 type = swf_GetBits(tag, 2);
448 printf("%s", types[type]);
450 deblock = swf_GetBits(tag, 1);
452 printf(" deblock ", deblock);
453 quantizer = swf_GetBits(tag, 5);
454 printf(" quant: %d ", quantizer);
457 void handlePlaceObject2(TAG*tag, char*prefix)
459 U8 flags = swf_GetU8(tag);
463 int ppos[3] = {0,0,0};
464 swf_GetU16(tag); //depth
467 if(flags&2) swf_GetU16(tag); //id
469 swf_GetMatrix(tag,&m);
471 ppos[0] += sprintf(pstr[0], "| Matrix ");
472 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
473 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
477 swf_GetCXForm(tag, &cx, 1);
479 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
480 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);
481 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
485 U16 ratio = swf_GetU16(tag); //ratio
487 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
488 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
489 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
493 U16 clip = swf_GetU16(tag); //clip
495 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
496 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
497 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
500 if(flags&32) { while(swf_GetU8(tag)); }
501 if(placements && ppos[0]) {
503 printf("%s %s\n", prefix, pstr[0]);
504 printf("%s %s\n", prefix, pstr[1]);
505 printf("%s %s", prefix, pstr[2]);
514 reserved = swf_GetU16(tag); // must be 0
515 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
517 printf("Unknown parameter field not zero: %04x\n", reserved);
520 printf("global flags: %04x\n", globalflags);
522 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
524 handlerflags = swf_GetU32(tag);
527 while(handlerflags) {
532 globalflags &= ~handlerflags;
533 printf("%s flags %08x ",prefix, handlerflags);
534 printhandlerflags(handlerflags);
535 length = swf_GetU32(tag);
536 printf(", %d bytes actioncode\n",length);
537 a = swf_ActionGet(tag);
538 swf_DumpActions(a,prefix);
541 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
543 if(globalflags) // should go to sterr.
544 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
546 printf(" has action code\n");
551 void handlePlaceObject(TAG*tag, char*prefix)
553 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
555 U16 id = swf_GetU16(tag);
556 U16 depth = swf_GetU16(tag);
559 swf_GetMatrix(tag, &matrix);
560 swf_GetCXForm(tag, &cxform, 0);
563 swf_SetU16(tag2, depth);
564 swf_SetMatrix(tag2, &matrix);
565 swf_SetCXForm(tag2, &cxform, 1);
567 handlePlaceObject2(tag2, prefix);
570 char* fillstyle2str(FILLSTYLE*style)
572 switch(style->type) {
574 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
576 case 0x10: case 0x12:
577 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
579 case 0x40: case 0x41:
580 /* TODO: display information about that bitmap */
581 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
584 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
588 char* linestyle2str(LINESTYLE*style)
590 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
594 void handleShape(TAG*tag, char*prefix)
602 swf_ParseDefineShape(tag, &shape);
604 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
606 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
611 else printf("%s | (Neither line nor fill styles)\n", prefix);
614 printf("%s", prefix);
615 if(t < shape.numfillstyles) {
616 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
620 if(t < shape.numlinestyles) {
621 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
626 printf("%s |\n", prefix);
630 printf("%s | fill: %02d/%02d line:%02d - ",
635 if(line->type == moveTo) {
636 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
637 } else if(line->type == lineTo) {
638 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
639 } else if(line->type == splineTo) {
640 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
641 line->sx/20.0, line->sy/20.0,
642 line->x/20.0, line->y/20.0
647 printf("%s |\n", prefix);
650 void fontcallback1(void*self, U16 id,U8 * name)
654 void fontcallback2(void*self, U16 id,U8 * name)
656 swf_FontExtract(&swf,id,&fonts[fontnum]);
660 static U8 printable(U8 a)
662 if(a<32 || a==127) return '.';
665 void hexdumpTag(TAG*tag, char* prefix)
669 printf(" %s-=> ",prefix);
670 for(t=0;t<tag->len;t++) {
671 printf("%02x ", tag->data[t]);
672 ascii[t&15] = printable(tag->data[t]);
673 if((t && ((t&15)==15)) || (t==tag->len-1))
677 for(s=p-1;s<16;s++) {
681 printf(" %s\n", ascii);
683 printf(" %s\n %s-=> ",ascii,prefix);
688 void handleExportAssets(TAG*tag, char* prefix)
694 num = swf_GetU16(tag);
697 id = swf_GetU16(tag);
698 name = swf_GetString(tag);
699 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
703 void dumperror(const char* format, ...)
708 va_start(arglist, format);
709 vsprintf(buf, format, arglist);
713 printf("==== Error: %s ====\n", buf);
716 static char strbuf[800];
719 char* timestring(double f)
721 int hours = (int)(f/3600);
722 int minutes = (int)((f-hours*3600)/60);
723 int seconds = (int)((f-hours*3600-minutes*60));
724 int useconds = (int)((f-(int)f)*1000+0.5);
727 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
728 return &strbuf[bufpos];
731 int main (int argc,char ** argv)
739 char issprite = 0; // are we inside a sprite definition?
742 char* spriteframelabel = 0;
743 char* framelabel = 0;
747 memset(idtab,0,65536);
749 processargs(argc, argv);
753 fprintf(stderr, "You must supply a filename.\n");
757 f = open(filename,O_RDONLY|O_BINARY);
762 sprintf(buffer, "Couldn't open %s", filename);
766 if FAILED(swf_ReadSWF(f,&swf))
768 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
775 if(statbuf.st_size != swf.fileSize && !swf.compressed)
776 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
777 statbuf.st_size, swf.fileSize);
778 filesize = statbuf.st_size;
783 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
784 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
788 printf("-X %d", xsize);
794 printf("-Y %d", ysize);
800 printf("-r %.2f", swf.frameRate/256.0);
806 printf("-f %d", swf.frameCount);
813 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
814 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
815 if(swf.fileVersion>9) {
816 fprintf(stderr, "Fileversion>9\n");
819 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
821 //" BGCOLOR=#ffffffff\n"?
823 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
824 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
825 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
826 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
827 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
828 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
829 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
830 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
831 " TYPE=\"application/x-shockwave-flash\"\n"
832 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
834 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
835 filename, filename, xsize, ysize);
838 printf("[HEADER] File version: %d\n", swf.fileVersion);
840 printf("[HEADER] File is zlib compressed.");
841 if(filesize && swf.fileSize)
842 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
846 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
847 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
848 printf("[HEADER] Frame count: %d\n",swf.frameCount);
849 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
850 if(swf.movieSize.xmin)
851 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
854 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
855 if(swf.movieSize.ymin)
856 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
864 swf_FontEnumerate(&swf,&fontcallback1, 0);
865 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
867 swf_FontEnumerate(&swf,&fontcallback2, 0);
871 char*name = swf_TagGetName(tag);
874 dumperror("Unknown tag:0x%03x", tag->id);
878 if(swf_TagGetName(tag)) {
879 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
881 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
884 if(tag->id == ST_FREECHARACTER) {
885 U16 id = swf_GetU16(tag);
889 if(swf_isDefiningTag(tag)) {
890 U16 id = swf_GetDefineID(tag);
891 printf(" defines id %04d", id);
893 dumperror("Id %04d is defined more than once.", id);
896 else if(swf_isPseudoDefiningTag(tag)) {
897 U16 id = swf_GetDefineID(tag);
898 printf(" adds information to id %04d", id);
900 dumperror("Id %04d is not yet defined.\n", id);
902 else if(tag->id == ST_PLACEOBJECT) {
903 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
905 printf(" name \"%s\"",swf_GetName(tag));
907 else if(tag->id == ST_PLACEOBJECT2) {
914 printf(" id %04d",swf_GetPlaceID(tag));
918 printf(" at depth %04d", swf_GetDepth(tag));
920 if(tag->data[0]&64) {
922 swf_GetPlaceObject(tag, &po);
923 printf(" (clip to %04d)", po.clipdepth);
924 swf_PlaceObjectFree(&po);
927 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+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
989 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
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 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1055 SRECT r = swf_GetDefineBBox(tag);
1056 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1063 sprintf(myprefix, " %s", prefix);
1065 if(tag->id == ST_DEFINESPRITE) {
1066 sprintf(prefix, " ");
1068 dumperror("Sprite definition inside a sprite definition");
1072 spriteframelabel = 0;
1074 else if(tag->id == ST_END) {
1077 spriteframelabel = 0;
1079 dumperror("End Tag not empty");
1081 else if(tag->id == ST_EXPORTASSETS) {
1082 handleExportAssets(tag, myprefix);
1084 else if(tag->id == ST_DOACTION && action) {
1086 actions = swf_ActionGet(tag);
1087 swf_DumpActions(actions, myprefix);
1089 else if(tag->id == ST_DOINITACTION && action) {
1091 swf_GetU16(tag); // id
1092 actions = swf_ActionGet(tag);
1093 swf_DumpActions(actions, myprefix);
1095 else if(tag->id == ST_DEFINEBUTTON && action) {
1096 dumpButtonActions(tag, myprefix);
1098 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1099 dumpButton2Actions(tag, myprefix);
1101 else if(tag->id == ST_PLACEOBJECT) {
1102 handlePlaceObject(tag, myprefix);
1104 else if(tag->id == ST_PLACEOBJECT2) {
1105 handlePlaceObject2(tag, myprefix);
1107 else if(tag->id == ST_DEFINESHAPE ||
1108 tag->id == ST_DEFINESHAPE2 ||
1109 tag->id == ST_DEFINESHAPE3) {
1111 handleShape(tag, myprefix);
1114 if(tag->len && used) {
1115 int num = swf_GetNumUsedIDs(tag);
1119 used = (int*)malloc(sizeof(int)*num);
1120 swf_GetUsedIDs(tag, used);
1121 printf("%s%suses IDs: ", indent, prefix);
1122 for(t=0;t<num;t++) {
1124 swf_SetTagPos(tag, used[t]);
1125 id = swf_GetU16(tag);
1126 printf("%d%s", id, t<num-1?", ":"");
1128 dumperror("Id %04d is not yet defined.\n", id);
1135 if(tag->len && hex) {
1136 hexdumpTag(tag, prefix);