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("-E , --xhtml Print out xhtml code for embedding the file\n");
171 printf("-a , --action Disassemble action tags\n");
172 printf("-t , --text Show text fields (like swfstrings).\n");
173 printf("-s , --shapes Show shape coordinates/styles\n");
174 printf("-p , --placements Show placement information\n");
175 printf("-b , --bbox Print tag's bounding boxes\n");
176 printf("-X , --width Prints out a string of the form \"-X width\".\n");
177 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
178 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
179 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
180 printf("-d , --hex Print hex output of tag data, too.\n");
181 printf("-u , --used Show referred IDs for each Tag.\n");
184 int args_callback_command(char*name,char*val)
187 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
195 char* testfunc(char*str)
197 printf("%s: %s\n", what, str);
201 void dumpButton2Actions(TAG*tag, char*prefix)
207 oldTagPos = swf_GetTagPos(tag);
209 // scan DefineButton2 Record
211 swf_GetU16(tag); // Character ID
212 swf_GetU8(tag); // Flags;
214 offsetpos = swf_GetTagPos(tag); // first offset
217 while (swf_GetU8(tag)) // state -> parse ButtonRecord
218 { swf_GetU16(tag); // id
219 swf_GetU16(tag); // layer
220 swf_GetMatrix(tag,NULL); // matrix
221 swf_GetCXForm(tag,NULL,1); // cxform
228 if(tag->pos >= tag->len)
231 offsetpos = swf_GetU16(tag);
232 condition = swf_GetU16(tag); // condition
234 actions = swf_ActionGet(tag);
235 printf("%s condition %04x\n", prefix, condition);
236 swf_DumpActions(actions, prefix);
239 swf_SetTagPos(tag,oldTagPos);
243 void dumpButtonActions(TAG*tag, char*prefix)
246 swf_GetU16(tag); // id
247 while (swf_GetU8(tag)) // state -> parse ButtonRecord
248 { swf_GetU16(tag); // id
249 swf_GetU16(tag); // layer
250 swf_GetMatrix(tag,NULL); // matrix
252 actions = swf_ActionGet(tag);
253 swf_DumpActions(actions, prefix);
260 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
263 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
264 for(t=0;t<fontnum;t++)
266 if(fonts[t]->id == fontid) {
276 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
277 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
280 if(fonts[font]->glyph2ascii[glyphs[t]])
281 a = fonts[font]->glyph2ascii[glyphs[t]];
291 printf("\\x%x", (int)a);
296 void handleText(TAG*tag)
299 swf_ParseDefineText(tag,textcallback, 0);
302 void handleDefineSound(TAG*tag)
304 U16 id = swf_GetU16(tag);
305 U8 flags = swf_GetU8(tag);
306 int compression = (flags>>4)&3;
307 int rate = (flags>>2)&3;
308 int bits = flags&2?16:8;
309 int stereo = flags&1;
311 if(compression == 0) printf("Raw ");
312 else if(compression == 1) printf("ADPCM ");
313 else if(compression == 2) printf("MP3 ");
315 if(rate == 0) printf("5.5Khz ");
316 if(rate == 1) printf("11Khz ");
317 if(rate == 2) printf("22Khz ");
318 if(rate == 3) printf("44Khz ");
319 printf("%dBit ", bits);
320 if(stereo) printf("stereo");
325 void handleDefineBits(TAG*tag)
331 id = swf_GetU16(tag);
332 mode = swf_GetU8(tag);
333 width = swf_GetU16(tag);
334 height = swf_GetU16(tag);
335 printf(" image %dx%d",width,height);
336 if(mode == 3) printf(" (8 bpp)");
337 else if(mode == 4) printf(" (16 bpp)");
338 else if(mode == 5) printf(" (32 bpp)");
339 else printf(" (? bpp)");
342 void handleEditText(TAG*tag)
347 id = swf_GetU16(tag);
350 //swf_ResetReadBits(tag);
356 flags = swf_GetBits(tag,16);
357 if(flags & ET_HASFONT) {
358 swf_GetU16(tag); //font
359 swf_GetU16(tag); //fontheight
361 if(flags & ET_HASTEXTCOLOR) {
362 swf_GetU8(tag); //rgba
367 if(flags & ET_HASMAXLENGTH) {
368 swf_GetU16(tag); //maxlength
370 if(flags & ET_HASLAYOUT) {
371 swf_GetU8(tag); //align
372 swf_GetU16(tag); //left margin
373 swf_GetU16(tag); //right margin
374 swf_GetU16(tag); //indent
375 swf_GetU16(tag); //leading
377 printf(" variable \"%s\" ", &tag->data[tag->pos]);
378 if(flags & ET_HTML) printf("(html)");
379 if(flags & ET_NOSELECT) printf("(noselect)");
380 if(flags & ET_PASSWORD) printf("(password)");
381 if(flags & ET_READONLY) printf("(readonly)");
383 if(flags & (ET_X1 | ET_X3 ))
385 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
388 while(tag->data[tag->pos++]);
389 if(flags & ET_HASTEXT)
390 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
393 void printhandlerflags(U32 handlerflags)
395 if(handlerflags&1) printf("[on load]");
396 if(handlerflags&2) printf("[enter frame]");
397 if(handlerflags&4) printf("[unload]");
398 if(handlerflags&8) printf("[mouse move]");
399 if(handlerflags&16) printf("[mouse down]");
400 if(handlerflags&32) printf("[mouse up]");
401 if(handlerflags&64) printf("[key down]");
402 if(handlerflags&128) printf("[key up]");
404 if(handlerflags&256) printf("[data]");
405 if(handlerflags&512) printf("[initialize]");
406 if(handlerflags&1024) printf("[mouse press]");
407 if(handlerflags&2048) printf("[mouse release]");
408 if(handlerflags&4096) printf("[mouse release outside]");
409 if(handlerflags&8192) printf("[mouse rollover]");
410 if(handlerflags&16384) printf("[mouse rollout]");
411 if(handlerflags&32768) printf("[mouse drag over]");
413 if(handlerflags&0x10000) printf("[mouse drag out]");
414 if(handlerflags&0x20000) printf("[key press]");
415 if(handlerflags&0x40000) printf("[construct even]");
416 if(handlerflags&0xfff80000) printf("[???]");
418 void handleVideoStream(TAG*tag, char*prefix)
420 U16 id = swf_GetU16(tag);
421 U16 frames = swf_GetU16(tag);
422 U16 width = swf_GetU16(tag);
423 U16 height = swf_GetU16(tag);
424 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
425 U8 codec = swf_GetU8(tag);
426 printf(" (%d frames, %dx%d", frames, width, height);
430 printf(" sorenson h.263)");
432 printf(" codec 0x%02x)", codec);
434 void handleVideoFrame(TAG*tag, char*prefix)
436 U32 code, version, reference, sizeflags;
437 U32 width=0, height=0;
439 U16 id = swf_GetU16(tag);
440 U16 frame = swf_GetU16(tag);
441 U8 deblock,flags, tmp, bit;
443 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
444 printf(" (frame %d) ", frame);
446 /* video packet follows */
447 code = swf_GetBits(tag, 17);
448 version = swf_GetBits(tag, 5);
449 reference = swf_GetBits(tag, 8);
451 sizeflags = swf_GetBits(tag, 3);
454 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
455 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
456 case 2: width = 352; height = 288; break;
457 case 3: width = 176; height = 144; break;
458 case 4: width = 128; height = 96; break;
459 case 5: width = 320; height = 240; break;
460 case 6: width = 160; height = 120; break;
461 case 7: width = -1; height = -1;/*reserved*/ break;
463 printf("%dx%d ", width, height);
464 type = swf_GetBits(tag, 2);
465 printf("%s", types[type]);
467 deblock = swf_GetBits(tag, 1);
469 printf(" deblock ", deblock);
470 quantizer = swf_GetBits(tag, 5);
471 printf(" quant: %d ", quantizer);
474 void handlePlaceObject2(TAG*tag, char*prefix)
480 int ppos[3] = {0,0,0};
481 swf_SetTagPos(tag, 0);
482 flags = swf_GetU8(tag);
483 swf_GetU16(tag); //depth
486 if(flags&2) swf_GetU16(tag); //id
488 swf_GetMatrix(tag,&m);
490 ppos[0] += sprintf(pstr[0], "| Matrix ");
491 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
492 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
496 swf_GetCXForm(tag, &cx, 1);
498 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
499 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);
500 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
504 U16 ratio = swf_GetU16(tag); //ratio
506 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
507 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
508 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
512 U16 clip = swf_GetU16(tag); //clip
514 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
515 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
516 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
519 if(flags&32) { while(swf_GetU8(tag)); }
520 if(placements && ppos[0]) {
522 printf("%s %s\n", prefix, pstr[0]);
523 printf("%s %s\n", prefix, pstr[1]);
524 printf("%s %s", prefix, pstr[2]);
533 reserved = swf_GetU16(tag); // must be 0
534 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
536 printf("Unknown parameter field not zero: %04x\n", reserved);
539 printf("global flags: %04x\n", globalflags);
541 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
543 handlerflags = swf_GetU32(tag);
546 while(handlerflags) {
551 globalflags &= ~handlerflags;
552 printf("%s flags %08x ",prefix, handlerflags);
553 printhandlerflags(handlerflags);
554 length = swf_GetU32(tag);
555 printf(", %d bytes actioncode\n",length);
556 a = swf_ActionGet(tag);
557 swf_DumpActions(a,prefix);
560 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
562 if(globalflags) // should go to sterr.
563 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
565 printf(" has action code\n");
570 void handlePlaceObject(TAG*tag, char*prefix)
572 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
577 swf_SetTagPos(tag, 0);
578 id = swf_GetU16(tag);
579 depth = swf_GetU16(tag);
580 swf_GetMatrix(tag, &matrix);
581 swf_GetCXForm(tag, &cxform, 0);
583 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
584 swf_SetU16(tag2, depth);
585 swf_SetU16(tag2, id);
586 swf_SetMatrix(tag2, &matrix);
587 swf_SetCXForm(tag2, &cxform, 1);
589 handlePlaceObject2(tag2, prefix);
592 char* fillstyle2str(FILLSTYLE*style)
594 switch(style->type) {
596 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
598 case 0x10: case 0x12:
599 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
602 /* TODO: display information about that bitmap */
603 sprintf(stylebuf, "BITMAPt %d", style->id_bitmap);
604 /* TODO: show matrix */
607 /* TODO: display information about that bitmap */
608 sprintf(stylebuf, "BITMAPc %d", style->id_bitmap);
609 /* TODO: show matrix */
612 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
616 char* linestyle2str(LINESTYLE*style)
618 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
622 void handleShape(TAG*tag, char*prefix)
630 swf_ParseDefineShape(tag, &shape);
632 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
634 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
639 else printf("%s | (Neither line nor fill styles)\n", prefix);
642 printf("%s", prefix);
643 if(t < shape.numfillstyles) {
644 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
648 if(t < shape.numlinestyles) {
649 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
654 printf("%s |\n", prefix);
658 printf("%s | fill: %02d/%02d line:%02d - ",
663 if(line->type == moveTo) {
664 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
665 } else if(line->type == lineTo) {
666 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
667 } else if(line->type == splineTo) {
668 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
669 line->sx/20.0, line->sy/20.0,
670 line->x/20.0, line->y/20.0
675 printf("%s |\n", prefix);
678 void fontcallback1(void*self, U16 id,U8 * name)
682 void fontcallback2(void*self, U16 id,U8 * name)
684 swf_FontExtract(&swf,id,&fonts[fontnum]);
688 static U8 printable(U8 a)
690 if(a<32 || a==127) return '.';
693 void hexdumpTag(TAG*tag, char* prefix)
697 printf(" %s-=> ",prefix);
698 for(t=0;t<tag->len;t++) {
699 printf("%02x ", tag->data[t]);
700 ascii[t&15] = printable(tag->data[t]);
701 if((t && ((t&15)==15)) || (t==tag->len-1))
705 for(s=p-1;s<16;s++) {
709 printf(" %s\n", ascii);
711 printf(" %s\n %s-=> ",ascii,prefix);
716 void handleExportAssets(TAG*tag, char* prefix)
722 num = swf_GetU16(tag);
725 id = swf_GetU16(tag);
726 name = swf_GetString(tag);
727 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
731 void dumperror(const char* format, ...)
736 va_start(arglist, format);
737 vsprintf(buf, format, arglist);
741 printf("==== Error: %s ====\n", buf);
744 static char strbuf[800];
747 char* timestring(double f)
749 int hours = (int)(f/3600);
750 int minutes = (int)((f-hours*3600)/60);
751 int seconds = (int)((f-hours*3600-minutes*60));
752 int useconds = (int)((f-(int)f)*1000+0.5);
755 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
756 return &strbuf[bufpos];
759 int main (int argc,char ** argv)
767 char issprite = 0; // are we inside a sprite definition?
770 char* spriteframelabel = 0;
771 char* framelabel = 0;
776 memset(idtab,0,65536);
778 processargs(argc, argv);
782 fprintf(stderr, "You must supply a filename.\n");
786 f = open(filename,O_RDONLY|O_BINARY);
791 sprintf(buffer, "Couldn't open %s", filename);
795 if FAILED(swf_ReadSWF(f,&swf))
797 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
804 if(statbuf.st_size != swf.fileSize && !swf.compressed)
805 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
806 statbuf.st_size, swf.fileSize);
807 filesize = statbuf.st_size;
812 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
813 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
817 printf("-X %d", xsize);
823 printf("-Y %d", ysize);
829 printf("-r %.2f", swf.frameRate/256.0);
835 printf("-f %d", swf.frameCount);
842 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
843 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
844 if(swf.fileVersion>9) {
845 fprintf(stderr, "Fileversion>9\n");
850 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
851 "<param name=\"movie\" value=\"%s\"/>\n"
852 "<param name=\"play\" value=\"true\"/>\n"
853 "<param name=\"loop\" value=\"false\"/>\n"
854 "<param name=\"quality\" value=\"high\"/>\n"
855 "<param name=\"loop\" value=\"false\"/>\n"
856 "</object>\n\n", filename, xsize, ysize, filename);
858 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
860 //" BGCOLOR=#ffffffff\n"?
862 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
863 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
864 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
865 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
866 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
867 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
868 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
869 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
870 " TYPE=\"application/x-shockwave-flash\"\n"
871 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
873 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
874 filename, filename, xsize, ysize);
878 printf("[HEADER] File version: %d\n", swf.fileVersion);
880 printf("[HEADER] File is zlib compressed.");
881 if(filesize && swf.fileSize)
882 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
886 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
887 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
888 printf("[HEADER] Frame count: %d\n",swf.frameCount);
889 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
890 if(swf.movieSize.xmin)
891 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
894 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
895 if(swf.movieSize.ymin)
896 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
904 swf_FontEnumerate(&swf,&fontcallback1, 0);
905 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
907 swf_FontEnumerate(&swf,&fontcallback2, 0);
911 char*name = swf_TagGetName(tag);
914 dumperror("Unknown tag:0x%03x", tag->id);
919 name = "UNKNOWN TAG";
923 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
925 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
928 if(tag->id == ST_FREECHARACTER) {
929 U16 id = swf_GetU16(tag);
933 if(swf_isDefiningTag(tag)) {
934 U16 id = swf_GetDefineID(tag);
935 printf(" defines id %04d", id);
937 dumperror("Id %04d is defined more than once.", id);
940 else if(swf_isPseudoDefiningTag(tag)) {
941 U16 id = swf_GetDefineID(tag);
942 printf(" adds information to id %04d", id);
944 dumperror("Id %04d is not yet defined.\n", id);
946 else if(tag->id == ST_PLACEOBJECT) {
947 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
949 printf(" name \"%s\"",swf_GetName(tag));
951 else if(tag->id == ST_PLACEOBJECT2) {
958 printf(" id %04d",swf_GetPlaceID(tag));
962 printf(" at depth %04d", swf_GetDepth(tag));
964 swf_SetTagPos(tag, 0);
965 if(tag->data[0]&64) {
967 swf_GetPlaceObject(tag, &po);
968 printf(" (clip to %04d)", po.clipdepth);
969 swf_PlaceObjectFree(&po);
972 printf(" name \"%s\"",swf_GetName(tag));
975 else if(tag->id == ST_REMOVEOBJECT) {
976 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
978 else if(tag->id == ST_REMOVEOBJECT2) {
979 printf(" removes object from depth %04d", swf_GetDepth(tag));
981 else if(tag->id == ST_FREECHARACTER) {
982 printf(" frees object %04d", swf_GetPlaceID(tag));
984 else if(tag->id == ST_STARTSOUND) {
987 id = swf_GetU16(tag);
988 flags = swf_GetU8(tag);
990 printf(" stops sound with id %04d", id);
992 printf(" starts sound with id %04d", id);
994 printf(" (if not already playing)");
1000 printf(" looping %d times", swf_GetU16(tag));
1003 else if(tag->id == ST_FRAMELABEL) {
1004 int l = strlen(tag->data);
1005 printf(" \"%s\"", tag->data);
1006 if((l+1) < tag->len) {
1007 printf(" has %d extra bytes", tag->len-1-l);
1008 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1009 printf(" (ANCHOR)");
1011 if((framelabel && !issprite) ||
1012 (spriteframelabel && issprite)) {
1013 dumperror("Frame %d has more than one label",
1014 issprite?spriteframe:mainframe);
1016 if(issprite) spriteframelabel = tag->data;
1017 else framelabel = tag->data;
1019 else if(tag->id == ST_SHOWFRAME) {
1020 char*label = issprite?spriteframelabel:framelabel;
1021 int frame = issprite?spriteframe:mainframe;
1024 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1026 if(issprite) spriteframe++;
1032 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1034 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1035 timestring(frame*(256.0/(swf.frameRate+0.1))),
1036 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1039 printf(" (label \"%s\")", label);
1040 if(issprite) {spriteframe++; spriteframelabel = 0;}
1041 if(!issprite) {mainframe++; framelabel = 0;}
1044 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1045 U8 r = swf_GetU8(tag);
1046 U8 g = swf_GetU8(tag);
1047 U8 b = swf_GetU8(tag);
1048 printf(" (%02x/%02x/%02x)\n",r,g,b);
1050 else if(tag->id == ST_PROTECT) {
1052 printf(" %s\n", swf_GetString(tag));
1057 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1058 tag->id == ST_DEFINEBITSLOSSLESS2) {
1059 handleDefineBits(tag);
1062 else if(tag->id == ST_DEFINESOUND) {
1063 handleDefineSound(tag);
1066 else if(tag->id == ST_VIDEOFRAME) {
1067 handleVideoFrame(tag, myprefix);
1070 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1071 handleVideoStream(tag, myprefix);
1074 else if(tag->id == ST_DEFINEEDITTEXT) {
1075 handleEditText(tag);
1078 else if(tag->id == ST_DEFINEMOVIE) {
1079 U16 id = swf_GetU16(tag);
1080 char*s = swf_GetString(tag);
1081 printf(" URL: %s\n", s);
1083 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1089 else if(tag->id == ST_PLACEOBJECT2) {
1091 else if(tag->id == ST_NAMECHARACTER) {
1093 printf(" \"%s\"\n", swf_GetString(tag));
1099 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1100 SRECT r = swf_GetDefineBBox(tag);
1101 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1108 sprintf(myprefix, " %s", prefix);
1110 if(tag->id == ST_DEFINESPRITE) {
1111 sprintf(prefix, " ");
1113 dumperror("Sprite definition inside a sprite definition");
1117 spriteframelabel = 0;
1119 else if(tag->id == ST_END) {
1122 spriteframelabel = 0;
1124 dumperror("End Tag not empty");
1126 else if(tag->id == ST_EXPORTASSETS) {
1127 handleExportAssets(tag, myprefix);
1129 else if(tag->id == ST_DOACTION && action) {
1131 actions = swf_ActionGet(tag);
1132 swf_DumpActions(actions, myprefix);
1134 else if(tag->id == ST_DOINITACTION && action) {
1136 swf_GetU16(tag); // id
1137 actions = swf_ActionGet(tag);
1138 swf_DumpActions(actions, myprefix);
1140 else if(tag->id == ST_DEFINEBUTTON && action) {
1141 dumpButtonActions(tag, myprefix);
1143 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1144 dumpButton2Actions(tag, myprefix);
1146 else if(tag->id == ST_PLACEOBJECT) {
1147 handlePlaceObject(tag, myprefix);
1149 else if(tag->id == ST_PLACEOBJECT2) {
1150 handlePlaceObject2(tag, myprefix);
1152 else if(tag->id == ST_DEFINESHAPE ||
1153 tag->id == ST_DEFINESHAPE2 ||
1154 tag->id == ST_DEFINESHAPE3) {
1156 handleShape(tag, myprefix);
1159 if(tag->len && used) {
1160 int num = swf_GetNumUsedIDs(tag);
1164 used = (int*)malloc(sizeof(int)*num);
1165 swf_GetUsedIDs(tag, used);
1166 printf("%s%suses IDs: ", indent, prefix);
1167 for(t=0;t<num;t++) {
1169 swf_SetTagPos(tag, used[t]);
1170 id = swf_GetU16(tag);
1171 printf("%d%s", id, t<num-1?", ":"");
1173 dumperror("Id %04d is not yet defined.\n", id);
1180 if(tag->len && hex) {
1181 hexdumpTag(tag, prefix);