2 Shows the structure of a swf file
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include "../config.h"
24 #ifdef HAVE_SYS_STAT_H
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
40 #include "../lib/rfxswf.h"
41 #include "../lib/args.h"
43 static char * filename
= 0;
45 /* idtab stores the ids which are defined in the file. This allows us
46 to detect errors in the file. (i.e. ids which are defined more than
48 static char idtab
[65536];
49 static char * indent
= " ";
51 static int placements
= 0;
52 static int action
= 0;
55 static int showtext
= 0;
56 static int showshapes
= 0;
60 static struct options_t options
[] = {
78 int args_callback_option(char*name
,char*val
)
80 if(!strcmp(name
, "V")) {
81 printf("swfdump - part of %s %s\n", PACKAGE
, VERSION
);
84 else if(name
[0]=='a') {
88 else if(name
[0]=='p') {
92 else if(name
[0]=='t') {
96 else if(name
[0]=='s') {
100 else if(name
[0]=='e') {
104 else if(name
[0]=='X') {
108 else if(name
[0]=='Y') {
112 else if(name
[0]=='r') {
116 else if(name
[0]=='f') {
120 else if(name
[0]=='d') {
124 else if(name
[0]=='u') {
128 else if(name
[0]=='D') {
129 action
= placements
= showtext
= showshapes
= 1;
133 printf("Unknown option: -%s\n", name
);
139 int args_callback_longoption(char*name
,char*val
)
141 return args_long2shortoption(options
, name
, val
);
143 void args_callback_usage(char *name
)
146 printf("Usage: %s [-atpdu] file.swf\n", name
);
148 printf("-h , --help Print short help message and exit\n");
149 printf("-D , --full Show everything. Same as -atp\n");
150 printf("-V , --version Print version info and exit\n");
151 printf("-e , --html Print out html code for embedding the file\n");
152 printf("-a , --action Disassemble action tags\n");
153 printf("-t , --text Show text fields (like swfstrings).\n");
154 printf("-p , --placements Show placement information\n");
155 printf("-X , --width Prints out a string of the form \"-X width\".\n");
156 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
157 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
158 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
159 printf("-d , --hex Print hex output of tag data, too.\n");
160 printf("-u , --used Show referred IDs for each Tag.\n");
163 int args_callback_command(char*name
,char*val
)
166 fprintf(stderr
, "Only one file allowed. You supplied at least two. (%s and %s)\n",
174 char* testfunc(char*str
)
176 printf("%s: %s\n", what
, str
);
180 void dumpButton2Actions(TAG
*tag
, char*prefix
)
186 oldTagPos
= swf_GetTagPos(tag
);
188 // scan DefineButton2 Record
190 swf_GetU16(tag
); // Character ID
191 swf_GetU8(tag
); // Flags;
193 offsetpos
= swf_GetTagPos(tag
); // first offset
196 while (swf_GetU8(tag
)) // state -> parse ButtonRecord
197 { swf_GetU16(tag
); // id
198 swf_GetU16(tag
); // layer
199 swf_GetMatrix(tag
,NULL
); // matrix
200 swf_GetCXForm(tag
,NULL
,1); // cxform
207 if(tag
->pos
>= tag
->len
)
210 offsetpos
= swf_GetU16(tag
);
211 condition
= swf_GetU16(tag
); // condition
213 actions
= swf_ActionGet(tag
);
214 printf("%s condition %04x\n", prefix
, condition
);
215 swf_DumpActions(actions
, prefix
);
218 swf_SetTagPos(tag
,oldTagPos
);
222 void dumpButtonActions(TAG
*tag
, char*prefix
)
225 swf_GetU16(tag
); // id
226 while (swf_GetU8(tag
)) // state -> parse ButtonRecord
227 { swf_GetU16(tag
); // id
228 swf_GetU16(tag
); // layer
229 swf_GetMatrix(tag
,NULL
); // matrix
231 actions
= swf_ActionGet(tag
);
232 swf_DumpActions(actions
, prefix
);
235 #define ET_HASTEXT 32768
236 #define ET_WORDWRAP 16384
237 #define ET_MULTILINE 8192
238 #define ET_PASSWORD 4096
239 #define ET_READONLY 2048
240 #define ET_HASTEXTCOLOR 1024
241 #define ET_HASMAXLENGTH 512
242 #define ET_HASFONT 256
245 #define ET_HASLAYOUT 32
246 #define ET_NOSELECT 16
250 #define ET_USEOUTLINES 1
256 void textcallback(void*self
, int*glyphs
, int*ypos
, int nr
, int fontid
, int fontsize
, int startx
, int starty
, RGBA
*color
)
259 printf(" <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr
, fontid
, color
->r
, color
->g
, color
->b
, color
->a
);
260 for(t
=0;t
<fontnum
;t
++)
262 if(fonts
[t
]->id
== fontid
) {
272 if(glyphs
[t
] >= fonts
[font
]->numchars
/*glyph is in range*/
273 || !fonts
[font
]->glyph2ascii
/* font has ascii<->glyph mapping */
276 a
= fonts
[font
]->glyph2ascii
[glyphs
[t
]];
283 printf("\\x%x", (int)a
);
288 void handleText(TAG
*tag
)
291 swf_ParseDefineText(tag
,textcallback
, 0);
294 void handleDefineSound(TAG
*tag
)
296 U16 id
= swf_GetU16(tag
);
297 U8 flags
= swf_GetU8(tag
);
298 int compression
= (flags
>>4)&3;
299 int rate
= (flags
>>2)&3;
300 int bits
= flags
&2?16:8;
301 int stereo
= flags
&1;
303 if(compression
== 0) printf("Raw ");
304 else if(compression
== 1) printf("ADPCM ");
305 else if(compression
== 2) printf("MP3 ");
307 if(rate
== 0) printf("5.5Khz ");
308 if(rate
== 1) printf("11Khz ");
309 if(rate
== 2) printf("22Khz ");
310 if(rate
== 3) printf("44Khz ");
311 printf("%dBit ", bits
);
312 if(stereo
) printf("stereo");
317 void handleDefineBits(TAG
*tag
)
323 id
= swf_GetU16(tag
);
324 mode
= swf_GetU8(tag
);
325 width
= swf_GetU16(tag
);
326 height
= swf_GetU16(tag
);
327 printf(" image %dx%d",width
,height
);
328 if(mode
== 3) printf(" (8 bpp)");
329 else if(mode
== 4) printf(" (16 bpp)");
330 else if(mode
== 5) printf(" (32 bpp)");
331 else printf(" (? bpp)");
334 void handleEditText(TAG
*tag
)
339 id
= swf_GetU16(tag
);
341 //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
]);
369 if(flags
& (ET_X1
| ET_X2
| ET_X3
| ET_X0
))
371 printf(" undefined flags: %d%d%d%d",
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
);
564 MATRIX matrix
; swf_GetMatrix(tag
, &matrix
);
565 CXFORM cxform
; swf_GetCXForm(tag
, &cxform
, 0);
568 swf_SetU16(tag2
, depth
);
569 swf_SetMatrix(tag2
, &matrix
);
570 swf_SetCXForm(tag2
, &cxform
, 1);
572 handlePlaceObject2(tag2
, prefix
);
575 char* fillstyle2str(FILLSTYLE
*style
)
577 switch(style
->type
) {
579 sprintf(stylebuf
, "SOLID %02x%02x%02x%02x", style
->color
.r
, style
->color
.g
, style
->color
.b
, style
->color
.a
);
581 case 0x10: case 0x12:
582 sprintf(stylebuf
, "GRADIENT (%d steps)", style
->gradient
.num
);
584 case 0x40: case 0x41:
585 /* TODO: display information about that bitmap */
586 sprintf(stylebuf
, "BITMAP %d", style
->id_bitmap
);
589 sprintf(stylebuf
, "UNKNOWN[%02x]",style
->type
);
593 char* linestyle2str(LINESTYLE
*style
)
595 sprintf(stylebuf
, "%.2f %02x%02x%02x%02x", style
->width
/20.0, style
->color
.r
, style
->color
.g
, style
->color
.b
, style
->color
.a
);
599 void handleShape(TAG
*tag
, char*prefix
)
604 swf_ParseDefineShape(tag
, &shape
);
608 int max
= shape
.numlinestyles
> shape
.numfillstyles
?shape
.numlinestyles
:shape
.numfillstyles
;
610 if(max
) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
615 else printf("%s | (Neither line nor fill styles)\n", prefix
);
618 printf("%s", prefix
);
619 if(t
< shape
.numfillstyles
) {
620 printf(" | %-2d) %-18.18s", t
+1, fillstyle2str(&shape
.fillstyles
[t
]));
624 if(t
< shape
.numlinestyles
) {
625 printf("%-2d) %s", t
+1, linestyle2str(&shape
.linestyles
[t
]));
630 printf("%s |\n", prefix
);
634 printf("%s | fill: %02d/%02d line:%02d - ",
639 if(line
->type
== moveTo
) {
640 printf("moveTo %.2f %.2f\n", line
->x
/20.0, line
->y
/20.0);
641 } else if(line
->type
== lineTo
) {
642 printf("lineTo %.2f %.2f\n", line
->x
/20.0, line
->y
/20.0);
643 } else if(line
->type
== splineTo
) {
644 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
645 line
->sx
/20.0, line
->sy
/20.0,
646 line
->x
/20.0, line
->y
/20.0
651 printf("%s |\n", prefix
);
654 void fontcallback1(U16 id
,U8
* name
)
658 void fontcallback2(U16 id
,U8
* name
)
660 swf_FontExtract(&swf
,id
,&fonts
[fontnum
]);
664 static U8
printable(U8 a
)
666 if(a
<32 || a
==127) return '.';
669 void hexdumpTag(TAG
*tag
, char* prefix
)
673 printf(" %s-=> ",prefix
);
674 for(t
=0;t
<tag
->len
;t
++) {
675 printf("%02x ", tag
->data
[t
]);
676 ascii
[t
&15] = printable(tag
->data
[t
]);
677 if((t
&& ((t
&15)==15)) || (t
==tag
->len
-1))
679 int s
,p
=((t
-1)&15)+1;
685 printf(" %s\n", ascii
);
687 printf(" %s\n %s-=> ",ascii
,prefix
);
692 void handleExportAssets(TAG
*tag
, char* prefix
)
698 num
= swf_GetU16(tag
);
701 id
= swf_GetU16(tag
);
702 name
= swf_GetString(tag
);
703 printf("%sexports %04d as \"%s\"\n", prefix
, id
, name
);
707 void dumperror(const char* format
, ...)
712 va_start(arglist
, format
);
713 vsprintf(buf
, format
, arglist
);
717 printf("==== Error: %s ====\n", buf
);
720 static char strbuf
[800];
723 char* timestring(double f
)
725 int hours
= (int)(f
/3600);
726 int minutes
= (int)((f
-hours
*3600)/60);
727 int seconds
= (int)((f
-hours
*3600-minutes
*60));
728 int useconds
= (int)((f
-(int)f
)*1000+0.5);
731 sprintf(&strbuf
[bufpos
], "%02d:%02d:%02d,%03d",hours
,minutes
,seconds
,useconds
);
732 return &strbuf
[bufpos
];
735 int main (int argc
,char ** argv
)
743 char issprite
= 0; // are we inside a sprite definition?
746 char* spriteframelabel
= 0;
747 char* framelabel
= 0;
751 memset(idtab
,0,65536);
753 processargs(argc
, argv
);
757 fprintf(stderr
, "You must supply a filename.\n");
761 f
= open(filename
,O_RDONLY
|O_BINARY
);
766 sprintf(buffer
, "Couldn't open %s", filename
);
770 if FAILED(swf_ReadSWF(f
,&swf
))
772 fprintf(stderr
, "%s is not a valid SWF file or contains errors.\n",filename
);
779 if(statbuf
.st_size
!= swf
.fileSize
&& !swf
.compressed
)
780 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
781 statbuf
.st_size
, swf
.fileSize
);
782 filesize
= statbuf
.st_size
;
787 xsize
= (swf
.movieSize
.xmax
-swf
.movieSize
.xmin
)/20;
788 ysize
= (swf
.movieSize
.ymax
-swf
.movieSize
.ymin
)/20;
792 printf("-X %d", xsize
);
798 printf("-Y %d", ysize
);
804 printf("-r %.2f", swf
.frameRate
/256.0);
810 printf("-f %d", swf
.frameCount
);
817 char*fileversions
[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
818 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
819 if(swf
.fileVersion
>9) {
820 fprintf(stderr
, "Fileversion>9\n");
823 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
825 //" BGCOLOR=#ffffffff\n"?
827 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
828 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
829 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
830 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
831 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
832 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
833 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
834 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
835 " TYPE=\"application/x-shockwave-flash\"\n"
836 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
838 "</OBJECT>\n", xsize
, ysize
, fileversions
[swf
.fileVersion
],
839 filename
, filename
, xsize
, ysize
);
842 printf("[HEADER] File version: %d\n", swf
.fileVersion
);
844 printf("[HEADER] File is zlib compressed.");
845 if(filesize
&& swf
.fileSize
)
846 printf(" Ratio: %02d%%\n", filesize
*100/(swf
.fileSize
));
850 printf("[HEADER] File size: %ld%s\n", swf
.fileSize
, swf
.compressed
?" (Depacked)":"");
851 printf("[HEADER] Frame rate: %f\n",swf
.frameRate
/256.0);
852 printf("[HEADER] Frame count: %d\n",swf
.frameCount
);
853 printf("[HEADER] Movie width: %.2f",(swf
.movieSize
.xmax
-swf
.movieSize
.xmin
)/20.0);
854 if(swf
.movieSize
.xmin
)
855 printf(" (left offset: %.2f)\n", swf
.movieSize
.xmin
/20.0);
858 printf("[HEADER] Movie height: %.2f",(swf
.movieSize
.ymax
-swf
.movieSize
.ymin
)/20.0);
859 if(swf
.movieSize
.ymin
)
860 printf(" (top offset: %.2f)\n", swf
.movieSize
.ymin
/20.0);
868 swf_FontEnumerate(&swf
,&fontcallback1
);
869 fonts
= (SWFFONT
**)malloc(fontnum
*sizeof(SWFFONT
*));
871 swf_FontEnumerate(&swf
,&fontcallback2
);
875 char*name
= swf_TagGetName(tag
);
878 dumperror("Unknown tag:0x%03x", tag
->id
);
882 if(swf_TagGetName(tag
)) {
883 printf("[%03x] %9ld %s%s", tag
->id
, tag
->len
, prefix
, swf_TagGetName(tag
));
885 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag
->id
, tag
->len
, prefix
, tag
->id
);
888 if(tag
->id
== ST_FREECHARACTER
) {
889 U16 id
= swf_GetU16(tag
);
893 if(swf_isDefiningTag(tag
)) {
894 U16 id
= swf_GetDefineID(tag
);
895 printf(" defines id %04d", id
);
897 dumperror("Id %04d is defined more than once.", id
);
900 else if(swf_isPseudoDefiningTag(tag
)) {
901 U16 id
= swf_GetDefineID(tag
);
902 printf(" adds information to id %04d", id
);
904 dumperror("Id %04d is not yet defined.\n", id
);
906 else if(tag
->id
== ST_PLACEOBJECT
) {
907 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag
), swf_GetDepth(tag
));
909 printf(" name \"%s\"",swf_GetName(tag
));
911 else if(tag
->id
== ST_PLACEOBJECT2
) {
918 printf(" id %04d",swf_GetPlaceID(tag
));
922 printf(" at depth %04d", swf_GetDepth(tag
));
924 printf(" name \"%s\"",swf_GetName(tag
));
926 else if(tag
->id
== ST_REMOVEOBJECT
) {
927 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag
), swf_GetDepth(tag
));
929 else if(tag
->id
== ST_REMOVEOBJECT2
) {
930 printf(" removes object from depth %04d", swf_GetDepth(tag
));
932 else if(tag
->id
== ST_FREECHARACTER
) {
933 printf(" frees object %04d", swf_GetPlaceID(tag
));
935 else if(tag
->id
== ST_STARTSOUND
) {
938 id
= swf_GetU16(tag
);
939 flags
= swf_GetU8(tag
);
941 printf(" stops sound with id %04d", id
);
943 printf(" starts sound with id %04d", id
);
945 printf(" (if not already playing)");
951 printf(" looping %d times", swf_GetU16(tag
));
954 else if(tag
->id
== ST_FRAMELABEL
) {
955 int l
= strlen(tag
->data
);
956 printf(" \"%s\"", tag
->data
);
958 printf(" has %d extra bytes", tag
->len
-1-l
);
959 if(tag
->len
-1-l
== 1 && tag
->data
[tag
->len
-1] == 1)
962 if((framelabel
&& !issprite
) ||
963 (spriteframelabel
&& issprite
)) {
964 dumperror("Frame %d has more than one label",
965 issprite
?spriteframe
:mainframe
);
967 if(issprite
) spriteframelabel
= tag
->data
;
968 else framelabel
= tag
->data
;
970 else if(tag
->id
== ST_SHOWFRAME
) {
971 char*label
= issprite
?spriteframelabel
:framelabel
;
972 int frame
= issprite
?spriteframe
:mainframe
;
975 while(tag
->next
&& tag
->next
->id
== ST_SHOWFRAME
&& tag
->next
->len
== 0) {
977 if(issprite
) spriteframe
++;
983 printf(" %d (%s)", frame
, timestring(frame
*(256.0/(swf
.frameRate
+0.1))));
985 printf(" %d-%d (%s-%s)", frame
, nframe
,
986 timestring(frame
*(256.0/(swf
.frameRate
+0.1))),
987 timestring(nframe
*(256.0/(swf
.frameRate
+0.1)))
990 printf(" (label \"%s\")", label
);
991 if(issprite
) {spriteframe
++; spriteframelabel
= 0;}
992 if(!issprite
) {mainframe
++; framelabel
= 0;}
995 if(tag
->id
== ST_SETBACKGROUNDCOLOR
) {
996 U8 r
= swf_GetU8(tag
);
997 U8 g
= swf_GetU8(tag
);
998 U8 b
= swf_GetU8(tag
);
999 printf(" (%02x/%02x/%02x)\n",r
,g
,b
);
1001 else if(tag
->id
== ST_PROTECT
) {
1003 printf(" %s\n", swf_GetString(tag
));
1008 else if(tag
->id
== ST_DEFINEBITSLOSSLESS
||
1009 tag
->id
== ST_DEFINEBITSLOSSLESS2
) {
1010 handleDefineBits(tag
);
1013 else if(tag
->id
== ST_DEFINESOUND
) {
1014 handleDefineSound(tag
);
1017 else if(tag
->id
== ST_VIDEOFRAME
) {
1018 handleVideoFrame(tag
, myprefix
);
1021 else if(tag
->id
== ST_DEFINEVIDEOSTREAM
) {
1022 handleVideoStream(tag
, myprefix
);
1025 else if(tag
->id
== ST_DEFINEEDITTEXT
) {
1026 handleEditText(tag
);
1029 else if(tag
->id
== ST_DEFINEMOVIE
) {
1030 U16 id
= swf_GetU16(tag
);
1031 char*s
= swf_GetString(tag
);
1032 printf(" URL: %s\n", s
);
1034 else if(tag
->id
== ST_DEFINETEXT
|| tag
->id
== ST_DEFINETEXT2
) {
1040 else if(tag
->id
== ST_PLACEOBJECT2
) {
1042 else if(tag
->id
== ST_NAMECHARACTER
) {
1044 printf(" \"%s\"\n", swf_GetString(tag
));
1050 sprintf(myprefix
, " %s", prefix
);
1052 if(tag
->id
== ST_DEFINESPRITE
) {
1053 sprintf(prefix
, " ");
1055 dumperror("Sprite definition inside a sprite definition");
1059 spriteframelabel
= 0;
1061 else if(tag
->id
== ST_END
) {
1064 spriteframelabel
= 0;
1066 dumperror("End Tag not empty");
1068 else if(tag
->id
== ST_EXPORTASSETS
) {
1069 handleExportAssets(tag
, myprefix
);
1071 else if(tag
->id
== ST_DOACTION
&& action
) {
1073 actions
= swf_ActionGet(tag
);
1074 swf_DumpActions(actions
, myprefix
);
1076 else if(tag
->id
== ST_DEFINEBUTTON
&& action
) {
1077 dumpButtonActions(tag
, myprefix
);
1079 else if(tag
->id
== ST_DEFINEBUTTON2
&& action
) {
1080 dumpButton2Actions(tag
, myprefix
);
1082 else if(tag
->id
== ST_PLACEOBJECT
) {
1083 handlePlaceObject(tag
, myprefix
);
1085 else if(tag
->id
== ST_PLACEOBJECT2
) {
1086 handlePlaceObject2(tag
, myprefix
);
1088 else if(tag
->id
== ST_DEFINESHAPE
||
1089 tag
->id
== ST_DEFINESHAPE2
||
1090 tag
->id
== ST_DEFINESHAPE3
) {
1092 handleShape(tag
, myprefix
);
1095 if(tag
->len
&& used
) {
1096 int num
= swf_GetNumUsedIDs(tag
);
1100 used
= (int*)malloc(sizeof(int)*num
);
1101 swf_GetUsedIDs(tag
, used
);
1102 printf("%s%suses IDs: ", indent
, prefix
);
1103 for(t
=0;t
<num
;t
++) {
1105 swf_SetTagPos(tag
, used
[t
]);
1106 id
= swf_GetU16(tag
);
1107 printf("%d%s", id
, t
<num
-1?", ":"");
1109 dumperror("Id %04d is not yet defined.\n", id
);
1116 if(tag
->len
&& hex
) {
1117 hexdumpTag(tag
, prefix
);