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;
62 static struct options_t options[] = {
82 int args_callback_option(char*name,char*val)
84 if(!strcmp(name, "V")) {
85 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
88 else if(name[0]=='a') {
92 else if(name[0]=='p') {
96 else if(name[0]=='t') {
100 else if(name[0]=='s') {
104 else if(name[0]=='e') {
108 else if(name[0]=='E') {
113 else if(name[0]=='X') {
117 else if(name[0]=='Y') {
121 else if(name[0]=='r') {
125 else if(name[0]=='f') {
129 else if(name[0]=='d') {
133 else if(name[0]=='u') {
137 else if(name[0]=='b') {
141 else if(name[0]=='D') {
142 action = placements = showtext = showshapes = 1;
146 printf("Unknown option: -%s\n", name);
152 int args_callback_longoption(char*name,char*val)
154 return args_long2shortoption(options, name, val);
156 void args_callback_usage(char *name)
159 printf("Usage: %s [-atpdu] file.swf\n", name);
161 printf("-h , --help Print short help message and exit\n");
162 printf("-D , --full Show everything. Same as -atp\n");
163 printf("-V , --version Print version info and exit\n");
164 printf("-e , --html Print out html code for embedding the file\n");
165 printf("-a , --action Disassemble action tags\n");
166 printf("-t , --text Show text fields (like swfstrings).\n");
167 printf("-s , --shapes Show shape coordinates/styles\n");
168 printf("-p , --placements Show placement information\n");
169 printf("-b , --bbox Print tag's bounding boxes\n");
170 printf("-X , --width Prints out a string of the form \"-X width\".\n");
171 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
172 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
173 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
174 printf("-d , --hex Print hex output of tag data, too.\n");
175 printf("-u , --used Show referred IDs for each Tag.\n");
178 int args_callback_command(char*name,char*val)
181 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
189 char* testfunc(char*str)
191 printf("%s: %s\n", what, str);
195 void dumpButton2Actions(TAG*tag, char*prefix)
201 oldTagPos = swf_GetTagPos(tag);
203 // scan DefineButton2 Record
205 swf_GetU16(tag); // Character ID
206 swf_GetU8(tag); // Flags;
208 offsetpos = swf_GetTagPos(tag); // first offset
211 while (swf_GetU8(tag)) // state -> parse ButtonRecord
212 { swf_GetU16(tag); // id
213 swf_GetU16(tag); // layer
214 swf_GetMatrix(tag,NULL); // matrix
215 swf_GetCXForm(tag,NULL,1); // cxform
222 if(tag->pos >= tag->len)
225 offsetpos = swf_GetU16(tag);
226 condition = swf_GetU16(tag); // condition
228 actions = swf_ActionGet(tag);
229 printf("%s condition %04x\n", prefix, condition);
230 swf_DumpActions(actions, prefix);
233 swf_SetTagPos(tag,oldTagPos);
237 void dumpButtonActions(TAG*tag, char*prefix)
240 swf_GetU16(tag); // id
241 while (swf_GetU8(tag)) // state -> parse ButtonRecord
242 { swf_GetU16(tag); // id
243 swf_GetU16(tag); // layer
244 swf_GetMatrix(tag,NULL); // matrix
246 actions = swf_ActionGet(tag);
247 swf_DumpActions(actions, prefix);
254 void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
257 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
258 for(t=0;t<fontnum;t++)
260 if(fonts[t]->id == fontid) {
270 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
271 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
274 a = fonts[font]->glyph2ascii[glyphs[t]];
281 printf("\\x%x", (int)a);
286 void handleText(TAG*tag)
289 swf_ParseDefineText(tag,textcallback, 0);
292 void handleDefineSound(TAG*tag)
294 U16 id = swf_GetU16(tag);
295 U8 flags = swf_GetU8(tag);
296 int compression = (flags>>4)&3;
297 int rate = (flags>>2)&3;
298 int bits = flags&2?16:8;
299 int stereo = flags&1;
301 if(compression == 0) printf("Raw ");
302 else if(compression == 1) printf("ADPCM ");
303 else if(compression == 2) printf("MP3 ");
305 if(rate == 0) printf("5.5Khz ");
306 if(rate == 1) printf("11Khz ");
307 if(rate == 2) printf("22Khz ");
308 if(rate == 3) printf("44Khz ");
309 printf("%dBit ", bits);
310 if(stereo) printf("stereo");
315 void handleDefineBits(TAG*tag)
321 id = swf_GetU16(tag);
322 mode = swf_GetU8(tag);
323 width = swf_GetU16(tag);
324 height = swf_GetU16(tag);
325 printf(" image %dx%d",width,height);
326 if(mode == 3) printf(" (8 bpp)");
327 else if(mode == 4) printf(" (16 bpp)");
328 else if(mode == 5) printf(" (32 bpp)");
329 else printf(" (? bpp)");
332 void handleEditText(TAG*tag)
337 id = swf_GetU16(tag);
340 //swf_ResetReadBits(tag);
346 flags = swf_GetBits(tag,16);
347 if(flags & ET_HASFONT) {
348 swf_GetU16(tag); //font
349 swf_GetU16(tag); //fontheight
351 if(flags & ET_HASTEXTCOLOR) {
352 swf_GetU8(tag); //rgba
357 if(flags & ET_HASMAXLENGTH) {
358 swf_GetU16(tag); //maxlength
360 if(flags & ET_HASLAYOUT) {
361 swf_GetU8(tag); //align
362 swf_GetU16(tag); //left margin
363 swf_GetU16(tag); //right margin
364 swf_GetU16(tag); //indent
365 swf_GetU16(tag); //leading
367 printf(" variable \"%s\" ", &tag->data[tag->pos]);
368 if(flags & ET_HTML) printf("(html)");
369 if(flags & ET_NOSELECT) printf("(noselect)");
370 if(flags & ET_PASSWORD) printf("(password)");
371 if(flags & ET_READONLY) printf("(readonly)");
373 if(flags & (ET_X1 | ET_X3 ))
375 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
378 while(tag->data[tag->pos++]);
379 if(flags & ET_HASTEXT)
380 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
383 void printhandlerflags(U32 handlerflags)
385 if(handlerflags&1) printf("[on load]");
386 if(handlerflags&2) printf("[enter frame]");
387 if(handlerflags&4) printf("[unload]");
388 if(handlerflags&8) printf("[mouse move]");
389 if(handlerflags&16) printf("[mouse down]");
390 if(handlerflags&32) printf("[mouse up]");
391 if(handlerflags&64) printf("[key down]");
392 if(handlerflags&128) printf("[key up]");
394 if(handlerflags&256) printf("[data]");
395 if(handlerflags&512) printf("[initialize]");
396 if(handlerflags&1024) printf("[mouse press]");
397 if(handlerflags&2048) printf("[mouse release]");
398 if(handlerflags&4096) printf("[mouse release outside]");
399 if(handlerflags&8192) printf("[mouse rollover]");
400 if(handlerflags&16384) printf("[mouse rollout]");
401 if(handlerflags&32768) printf("[mouse drag over]");
403 if(handlerflags&0x10000) printf("[mouse drag out]");
404 if(handlerflags&0x20000) printf("[key press]");
405 if(handlerflags&0x40000) printf("[construct even]");
406 if(handlerflags&0xfff80000) printf("[???]");
408 void handleVideoStream(TAG*tag, char*prefix)
410 U16 id = swf_GetU16(tag);
411 U16 frames = swf_GetU16(tag);
412 U16 width = swf_GetU16(tag);
413 U16 height = swf_GetU16(tag);
414 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
415 U8 codec = swf_GetU8(tag);
416 printf(" (%d frames, %dx%d", frames, width, height);
420 printf(" sorenson h.263)");
422 printf(" codec 0x%02x)", codec);
424 void handleVideoFrame(TAG*tag, char*prefix)
426 U32 code, version, reference, sizeflags;
427 U32 width=0, height=0;
429 U16 id = swf_GetU16(tag);
430 U16 frame = swf_GetU16(tag);
431 U8 deblock,flags, tmp, bit;
433 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
434 printf(" (frame %d) ", frame);
436 /* video packet follows */
437 code = swf_GetBits(tag, 17);
438 version = swf_GetBits(tag, 5);
439 reference = swf_GetBits(tag, 8);
441 sizeflags = swf_GetBits(tag, 3);
444 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
445 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
446 case 2: width = 352; height = 288; break;
447 case 3: width = 176; height = 144; break;
448 case 4: width = 128; height = 96; break;
449 case 5: width = 320; height = 240; break;
450 case 6: width = 160; height = 120; break;
451 case 7: width = -1; height = -1;/*reserved*/ break;
453 printf("%dx%d ", width, height);
454 type = swf_GetBits(tag, 2);
455 printf("%s", types[type]);
457 deblock = swf_GetBits(tag, 1);
459 printf(" deblock ", deblock);
460 quantizer = swf_GetBits(tag, 5);
461 printf(" quant: %d ", quantizer);
464 void handlePlaceObject2(TAG*tag, char*prefix)
466 U8 flags = swf_GetU8(tag);
470 int ppos[3] = {0,0,0};
471 swf_GetU16(tag); //depth
474 if(flags&2) swf_GetU16(tag); //id
476 swf_GetMatrix(tag,&m);
478 ppos[0] += sprintf(pstr[0], "| Matrix ");
479 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
480 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
484 swf_GetCXForm(tag, &cx, 1);
486 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
487 ppos[1] += sprintf(pstr[1]+ppos[1], "| mul %4.1f %4.1f %4.1f %4.1f ", cx.r0/256.0, cx.g0/256.0, cx.b0/256.0, cx.a0/256.0);
488 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
492 U16 ratio = swf_GetU16(tag); //ratio
494 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
495 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
496 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
500 U16 clip = swf_GetU16(tag); //clip
502 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
503 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
504 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
507 if(flags&32) { while(swf_GetU8(tag)); }
508 if(placements && ppos[0]) {
510 printf("%s %s\n", prefix, pstr[0]);
511 printf("%s %s\n", prefix, pstr[1]);
512 printf("%s %s", prefix, pstr[2]);
521 reserved = swf_GetU16(tag); // must be 0
522 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
524 printf("Unknown parameter field not zero: %04x\n", reserved);
527 printf("global flags: %04x\n", globalflags);
529 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
531 handlerflags = swf_GetU32(tag);
534 while(handlerflags) {
539 globalflags &= ~handlerflags;
540 printf("%s flags %08x ",prefix, handlerflags);
541 printhandlerflags(handlerflags);
542 length = swf_GetU32(tag);
543 printf(", %d bytes actioncode\n",length);
544 a = swf_ActionGet(tag);
545 swf_DumpActions(a,prefix);
548 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
550 if(globalflags) // should go to sterr.
551 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
553 printf(" has action code\n");
558 void handlePlaceObject(TAG*tag, char*prefix)
560 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
562 U16 id = swf_GetU16(tag);
563 U16 depth = swf_GetU16(tag);
566 swf_GetMatrix(tag, &matrix);
567 swf_GetCXForm(tag, &cxform, 0);
570 swf_SetU16(tag2, depth);
571 swf_SetMatrix(tag2, &matrix);
572 swf_SetCXForm(tag2, &cxform, 1);
574 handlePlaceObject2(tag2, prefix);
577 char* fillstyle2str(FILLSTYLE*style)
579 switch(style->type) {
581 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
583 case 0x10: case 0x12:
584 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
586 case 0x40: case 0x41:
587 /* TODO: display information about that bitmap */
588 sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
591 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
595 char* linestyle2str(LINESTYLE*style)
597 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
601 void handleShape(TAG*tag, char*prefix)
609 swf_ParseDefineShape(tag, &shape);
611 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
613 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
618 else printf("%s | (Neither line nor fill styles)\n", prefix);
621 printf("%s", prefix);
622 if(t < shape.numfillstyles) {
623 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
627 if(t < shape.numlinestyles) {
628 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
633 printf("%s |\n", prefix);
637 printf("%s | fill: %02d/%02d line:%02d - ",
642 if(line->type == moveTo) {
643 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
644 } else if(line->type == lineTo) {
645 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
646 } else if(line->type == splineTo) {
647 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
648 line->sx/20.0, line->sy/20.0,
649 line->x/20.0, line->y/20.0
654 printf("%s |\n", prefix);
657 void fontcallback1(void*self, U16 id,U8 * name)
661 void fontcallback2(void*self, U16 id,U8 * name)
663 swf_FontExtract(&swf,id,&fonts[fontnum]);
667 static U8 printable(U8 a)
669 if(a<32 || a==127) return '.';
672 void hexdumpTag(TAG*tag, char* prefix)
676 printf(" %s-=> ",prefix);
677 for(t=0;t<tag->len;t++) {
678 printf("%02x ", tag->data[t]);
679 ascii[t&15] = printable(tag->data[t]);
680 if((t && ((t&15)==15)) || (t==tag->len-1))
684 for(s=p-1;s<16;s++) {
688 printf(" %s\n", ascii);
690 printf(" %s\n %s-=> ",ascii,prefix);
695 void handleExportAssets(TAG*tag, char* prefix)
701 num = swf_GetU16(tag);
704 id = swf_GetU16(tag);
705 name = swf_GetString(tag);
706 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
710 void dumperror(const char* format, ...)
715 va_start(arglist, format);
716 vsprintf(buf, format, arglist);
720 printf("==== Error: %s ====\n", buf);
723 static char strbuf[800];
726 char* timestring(double f)
728 int hours = (int)(f/3600);
729 int minutes = (int)((f-hours*3600)/60);
730 int seconds = (int)((f-hours*3600-minutes*60));
731 int useconds = (int)((f-(int)f)*1000+0.5);
734 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
735 return &strbuf[bufpos];
738 int main (int argc,char ** argv)
746 char issprite = 0; // are we inside a sprite definition?
749 char* spriteframelabel = 0;
750 char* framelabel = 0;
754 memset(idtab,0,65536);
756 processargs(argc, argv);
760 fprintf(stderr, "You must supply a filename.\n");
764 f = open(filename,O_RDONLY|O_BINARY);
769 sprintf(buffer, "Couldn't open %s", filename);
773 if FAILED(swf_ReadSWF(f,&swf))
775 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
782 if(statbuf.st_size != swf.fileSize && !swf.compressed)
783 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
784 statbuf.st_size, swf.fileSize);
785 filesize = statbuf.st_size;
790 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
791 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
795 printf("-X %d", xsize);
801 printf("-Y %d", ysize);
807 printf("-r %.2f", swf.frameRate/256.0);
813 printf("-f %d", swf.frameCount);
820 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
821 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
822 if(swf.fileVersion>9) {
823 fprintf(stderr, "Fileversion>9\n");
828 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
829 "<param name=\"movie\" value=\"%s\"/>\n"
830 "<param name=\"play\" value=\"true\"/>\n"
831 "<param name=\"loop\" value=\"false\"/>\n"
832 "<param name=\"quality\" value=\"high\"/>\n"
833 "<param name=\"loop\" value=\"false\"/>\n"
834 "</object>\n\n", filename, xsize, ysize, filename);
836 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
838 //" BGCOLOR=#ffffffff\n"?
840 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
841 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
842 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
843 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
844 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
845 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
846 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
847 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
848 " TYPE=\"application/x-shockwave-flash\"\n"
849 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
851 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
852 filename, filename, xsize, ysize);
856 printf("[HEADER] File version: %d\n", swf.fileVersion);
858 printf("[HEADER] File is zlib compressed.");
859 if(filesize && swf.fileSize)
860 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
864 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
865 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
866 printf("[HEADER] Frame count: %d\n",swf.frameCount);
867 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
868 if(swf.movieSize.xmin)
869 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
872 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
873 if(swf.movieSize.ymin)
874 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
882 swf_FontEnumerate(&swf,&fontcallback1, 0);
883 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
885 swf_FontEnumerate(&swf,&fontcallback2, 0);
889 char*name = swf_TagGetName(tag);
892 dumperror("Unknown tag:0x%03x", tag->id);
896 if(swf_TagGetName(tag)) {
897 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
899 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
902 if(tag->id == ST_FREECHARACTER) {
903 U16 id = swf_GetU16(tag);
907 if(swf_isDefiningTag(tag)) {
908 U16 id = swf_GetDefineID(tag);
909 printf(" defines id %04d", id);
911 dumperror("Id %04d is defined more than once.", id);
914 else if(swf_isPseudoDefiningTag(tag)) {
915 U16 id = swf_GetDefineID(tag);
916 printf(" adds information to id %04d", id);
918 dumperror("Id %04d is not yet defined.\n", id);
920 else if(tag->id == ST_PLACEOBJECT) {
921 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
923 printf(" name \"%s\"",swf_GetName(tag));
925 else if(tag->id == ST_PLACEOBJECT2) {
932 printf(" id %04d",swf_GetPlaceID(tag));
936 printf(" at depth %04d", swf_GetDepth(tag));
938 if(tag->data[0]&64) {
940 swf_GetPlaceObject(tag, &po);
941 printf(" (clip to %04d)", po.clipdepth);
942 swf_PlaceObjectFree(&po);
945 printf(" name \"%s\"",swf_GetName(tag));
948 else if(tag->id == ST_REMOVEOBJECT) {
949 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
951 else if(tag->id == ST_REMOVEOBJECT2) {
952 printf(" removes object from depth %04d", swf_GetDepth(tag));
954 else if(tag->id == ST_FREECHARACTER) {
955 printf(" frees object %04d", swf_GetPlaceID(tag));
957 else if(tag->id == ST_STARTSOUND) {
960 id = swf_GetU16(tag);
961 flags = swf_GetU8(tag);
963 printf(" stops sound with id %04d", id);
965 printf(" starts sound with id %04d", id);
967 printf(" (if not already playing)");
973 printf(" looping %d times", swf_GetU16(tag));
976 else if(tag->id == ST_FRAMELABEL) {
977 int l = strlen(tag->data);
978 printf(" \"%s\"", tag->data);
980 printf(" has %d extra bytes", tag->len-1-l);
981 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
984 if((framelabel && !issprite) ||
985 (spriteframelabel && issprite)) {
986 dumperror("Frame %d has more than one label",
987 issprite?spriteframe:mainframe);
989 if(issprite) spriteframelabel = tag->data;
990 else framelabel = tag->data;
992 else if(tag->id == ST_SHOWFRAME) {
993 char*label = issprite?spriteframelabel:framelabel;
994 int frame = issprite?spriteframe:mainframe;
997 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
999 if(issprite) spriteframe++;
1005 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1007 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1008 timestring(frame*(256.0/(swf.frameRate+0.1))),
1009 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1012 printf(" (label \"%s\")", label);
1013 if(issprite) {spriteframe++; spriteframelabel = 0;}
1014 if(!issprite) {mainframe++; framelabel = 0;}
1017 if(tag->id == ST_SETBACKGROUNDCOLOR) {
1018 U8 r = swf_GetU8(tag);
1019 U8 g = swf_GetU8(tag);
1020 U8 b = swf_GetU8(tag);
1021 printf(" (%02x/%02x/%02x)\n",r,g,b);
1023 else if(tag->id == ST_PROTECT) {
1025 printf(" %s\n", swf_GetString(tag));
1030 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
1031 tag->id == ST_DEFINEBITSLOSSLESS2) {
1032 handleDefineBits(tag);
1035 else if(tag->id == ST_DEFINESOUND) {
1036 handleDefineSound(tag);
1039 else if(tag->id == ST_VIDEOFRAME) {
1040 handleVideoFrame(tag, myprefix);
1043 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1044 handleVideoStream(tag, myprefix);
1047 else if(tag->id == ST_DEFINEEDITTEXT) {
1048 handleEditText(tag);
1051 else if(tag->id == ST_DEFINEMOVIE) {
1052 U16 id = swf_GetU16(tag);
1053 char*s = swf_GetString(tag);
1054 printf(" URL: %s\n", s);
1056 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1062 else if(tag->id == ST_PLACEOBJECT2) {
1064 else if(tag->id == ST_NAMECHARACTER) {
1066 printf(" \"%s\"\n", swf_GetString(tag));
1072 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1073 SRECT r = swf_GetDefineBBox(tag);
1074 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1081 sprintf(myprefix, " %s", prefix);
1083 if(tag->id == ST_DEFINESPRITE) {
1084 sprintf(prefix, " ");
1086 dumperror("Sprite definition inside a sprite definition");
1090 spriteframelabel = 0;
1092 else if(tag->id == ST_END) {
1095 spriteframelabel = 0;
1097 dumperror("End Tag not empty");
1099 else if(tag->id == ST_EXPORTASSETS) {
1100 handleExportAssets(tag, myprefix);
1102 else if(tag->id == ST_DOACTION && action) {
1104 actions = swf_ActionGet(tag);
1105 swf_DumpActions(actions, myprefix);
1107 else if(tag->id == ST_DOINITACTION && action) {
1109 swf_GetU16(tag); // id
1110 actions = swf_ActionGet(tag);
1111 swf_DumpActions(actions, myprefix);
1113 else if(tag->id == ST_DEFINEBUTTON && action) {
1114 dumpButtonActions(tag, myprefix);
1116 else if(tag->id == ST_DEFINEBUTTON2 && action) {
1117 dumpButton2Actions(tag, myprefix);
1119 else if(tag->id == ST_PLACEOBJECT) {
1120 handlePlaceObject(tag, myprefix);
1122 else if(tag->id == ST_PLACEOBJECT2) {
1123 handlePlaceObject2(tag, myprefix);
1125 else if(tag->id == ST_DEFINESHAPE ||
1126 tag->id == ST_DEFINESHAPE2 ||
1127 tag->id == ST_DEFINESHAPE3) {
1129 handleShape(tag, myprefix);
1132 if(tag->len && used) {
1133 int num = swf_GetNumUsedIDs(tag);
1137 used = (int*)malloc(sizeof(int)*num);
1138 swf_GetUsedIDs(tag, used);
1139 printf("%s%suses IDs: ", indent, prefix);
1140 for(t=0;t<num;t++) {
1142 swf_SetTagPos(tag, used[t]);
1143 id = swf_GetU16(tag);
1144 printf("%d%s", id, t<num-1?", ":"");
1146 dumperror("Id %04d is not yet defined.\n", id);
1153 if(tag->len && hex) {
1154 hexdumpTag(tag, prefix);