2 Shows the structure of a swf file
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include "../config.h"
24 #ifdef HAVE_SYS_STAT_H
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
40 #include "../lib/rfxswf.h"
41 #include "../lib/args.h"
43 static char * filename = 0;
45 /* idtab stores the ids which are defined in the file. This allows us
46 to detect errors in the file. (i.e. ids which are defined more than
48 static char idtab[65536];
49 static char * indent = " ";
51 static int placements = 0;
52 static int action = 0;
56 static int showtext = 0;
57 static int showshapes = 0;
61 static int cumulative = 0;
63 static struct options_t options[] = {
83 int args_callback_option(char*name,char*val)
85 if(!strcmp(name, "V")) {
86 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
89 else if(name[0]=='a') {
93 else if(name[0]=='p') {
97 else if(name[0]=='t') {
101 else if(name[0]=='s') {
105 else if(name[0]=='e') {
109 else if(name[0]=='c') {
113 else if(name[0]=='E') {
118 else if(name[0]=='X') {
122 else if(name[0]=='Y') {
126 else if(name[0]=='r') {
130 else if(name[0]=='f') {
134 else if(name[0]=='d') {
138 else if(name[0]=='u') {
142 else if(name[0]=='b') {
146 else if(name[0]=='D') {
147 action = placements = showtext = showshapes = 1;
151 printf("Unknown option: -%s\n", name);
157 int args_callback_longoption(char*name,char*val)
159 return args_long2shortoption(options, name, val);
161 void args_callback_usage(char *name)
164 printf("Usage: %s [-atpdu] file.swf\n", name);
166 printf("-h , --help Print short help message and exit\n");
167 printf("-D , --full Show everything. Same as -atp\n");
168 printf("-V , --version Print version info and exit\n");
169 printf("-e , --html Print out html code for embedding the file\n");
170 printf("-a , --action Disassemble action tags\n");
171 printf("-t , --text Show text fields (like swfstrings).\n");
172 printf("-s , --shapes Show shape coordinates/styles\n");
173 printf("-p , --placements Show placement information\n");
174 printf("-b , --bbox Print tag's bounding boxes\n");
175 printf("-X , --width Prints out a string of the form \"-X width\".\n");
176 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
177 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
178 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
179 printf("-d , --hex Print hex output of tag data, too.\n");
180 printf("-u , --used Show referred IDs for each Tag.\n");
183 int args_callback_command(char*name,char*val)
186 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
194 char* testfunc(char*str)
196 printf("%s: %s\n", what, str);
200 void dumpButton2Actions(TAG*tag, char*prefix)
206 oldTagPos = swf_GetTagPos(tag);
208 // scan DefineButton2 Record
210 swf_GetU16(tag); // Character ID
211 swf_GetU8(tag); // Flags;
213 offsetpos = swf_GetTagPos(tag); // first offset
216 while (swf_GetU8(tag)) // state -> parse ButtonRecord
217 { swf_GetU16(tag); // id
218 swf_GetU16(tag); // layer
219 swf_GetMatrix(tag,NULL); // matrix
220 swf_GetCXForm(tag,NULL,1); // cxform
227 if(tag->pos >= tag->len)
230 offsetpos = swf_GetU16(tag);
231 condition = swf_GetU16(tag); // condition
233 actions = swf_ActionGet(tag);
234 printf("%s condition %04x\n", prefix, condition);
235 swf_DumpActions(actions, prefix);
238 swf_SetTagPos(tag,oldTagPos);
242 void dumpButtonActions(TAG*tag, char*prefix)
245 swf_GetU16(tag); // id
246 while (swf_GetU8(tag)) // state -> parse ButtonRecord
247 { swf_GetU16(tag); // id
248 swf_GetU16(tag); // layer
249 swf_GetMatrix(tag,NULL); // matrix
251 actions = swf_ActionGet(tag);
252 swf_DumpActions(actions, prefix);
259 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
262 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
263 for(t=0;t<fontnum;t++)
265 if(fonts[t]->id == fontid) {
275 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
276 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
279 if(fonts[font]->glyph2ascii[glyphs[t]])
280 a = fonts[font]->glyph2ascii[glyphs[t]];
290 printf("\\x%x", (int)a);
295 void handleText(TAG*tag)
298 swf_ParseDefineText(tag,textcallback, 0);
301 void handleDefineSound(TAG*tag)
303 U16 id = swf_GetU16(tag);
304 U8 flags = swf_GetU8(tag);
305 int compression = (flags>>4)&3;
306 int rate = (flags>>2)&3;
307 int bits = flags&2?16:8;
308 int stereo = flags&1;
310 if(compression == 0) printf("Raw ");
311 else if(compression == 1) printf("ADPCM ");
312 else if(compression == 2) printf("MP3 ");
314 if(rate == 0) printf("5.5Khz ");
315 if(rate == 1) printf("11Khz ");
316 if(rate == 2) printf("22Khz ");
317 if(rate == 3) printf("44Khz ");
318 printf("%dBit ", bits);
319 if(stereo) printf("stereo");
324 void handleDefineBits(TAG*tag)
330 id = swf_GetU16(tag);
331 mode = swf_GetU8(tag);
332 width = swf_GetU16(tag);
333 height = swf_GetU16(tag);
334 printf(" image %dx%d",width,height);
335 if(mode == 3) printf(" (8 bpp)");
336 else if(mode == 4) printf(" (16 bpp)");
337 else if(mode == 5) printf(" (32 bpp)");
338 else printf(" (? bpp)");
341 void handleEditText(TAG*tag)
346 id = swf_GetU16(tag);
349 //swf_ResetReadBits(tag);
355 flags = swf_GetBits(tag,16);
356 if(flags & ET_HASFONT) {
357 swf_GetU16(tag); //font
358 swf_GetU16(tag); //fontheight
360 if(flags & ET_HASTEXTCOLOR) {
361 swf_GetU8(tag); //rgba
366 if(flags & ET_HASMAXLENGTH) {
367 swf_GetU16(tag); //maxlength
369 if(flags & ET_HASLAYOUT) {
370 swf_GetU8(tag); //align
371 swf_GetU16(tag); //left margin
372 swf_GetU16(tag); //right margin
373 swf_GetU16(tag); //indent
374 swf_GetU16(tag); //leading
376 printf(" variable \"%s\" ", &tag->data[tag->pos]);
377 if(flags & ET_HTML) printf("(html)");
378 if(flags & ET_NOSELECT) printf("(noselect)");
379 if(flags & ET_PASSWORD) printf("(password)");
380 if(flags & ET_READONLY) printf("(readonly)");
382 if(flags & (ET_X1 | ET_X3 ))
384 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
387 while(tag->data[tag->pos++]);
388 if(flags & ET_HASTEXT)
389 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
392 void printhandlerflags(U32 handlerflags)
394 if(handlerflags&1) printf("[on load]");
395 if(handlerflags&2) printf("[enter frame]");
396 if(handlerflags&4) printf("[unload]");
397 if(handlerflags&8) printf("[mouse move]");
398 if(handlerflags&16) printf("[mouse down]");
399 if(handlerflags&32) printf("[mouse up]");
400 if(handlerflags&64) printf("[key down]");
401 if(handlerflags&128) printf("[key up]");
403 if(handlerflags&256) printf("[data]");
404 if(handlerflags&512) printf("[initialize]");
405 if(handlerflags&1024) printf("[mouse press]");
406 if(handlerflags&2048) printf("[mouse release]");
407 if(handlerflags&4096) printf("[mouse release outside]");
408 if(handlerflags&8192) printf("[mouse rollover]");
409 if(handlerflags&16384) printf("[mouse rollout]");
410 if(handlerflags&32768) printf("[mouse drag over]");
412 if(handlerflags&0x10000) printf("[mouse drag out]");
413 if(handlerflags&0x20000) printf("[key press]");
414 if(handlerflags&0x40000) printf("[construct even]");
415 if(handlerflags&0xfff80000) printf("[???]");
417 void handleVideoStream(TAG*tag, char*prefix)
419 U16 id = swf_GetU16(tag);
420 U16 frames = swf_GetU16(tag);
421 U16 width = swf_GetU16(tag);
422 U16 height = swf_GetU16(tag);
423 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
424 U8 codec = swf_GetU8(tag);
425 printf(" (%d frames, %dx%d", frames, width, height);
429 printf(" sorenson h.263)");
431 printf(" codec 0x%02x)", codec);
433 void handleVideoFrame(TAG*tag, char*prefix)
435 U32 code, version, reference, sizeflags;
436 U32 width=0, height=0;
438 U16 id = swf_GetU16(tag);
439 U16 frame = swf_GetU16(tag);
440 U8 deblock,flags, tmp, bit;
442 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
443 printf(" (frame %d) ", frame);
445 /* video packet follows */
446 code = swf_GetBits(tag, 17);
447 version = swf_GetBits(tag, 5);
448 reference = swf_GetBits(tag, 8);
450 sizeflags = swf_GetBits(tag, 3);
453 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
454 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
455 case 2: width = 352; height = 288; break;
456 case 3: width = 176; height = 144; break;
457 case 4: width = 128; height = 96; break;
458 case 5: width = 320; height = 240; break;
459 case 6: width = 160; height = 120; break;
460 case 7: width = -1; height = -1;/*reserved*/ break;
462 printf("%dx%d ", width, height);
463 type = swf_GetBits(tag, 2);
464 printf("%s", types[type]);
466 deblock = swf_GetBits(tag, 1);
468 printf(" deblock ", deblock);
469 quantizer = swf_GetBits(tag, 5);
470 printf(" quant: %d ", quantizer);
473 void handlePlaceObject2(TAG*tag, char*prefix)
479 int ppos[3] = {0,0,0};
480 swf_SetTagPos(tag, 0);
481 flags = swf_GetU8(tag);
482 swf_GetU16(tag); //depth
485 if(flags&2) swf_GetU16(tag); //id
487 swf_GetMatrix(tag,&m);
489 ppos[0] += sprintf(pstr[0], "| Matrix ");
490 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
491 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
495 swf_GetCXForm(tag, &cx, 1);
497 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
498 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);
499 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
503 U16 ratio = swf_GetU16(tag); //ratio
505 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
506 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
507 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
511 U16 clip = swf_GetU16(tag); //clip
513 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
514 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
515 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
518 if(flags&32) { while(swf_GetU8(tag)); }
519 if(placements && ppos[0]) {
521 printf("%s %s\n", prefix, pstr[0]);
522 printf("%s %s\n", prefix, pstr[1]);
523 printf("%s %s", prefix, pstr[2]);
532 reserved = swf_GetU16(tag); // must be 0
533 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
535 printf("Unknown parameter field not zero: %04x\n", reserved);
538 printf("global flags: %04x\n", globalflags);
540 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
542 handlerflags = swf_GetU32(tag);
545 while(handlerflags) {
550 globalflags &= ~handlerflags;
551 printf("%s flags %08x ",prefix, handlerflags);
552 printhandlerflags(handlerflags);
553 length = swf_GetU32(tag);
554 printf(", %d bytes actioncode\n",length);
555 a = swf_ActionGet(tag);
556 swf_DumpActions(a,prefix);
559 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
561 if(globalflags) // should go to sterr.
562 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
564 printf(" has action code\n");
569 void handlePlaceObject(TAG*tag, char*prefix)
571 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
576 swf_SetTagPos(tag, 0);
577 id = swf_GetU16(tag);
578 depth = swf_GetU16(tag);
579 swf_GetMatrix(tag, &matrix);
580 swf_GetCXForm(tag, &cxform, 0);
582 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
583 swf_SetU16(tag2, depth);
584 swf_SetU16(tag2, id);
585 swf_SetMatrix(tag2, &matrix);
586 swf_SetCXForm(tag2, &cxform, 1);
588 handlePlaceObject2(tag2, prefix);
591 char* fillstyle2str(FILLSTYLE*style)
593 switch(style->type) {
595 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
597 case 0x10: case 0x12:
598 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
601 /* TODO: display information about that bitmap */
602 sprintf(stylebuf, "BITMAPt %d", style->id_bitmap);
603 /* TODO: show matrix */
606 /* TODO: display information about that bitmap */
607 sprintf(stylebuf, "BITMAPc %d", style->id_bitmap);
608 /* TODO: show matrix */
611 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
615 char* linestyle2str(LINESTYLE*style)
617 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
621 void handleShape(TAG*tag, char*prefix)
629 swf_ParseDefineShape(tag, &shape);
631 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
633 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
638 else printf("%s | (Neither line nor fill styles)\n", prefix);
641 printf("%s", prefix);
642 if(t < shape.numfillstyles) {
643 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
647 if(t < shape.numlinestyles) {
648 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
653 printf("%s |\n", prefix);
657 printf("%s | fill: %02d/%02d line:%02d - ",
662 if(line->type == moveTo) {
663 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
664 } else if(line->type == lineTo) {
665 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
666 } else if(line->type == splineTo) {
667 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
668 line->sx/20.0, line->sy/20.0,
669 line->x/20.0, line->y/20.0
674 printf("%s |\n", prefix);
677 void fontcallback1(void*self, U16 id,U8 * name)
681 void fontcallback2(void*self, U16 id,U8 * name)
683 swf_FontExtract(&swf,id,&fonts[fontnum]);
687 static U8 printable(U8 a)
689 if(a<32 || a==127) return '.';
692 void hexdumpTag(TAG*tag, char* prefix)
696 printf(" %s-=> ",prefix);
697 for(t=0;t<tag->len;t++) {
698 printf("%02x ", tag->data[t]);
699 ascii[t&15] = printable(tag->data[t]);
700 if((t && ((t&15)==15)) || (t==tag->len-1))
704 for(s=p-1;s<16;s++) {
708 printf(" %s\n", ascii);
710 printf(" %s\n %s-=> ",ascii,prefix);
715 void handleExportAssets(TAG*tag, char* prefix)
721 num = swf_GetU16(tag);
724 id = swf_GetU16(tag);
725 name = swf_GetString(tag);
726 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
730 void dumperror(const char* format, ...)
735 va_start(arglist, format);
736 vsprintf(buf, format, arglist);
740 printf("==== Error: %s ====\n", buf);
743 static char strbuf[800];
746 char* timestring(double f)
748 int hours = (int)(f/3600);
749 int minutes = (int)((f-hours*3600)/60);
750 int seconds = (int)((f-hours*3600-minutes*60));
751 int useconds = (int)((f-(int)f)*1000+0.5);
754 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
755 return &strbuf[bufpos];
758 int main (int argc,char ** argv)
766 char issprite = 0; // are we inside a sprite definition?
769 char* spriteframelabel = 0;
770 char* framelabel = 0;
775 memset(idtab,0,65536);
777 processargs(argc, argv);
781 fprintf(stderr, "You must supply a filename.\n");
785 f = open(filename,O_RDONLY|O_BINARY);
790 sprintf(buffer, "Couldn't open %s", filename);
794 if FAILED(swf_ReadSWF(f,&swf))
796 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
803 if(statbuf.st_size != swf.fileSize && !swf.compressed)
804 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
805 statbuf.st_size, swf.fileSize);
806 filesize = statbuf.st_size;
811 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
812 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
816 printf("-X %d", xsize);
822 printf("-Y %d", ysize);
828 printf("-r %.2f", swf.frameRate/256.0);
834 printf("-f %d", swf.frameCount);
841 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
842 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
843 if(swf.fileVersion>9) {
844 fprintf(stderr, "Fileversion>9\n");
849 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
850 "<param name=\"movie\" value=\"%s\"/>\n"
851 "<param name=\"play\" value=\"true\"/>\n"
852 "<param name=\"loop\" value=\"false\"/>\n"
853 "<param name=\"quality\" value=\"high\"/>\n"
854 "<param name=\"loop\" value=\"false\"/>\n"
855 "</object>\n\n", filename, xsize, ysize, filename);
857 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
859 //" BGCOLOR=#ffffffff\n"?
861 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
862 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
863 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
864 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
865 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
866 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
867 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
868 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
869 " TYPE=\"application/x-shockwave-flash\"\n"
870 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
872 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
873 filename, filename, xsize, ysize);
877 printf("[HEADER] File version: %d\n", swf.fileVersion);
879 printf("[HEADER] File is zlib compressed.");
880 if(filesize && swf.fileSize)
881 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
885 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
886 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
887 printf("[HEADER] Frame count: %d\n",swf.frameCount);
888 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
889 if(swf.movieSize.xmin)
890 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
893 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
894 if(swf.movieSize.ymin)
895 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
903 swf_FontEnumerate(&swf,&fontcallback1, 0);
904 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
906 swf_FontEnumerate(&swf,&fontcallback2, 0);
910 char*name = swf_TagGetName(tag);
913 dumperror("Unknown tag:0x%03x", tag->id);
918 name = "UNKNOWN TAG";
922 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
924 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
927 if(tag->id == ST_FREECHARACTER) {
928 U16 id = swf_GetU16(tag);
932 if(swf_isDefiningTag(tag)) {
933 U16 id = swf_GetDefineID(tag);
934 printf(" defines id %04d", id);
936 dumperror("Id %04d is defined more than once.", id);
939 else if(swf_isPseudoDefiningTag(tag)) {
940 U16 id = swf_GetDefineID(tag);
941 printf(" adds information to id %04d", id);
943 dumperror("Id %04d is not yet defined.\n", id);
945 else if(tag->id == ST_PLACEOBJECT) {
946 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
948 printf(" name \"%s\"",swf_GetName(tag));
950 else if(tag->id == ST_PLACEOBJECT2) {
957 printf(" id %04d",swf_GetPlaceID(tag));
961 printf(" at depth %04d", swf_GetDepth(tag));
963 swf_SetTagPos(tag, 0);
964 if(tag->data[0]&64) {
966 swf_GetPlaceObject(tag, &po);
967 printf(" (clip to %04d)", po.clipdepth);
968 swf_PlaceObjectFree(&po);
971 printf(" name \"%s\"",swf_GetName(tag));
974 else if(tag->id == ST_REMOVEOBJECT) {
975 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
977 else if(tag->id == ST_REMOVEOBJECT2) {
978 printf(" removes object from depth %04d", swf_GetDepth(tag));
980 else if(tag->id == ST_FREECHARACTER) {
981 printf(" frees object %04d", swf_GetPlaceID(tag));
983 else if(tag->id == ST_STARTSOUND) {
986 id = swf_GetU16(tag);
987 flags = swf_GetU8(tag);
989 printf(" stops sound with id %04d", id);
991 printf(" starts sound with id %04d", id);
993 printf(" (if not already playing)");
999 printf(" looping %d times", swf_GetU16(tag));
1002 else if(tag->id == ST_FRAMELABEL) {
1003 int l = strlen(tag->data);
1004 printf(" \"%s\"", tag->data);
1005 if((l+1) < tag->len) {
1006 printf(" has %d extra bytes", tag->len-1-l);
1007 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1008 printf(" (ANCHOR)");
1010 if((framelabel && !issprite) ||
1011 (spriteframelabel && issprite)) {
1012 dumperror("Frame %d has more than one label",
1013 issprite?spriteframe:mainframe);
1015 if(issprite) spriteframelabel = tag->data;
1016 else framelabel = tag->data;
1018 else if(tag->id == ST_SHOWFRAME) {
1019 char*label = issprite?spriteframelabel:framelabel;
1020 int frame = issprite?spriteframe:mainframe;
1023 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1025 if(issprite) spriteframe++;
1031 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1033 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1034 timestring(frame*(256.0/(swf.frameRate+0.1))),
1035 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1038 printf(" (label \"%s\")", label);
1039 if(issprite) {spriteframe++; spriteframelabel = 0;}
1040 if(!issprite) {mainframe++; framelabel = 0;}
1043 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1044 U8 r = swf_GetU8(tag);
1045 U8 g = swf_GetU8(tag);
1046 U8 b = swf_GetU8(tag);
1047 printf(" (%02x/%02x/%02x)\n",r,g,b);
1049 else if(tag->id == ST_PROTECT) {
1051 printf(" %s\n", swf_GetString(tag));
1056 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1057 tag->id == ST_DEFINEBITSLOSSLESS2) {
1058 handleDefineBits(tag);
1061 else if(tag->id == ST_DEFINESOUND) {
1062 handleDefineSound(tag);
1065 else if(tag->id == ST_VIDEOFRAME) {
1066 handleVideoFrame(tag, myprefix);
1069 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1070 handleVideoStream(tag, myprefix);
1073 else if(tag->id == ST_DEFINEEDITTEXT) {
1074 handleEditText(tag);
1077 else if(tag->id == ST_DEFINEMOVIE) {
1078 U16 id = swf_GetU16(tag);
1079 char*s = swf_GetString(tag);
1080 printf(" URL: %s\n", s);
1082 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1088 else if(tag->id == ST_PLACEOBJECT2) {
1090 else if(tag->id == ST_NAMECHARACTER) {
1092 printf(" \"%s\"\n", swf_GetString(tag));
1098 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1099 SRECT r = swf_GetDefineBBox(tag);
1100 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1107 sprintf(myprefix, " %s", prefix);
1109 if(tag->id == ST_DEFINESPRITE) {
1110 sprintf(prefix, " ");
1112 dumperror("Sprite definition inside a sprite definition");
1116 spriteframelabel = 0;
1118 else if(tag->id == ST_END) {
1121 spriteframelabel = 0;
1123 dumperror("End Tag not empty");
1125 else if(tag->id == ST_EXPORTASSETS) {
1126 handleExportAssets(tag, myprefix);
1128 else if(tag->id == ST_DOACTION && action) {
1130 actions = swf_ActionGet(tag);
1131 swf_DumpActions(actions, myprefix);
1133 else if(tag->id == ST_DOINITACTION && action) {
1135 swf_GetU16(tag); // id
1136 actions = swf_ActionGet(tag);
1137 swf_DumpActions(actions, myprefix);
1139 else if(tag->id == ST_DEFINEBUTTON && action) {
1140 dumpButtonActions(tag, myprefix);
1142 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1143 dumpButton2Actions(tag, myprefix);
1145 else if(tag->id == ST_PLACEOBJECT) {
1146 handlePlaceObject(tag, myprefix);
1148 else if(tag->id == ST_PLACEOBJECT2) {
1149 handlePlaceObject2(tag, myprefix);
1151 else if(tag->id == ST_DEFINESHAPE ||
1152 tag->id == ST_DEFINESHAPE2 ||
1153 tag->id == ST_DEFINESHAPE3) {
1155 handleShape(tag, myprefix);
1158 if(tag->len && used) {
1159 int num = swf_GetNumUsedIDs(tag);
1163 used = (int*)malloc(sizeof(int)*num);
1164 swf_GetUsedIDs(tag, used);
1165 printf("%s%suses IDs: ", indent, prefix);
1166 for(t=0;t<num;t++) {
1168 swf_SetTagPos(tag, used[t]);
1169 id = swf_GetU16(tag);
1170 printf("%d%s", id, t<num-1?", ":"");
1172 dumperror("Id %04d is not yet defined.\n", id);
1179 if(tag->len && hex) {
1180 hexdumpTag(tag, prefix);