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)&7;
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 ");
314 else if(compression == 3) printf("Raw little-endian ");
315 else if(compression == 6) printf("ASAO ");
317 if(rate == 0) printf("5.5Khz ");
318 if(rate == 1) printf("11Khz ");
319 if(rate == 2) printf("22Khz ");
320 if(rate == 3) printf("44Khz ");
321 printf("%dBit ", bits);
322 if(stereo) printf("stereo");
327 void handleDefineBits(TAG*tag)
333 id = swf_GetU16(tag);
334 mode = swf_GetU8(tag);
335 width = swf_GetU16(tag);
336 height = swf_GetU16(tag);
337 printf(" image %dx%d",width,height);
338 if(mode == 3) printf(" (8 bpp)");
339 else if(mode == 4) printf(" (16 bpp)");
340 else if(mode == 5) printf(" (32 bpp)");
341 else printf(" (? bpp)");
344 void handleEditText(TAG*tag)
349 id = swf_GetU16(tag);
352 //swf_ResetReadBits(tag);
358 flags = swf_GetBits(tag,16);
359 if(flags & ET_HASFONT) {
360 swf_GetU16(tag); //font
361 swf_GetU16(tag); //fontheight
363 if(flags & ET_HASTEXTCOLOR) {
364 swf_GetU8(tag); //rgba
369 if(flags & ET_HASMAXLENGTH) {
370 swf_GetU16(tag); //maxlength
372 if(flags & ET_HASLAYOUT) {
373 swf_GetU8(tag); //align
374 swf_GetU16(tag); //left margin
375 swf_GetU16(tag); //right margin
376 swf_GetU16(tag); //indent
377 swf_GetU16(tag); //leading
379 printf(" variable \"%s\" ", &tag->data[tag->pos]);
380 if(flags & ET_HTML) printf("(html)");
381 if(flags & ET_NOSELECT) printf("(noselect)");
382 if(flags & ET_PASSWORD) printf("(password)");
383 if(flags & ET_READONLY) printf("(readonly)");
385 if(flags & (ET_X1 | ET_X3 ))
387 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
390 while(tag->data[tag->pos++]);
391 if(flags & ET_HASTEXT)
392 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
395 void printhandlerflags(U32 handlerflags)
397 if(handlerflags&1) printf("[on load]");
398 if(handlerflags&2) printf("[enter frame]");
399 if(handlerflags&4) printf("[unload]");
400 if(handlerflags&8) printf("[mouse move]");
401 if(handlerflags&16) printf("[mouse down]");
402 if(handlerflags&32) printf("[mouse up]");
403 if(handlerflags&64) printf("[key down]");
404 if(handlerflags&128) printf("[key up]");
406 if(handlerflags&256) printf("[data]");
407 if(handlerflags&512) printf("[initialize]");
408 if(handlerflags&1024) printf("[mouse press]");
409 if(handlerflags&2048) printf("[mouse release]");
410 if(handlerflags&4096) printf("[mouse release outside]");
411 if(handlerflags&8192) printf("[mouse rollover]");
412 if(handlerflags&16384) printf("[mouse rollout]");
413 if(handlerflags&32768) printf("[mouse drag over]");
415 if(handlerflags&0x10000) printf("[mouse drag out]");
416 if(handlerflags&0x20000) printf("[key press]");
417 if(handlerflags&0x40000) printf("[construct even]");
418 if(handlerflags&0xfff80000) printf("[???]");
420 void handleVideoStream(TAG*tag, char*prefix)
422 U16 id = swf_GetU16(tag);
423 U16 frames = swf_GetU16(tag);
424 U16 width = swf_GetU16(tag);
425 U16 height = swf_GetU16(tag);
426 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
427 U8 codec = swf_GetU8(tag);
428 printf(" (%d frames, %dx%d", frames, width, height);
432 printf(" sorenson h.263)");
434 printf(" codec 0x%02x)", codec);
436 void handleVideoFrame(TAG*tag, char*prefix)
438 U32 code, version, reference, sizeflags;
439 U32 width=0, height=0;
441 U16 id = swf_GetU16(tag);
442 U16 frame = swf_GetU16(tag);
443 U8 deblock,flags, tmp, bit;
445 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
446 printf(" (frame %d) ", frame);
448 /* video packet follows */
449 code = swf_GetBits(tag, 17);
450 version = swf_GetBits(tag, 5);
451 reference = swf_GetBits(tag, 8);
453 sizeflags = swf_GetBits(tag, 3);
456 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
457 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
458 case 2: width = 352; height = 288; break;
459 case 3: width = 176; height = 144; break;
460 case 4: width = 128; height = 96; break;
461 case 5: width = 320; height = 240; break;
462 case 6: width = 160; height = 120; break;
463 case 7: width = -1; height = -1;/*reserved*/ break;
465 printf("%dx%d ", width, height);
466 type = swf_GetBits(tag, 2);
467 printf("%s", types[type]);
469 deblock = swf_GetBits(tag, 1);
471 printf(" deblock ", deblock);
472 quantizer = swf_GetBits(tag, 5);
473 printf(" quant: %d ", quantizer);
476 void handlePlaceObject2(TAG*tag, char*prefix)
482 int ppos[3] = {0,0,0};
483 swf_SetTagPos(tag, 0);
484 flags = swf_GetU8(tag);
485 swf_GetU16(tag); //depth
488 if(flags&2) swf_GetU16(tag); //id
490 swf_GetMatrix(tag,&m);
492 ppos[0] += sprintf(pstr[0], "| Matrix ");
493 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
494 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
498 swf_GetCXForm(tag, &cx, 1);
500 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
501 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);
502 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
506 U16 ratio = swf_GetU16(tag); //ratio
508 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
509 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
510 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
514 U16 clip = swf_GetU16(tag); //clip
516 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
517 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
518 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
521 if(flags&32) { while(swf_GetU8(tag)); }
522 if(placements && ppos[0]) {
524 printf("%s %s\n", prefix, pstr[0]);
525 printf("%s %s\n", prefix, pstr[1]);
526 printf("%s %s", prefix, pstr[2]);
535 reserved = swf_GetU16(tag); // must be 0
536 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
538 printf("Unknown parameter field not zero: %04x\n", reserved);
541 printf("global flags: %04x\n", globalflags);
543 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
545 handlerflags = swf_GetU32(tag);
548 while(handlerflags) {
553 globalflags &= ~handlerflags;
554 printf("%s flags %08x ",prefix, handlerflags);
555 printhandlerflags(handlerflags);
556 length = swf_GetU32(tag);
557 printf(", %d bytes actioncode\n",length);
558 a = swf_ActionGet(tag);
559 swf_DumpActions(a,prefix);
562 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
564 if(globalflags) // should go to sterr.
565 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
567 printf(" has action code\n");
572 void handlePlaceObject(TAG*tag, char*prefix)
574 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
579 swf_SetTagPos(tag, 0);
580 id = swf_GetU16(tag);
581 depth = swf_GetU16(tag);
582 swf_GetMatrix(tag, &matrix);
583 swf_GetCXForm(tag, &cxform, 0);
585 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
586 swf_SetU16(tag2, depth);
587 swf_SetU16(tag2, id);
588 swf_SetMatrix(tag2, &matrix);
589 swf_SetCXForm(tag2, &cxform, 1);
591 handlePlaceObject2(tag2, prefix);
594 char* fillstyle2str(FILLSTYLE*style)
596 switch(style->type) {
598 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
600 case 0x10: case 0x12:
601 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
604 /* TODO: display information about that bitmap */
605 sprintf(stylebuf, "BITMAPt %d", style->id_bitmap);
606 /* TODO: show matrix */
609 /* TODO: display information about that bitmap */
610 sprintf(stylebuf, "BITMAPc %d", style->id_bitmap);
611 /* TODO: show matrix */
614 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
618 char* linestyle2str(LINESTYLE*style)
620 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
624 void handleShape(TAG*tag, char*prefix)
632 swf_ParseDefineShape(tag, &shape);
634 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
636 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
641 else printf("%s | (Neither line nor fill styles)\n", prefix);
644 printf("%s", prefix);
645 if(t < shape.numfillstyles) {
646 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
650 if(t < shape.numlinestyles) {
651 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
656 printf("%s |\n", prefix);
660 printf("%s | fill: %02d/%02d line:%02d - ",
665 if(line->type == moveTo) {
666 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
667 } else if(line->type == lineTo) {
668 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
669 } else if(line->type == splineTo) {
670 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
671 line->sx/20.0, line->sy/20.0,
672 line->x/20.0, line->y/20.0
677 printf("%s |\n", prefix);
680 void fontcallback1(void*self, U16 id,U8 * name)
684 void fontcallback2(void*self, U16 id,U8 * name)
686 swf_FontExtract(&swf,id,&fonts[fontnum]);
690 static U8 printable(U8 a)
692 if(a<32 || a==127) return '.';
695 void hexdumpTag(TAG*tag, char* prefix)
699 printf(" %s-=> ",prefix);
700 for(t=0;t<tag->len;t++) {
701 printf("%02x ", tag->data[t]);
702 ascii[t&15] = printable(tag->data[t]);
703 if((t && ((t&15)==15)) || (t==tag->len-1))
707 for(s=p-1;s<16;s++) {
711 printf(" %s\n", ascii);
713 printf(" %s\n %s-=> ",ascii,prefix);
718 void handleExportAssets(TAG*tag, char* prefix)
724 num = swf_GetU16(tag);
727 id = swf_GetU16(tag);
728 name = swf_GetString(tag);
729 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
733 void dumperror(const char* format, ...)
738 va_start(arglist, format);
739 vsprintf(buf, format, arglist);
743 printf("==== Error: %s ====\n", buf);
746 static char strbuf[800];
749 char* timestring(double f)
751 int hours = (int)(f/3600);
752 int minutes = (int)((f-hours*3600)/60);
753 int seconds = (int)((f-hours*3600-minutes*60));
754 int useconds = (int)((f-(int)f)*1000+0.5);
757 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
758 return &strbuf[bufpos];
761 int main (int argc,char ** argv)
769 char issprite = 0; // are we inside a sprite definition?
772 char* spriteframelabel = 0;
773 char* framelabel = 0;
778 memset(idtab,0,65536);
780 processargs(argc, argv);
784 fprintf(stderr, "You must supply a filename.\n");
788 f = open(filename,O_RDONLY|O_BINARY);
793 sprintf(buffer, "Couldn't open %s", filename);
797 if FAILED(swf_ReadSWF(f,&swf))
799 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
806 if(statbuf.st_size != swf.fileSize && !swf.compressed)
807 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
808 statbuf.st_size, swf.fileSize);
809 filesize = statbuf.st_size;
814 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
815 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
819 printf("-X %d", xsize);
825 printf("-Y %d", ysize);
831 printf("-r %.2f", swf.frameRate/256.0);
837 printf("-f %d", swf.frameCount);
844 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
845 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
846 if(swf.fileVersion>9) {
847 fprintf(stderr, "Fileversion>9\n");
852 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
853 "<param name=\"movie\" value=\"%s\"/>\n"
854 "<param name=\"play\" value=\"true\"/>\n"
855 "<param name=\"loop\" value=\"false\"/>\n"
856 "<param name=\"quality\" value=\"high\"/>\n"
857 "<param name=\"loop\" value=\"false\"/>\n"
858 "</object>\n\n", filename, xsize, ysize, filename);
860 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
862 //" BGCOLOR=#ffffffff\n"?
864 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
865 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
866 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
867 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
868 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
869 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
870 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
871 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
872 " TYPE=\"application/x-shockwave-flash\"\n"
873 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
875 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
876 filename, filename, xsize, ysize);
880 printf("[HEADER] File version: %d\n", swf.fileVersion);
882 printf("[HEADER] File is zlib compressed.");
883 if(filesize && swf.fileSize)
884 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
888 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
889 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
890 printf("[HEADER] Frame count: %d\n",swf.frameCount);
891 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
892 if(swf.movieSize.xmin)
893 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
896 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
897 if(swf.movieSize.ymin)
898 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
906 swf_FontEnumerate(&swf,&fontcallback1, 0);
907 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
909 swf_FontEnumerate(&swf,&fontcallback2, 0);
913 char*name = swf_TagGetName(tag);
916 dumperror("Unknown tag:0x%03x", tag->id);
921 name = "UNKNOWN TAG";
925 printf("[%03x] %9ld %9ld %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
927 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
930 if(swf_isDefiningTag(tag)) {
931 U16 id = swf_GetDefineID(tag);
932 printf(" defines id %04d", id);
934 dumperror("Id %04d is defined more than once.", id);
937 else if(swf_isPseudoDefiningTag(tag)) {
938 U16 id = swf_GetDefineID(tag);
939 printf(" adds information to id %04d", id);
941 dumperror("Id %04d is not yet defined.\n", id);
943 else if(tag->id == ST_PLACEOBJECT) {
944 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
946 printf(" name \"%s\"",swf_GetName(tag));
948 else if(tag->id == ST_PLACEOBJECT2) {
955 printf(" id %04d",swf_GetPlaceID(tag));
959 printf(" at depth %04d", swf_GetDepth(tag));
961 swf_SetTagPos(tag, 0);
962 if(tag->data[0]&64) {
964 swf_GetPlaceObject(tag, &po);
965 printf(" (clip to %04d)", po.clipdepth);
966 swf_PlaceObjectFree(&po);
969 printf(" name \"%s\"",swf_GetName(tag));
972 else if(tag->id == ST_REMOVEOBJECT) {
973 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
975 else if(tag->id == ST_REMOVEOBJECT2) {
976 printf(" removes object from depth %04d", swf_GetDepth(tag));
978 else if(tag->id == ST_FREECHARACTER) {
979 printf(" frees object %04d", swf_GetPlaceID(tag));
981 else if(tag->id == ST_STARTSOUND) {
984 id = swf_GetU16(tag);
985 flags = swf_GetU8(tag);
987 printf(" stops sound with id %04d", id);
989 printf(" starts sound with id %04d", id);
991 printf(" (if not already playing)");
997 printf(" looping %d times", swf_GetU16(tag));
1000 else if(tag->id == ST_FRAMELABEL) {
1001 int l = strlen(tag->data);
1002 printf(" \"%s\"", tag->data);
1003 if((l+1) < tag->len) {
1004 printf(" has %d extra bytes", tag->len-1-l);
1005 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1006 printf(" (ANCHOR)");
1008 if((framelabel && !issprite) ||
1009 (spriteframelabel && issprite)) {
1010 dumperror("Frame %d has more than one label",
1011 issprite?spriteframe:mainframe);
1013 if(issprite) spriteframelabel = tag->data;
1014 else framelabel = tag->data;
1016 else if(tag->id == ST_SHOWFRAME) {
1017 char*label = issprite?spriteframelabel:framelabel;
1018 int frame = issprite?spriteframe:mainframe;
1021 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1023 if(issprite) spriteframe++;
1029 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1031 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1032 timestring(frame*(256.0/(swf.frameRate+0.1))),
1033 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1036 printf(" (label \"%s\")", label);
1037 if(issprite) {spriteframe++; spriteframelabel = 0;}
1038 if(!issprite) {mainframe++; framelabel = 0;}
1041 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1042 U8 r = swf_GetU8(tag);
1043 U8 g = swf_GetU8(tag);
1044 U8 b = swf_GetU8(tag);
1045 printf(" (%02x/%02x/%02x)\n",r,g,b);
1047 else if(tag->id == ST_PROTECT) {
1049 printf(" %s\n", swf_GetString(tag));
1054 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1055 tag->id == ST_DEFINEBITSLOSSLESS2) {
1056 handleDefineBits(tag);
1059 else if(tag->id == ST_DEFINESOUND) {
1060 handleDefineSound(tag);
1063 else if(tag->id == ST_VIDEOFRAME) {
1064 handleVideoFrame(tag, myprefix);
1067 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1068 handleVideoStream(tag, myprefix);
1071 else if(tag->id == ST_DEFINEEDITTEXT) {
1072 handleEditText(tag);
1075 else if(tag->id == ST_DEFINEMOVIE) {
1076 U16 id = swf_GetU16(tag);
1077 char*s = swf_GetString(tag);
1078 printf(" URL: %s\n", s);
1080 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1086 else if(tag->id == ST_PLACEOBJECT2) {
1088 else if(tag->id == ST_NAMECHARACTER) {
1090 printf(" \"%s\"\n", swf_GetString(tag));
1096 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1097 SRECT r = swf_GetDefineBBox(tag);
1098 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1105 sprintf(myprefix, " %s", prefix);
1107 if(tag->id == ST_DEFINESPRITE) {
1108 sprintf(prefix, " ");
1110 dumperror("Sprite definition inside a sprite definition");
1114 spriteframelabel = 0;
1116 else if(tag->id == ST_END) {
1119 spriteframelabel = 0;
1121 dumperror("End Tag not empty");
1123 else if(tag->id == ST_EXPORTASSETS) {
1124 handleExportAssets(tag, myprefix);
1126 else if(tag->id == ST_DOACTION && action) {
1128 actions = swf_ActionGet(tag);
1129 swf_DumpActions(actions, myprefix);
1131 else if(tag->id == ST_DOINITACTION && action) {
1133 swf_GetU16(tag); // id
1134 actions = swf_ActionGet(tag);
1135 swf_DumpActions(actions, myprefix);
1137 else if(tag->id == ST_DEFINEBUTTON && action) {
1138 dumpButtonActions(tag, myprefix);
1140 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1141 dumpButton2Actions(tag, myprefix);
1143 else if(tag->id == ST_PLACEOBJECT) {
1144 handlePlaceObject(tag, myprefix);
1146 else if(tag->id == ST_PLACEOBJECT2) {
1147 handlePlaceObject2(tag, myprefix);
1149 else if(tag->id == ST_DEFINESHAPE ||
1150 tag->id == ST_DEFINESHAPE2 ||
1151 tag->id == ST_DEFINESHAPE3) {
1153 handleShape(tag, myprefix);
1156 if(tag->len && used) {
1157 int num = swf_GetNumUsedIDs(tag);
1161 used = (int*)malloc(sizeof(int)*num);
1162 swf_GetUsedIDs(tag, used);
1163 printf("%s%suses IDs: ", indent, prefix);
1164 for(t=0;t<num;t++) {
1166 swf_SetTagPos(tag, used[t]);
1167 id = swf_GetU16(tag);
1168 printf("%d%s", id, t<num-1?", ":"");
1170 dumperror("Id %04d is not yet defined.\n", id);
1177 if(tag->id == ST_FREECHARACTER) {
1179 swf_SetTagPos(tag, 0);
1180 id = swf_GetU16(tag);
1184 if(tag->len && hex) {
1185 hexdumpTag(tag, prefix);