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;
59 static struct options_t options[] = {
76 int args_callback_option(char*name,char*val)
78 if(!strcmp(name, "V")) {
79 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
82 else if(name[0]=='a') {
86 else if(name[0]=='p') {
90 else if(name[0]=='t') {
94 else if(name[0]=='e') {
98 else if(name[0]=='X') {
102 else if(name[0]=='Y') {
106 else if(name[0]=='r') {
110 else if(name[0]=='f') {
114 else if(name[0]=='d') {
118 else if(name[0]=='u') {
122 else if(name[0]=='D') {
123 action = placements = showtext = 1;
127 printf("Unknown option: -%s\n", name);
133 int args_callback_longoption(char*name,char*val)
135 return args_long2shortoption(options, name, val);
137 void args_callback_usage(char *name)
140 printf("Usage: %s [-atpdu] file.swf\n", name);
142 printf("-h , --help Print short help message and exit\n");
143 printf("-D , --full Show everything. Same as -atp\n");
144 printf("-V , --version Print version info and exit\n");
145 printf("-e , --html Print out html code for embedding the file\n");
146 printf("-a , --action Disassemble action tags\n");
147 printf("-t , --text Show text fields (like swfstrings).\n");
148 printf("-p , --placements Show placement information\n");
149 printf("-X , --width Prints out a string of the form \"-X width\".\n");
150 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
151 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
152 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
153 printf("-d , --hex Print hex output of tag data, too.\n");
154 printf("-u , --used Show referred IDs for each Tag.\n");
157 int args_callback_command(char*name,char*val)
160 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
168 char* testfunc(char*str)
170 printf("%s: %s\n", what, str);
174 void dumpButton2Actions(TAG*tag, char*prefix)
180 oldTagPos = swf_GetTagPos(tag);
182 // scan DefineButton2 Record
184 swf_GetU16(tag); // Character ID
185 swf_GetU8(tag); // Flags;
187 offsetpos = swf_GetTagPos(tag); // first offset
190 while (swf_GetU8(tag)) // state -> parse ButtonRecord
191 { swf_GetU16(tag); // id
192 swf_GetU16(tag); // layer
193 swf_GetMatrix(tag,NULL); // matrix
194 swf_GetCXForm(tag,NULL,1); // cxform
201 if(tag->pos >= tag->len)
204 offsetpos = swf_GetU16(tag);
205 condition = swf_GetU16(tag); // condition
207 actions = swf_ActionGet(tag);
208 printf("%s condition %04x\n", prefix, condition);
209 swf_DumpActions(actions, prefix);
212 swf_SetTagPos(tag,oldTagPos);
216 void dumpButtonActions(TAG*tag, char*prefix)
219 swf_GetU16(tag); // id
220 while (swf_GetU8(tag)) // state -> parse ButtonRecord
221 { swf_GetU16(tag); // id
222 swf_GetU16(tag); // layer
223 swf_GetMatrix(tag,NULL); // matrix
225 actions = swf_ActionGet(tag);
226 swf_DumpActions(actions, prefix);
229 #define ET_HASTEXT 32768
230 #define ET_WORDWRAP 16384
231 #define ET_MULTILINE 8192
232 #define ET_PASSWORD 4096
233 #define ET_READONLY 2048
234 #define ET_HASTEXTCOLOR 1024
235 #define ET_HASMAXLENGTH 512
236 #define ET_HASFONT 256
239 #define ET_HASLAYOUT 32
240 #define ET_NOSELECT 16
244 #define ET_USEOUTLINES 1
250 void textcallback(int*glyphs, int nr, int fontid)
253 printf(" <%2d glyphs in font %2d> ",nr, fontid);
254 for(t=0;t<fontnum;t++)
256 if(fonts[t]->id == fontid) {
266 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
267 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
270 a = fonts[font]->glyph2ascii[glyphs[t]];
277 printf("\\x%x", (int)a);
282 void handleText(TAG*tag)
285 swf_FontExtract_DefineTextCallback(-1,0,tag,4, textcallback);
288 void handleDefineSound(TAG*tag)
290 U16 id = swf_GetU16(tag);
291 U8 flags = swf_GetU8(tag);
292 int compression = (flags>>4)&3;
293 int rate = (flags>>2)&3;
294 int bits = flags&2?16:8;
295 int stereo = flags&1;
297 if(compression == 0) printf("Raw ");
298 else if(compression == 1) printf("ADPCM ");
299 else if(compression == 2) printf("MP3 ");
301 if(rate == 0) printf("5.5Khz ");
302 if(rate == 1) printf("11Khz ");
303 if(rate == 2) printf("22Khz ");
304 if(rate == 3) printf("44Khz ");
305 printf("%dBit ", bits);
306 if(stereo) printf("stereo");
311 void handleDefineBits(TAG*tag)
317 id = swf_GetU16(tag);
318 mode = swf_GetU8(tag);
319 width = swf_GetU16(tag);
320 height = swf_GetU16(tag);
321 printf(" image %dx%d",width,height);
322 if(mode == 3) printf(" (8 bpp)");
323 else if(mode == 4) printf(" (16 bpp)");
324 else if(mode == 5) printf(" (32 bpp)");
325 else printf(" (? bpp)");
328 void handleEditText(TAG*tag)
333 id = swf_GetU16(tag);
335 //swf_ResetReadBits(tag);
340 flags = swf_GetBits(tag,16);
341 if(flags & ET_HASFONT) {
342 swf_GetU16(tag); //font
343 swf_GetU16(tag); //fontheight
345 if(flags & ET_HASTEXTCOLOR) {
346 swf_GetU8(tag); //rgba
351 if(flags & ET_HASMAXLENGTH) {
352 swf_GetU16(tag); //maxlength
354 if(flags & ET_HASLAYOUT) {
355 swf_GetU8(tag); //align
356 swf_GetU16(tag); //left margin
357 swf_GetU16(tag); //right margin
358 swf_GetU16(tag); //indent
359 swf_GetU16(tag); //leading
361 printf(" variable \"%s\"", &tag->data[tag->pos]);
363 if(flags & (ET_X1 | ET_X2 | ET_X3 | ET_X0))
365 printf(" undefined flags: %d%d%d%d",
372 while(tag->data[tag->pos++]);
373 if(flags & ET_HASTEXT)
374 // printf(" text \"%s\"\n", &tag->data[tag->pos])
377 void printhandlerflags(U32 handlerflags)
379 if(handlerflags&1) printf("[on load]");
380 if(handlerflags&2) printf("[enter frame]");
381 if(handlerflags&4) printf("[unload]");
382 if(handlerflags&8) printf("[mouse move]");
383 if(handlerflags&16) printf("[mouse down]");
384 if(handlerflags&32) printf("[mouse up]");
385 if(handlerflags&64) printf("[key down]");
386 if(handlerflags&128) printf("[key up]");
388 if(handlerflags&256) printf("[data]");
389 if(handlerflags&512) printf("[initialize]");
390 if(handlerflags&1024) printf("[mouse press]");
391 if(handlerflags&2048) printf("[mouse release]");
392 if(handlerflags&4096) printf("[mouse release outside]");
393 if(handlerflags&8192) printf("[mouse rollover]");
394 if(handlerflags&16384) printf("[mouse rollout]");
395 if(handlerflags&32768) printf("[mouse drag over]");
397 if(handlerflags&0x10000) printf("[mouse drag out]");
398 if(handlerflags&0x20000) printf("[key press]");
399 if(handlerflags&0x40000) printf("[construct even]");
400 if(handlerflags&0xfff80000) printf("[???]");
402 void handleVideoStream(TAG*tag, char*prefix)
404 U16 id = swf_GetU16(tag);
405 U16 frames = swf_GetU16(tag);
406 U16 width = swf_GetU16(tag);
407 U16 height = swf_GetU16(tag);
408 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
409 U8 codec = swf_GetU8(tag);
410 printf(" (%d frames, %dx%d", frames, width, height);
414 printf(" sorenson h.263)");
416 printf(" codec 0x%02x)", codec);
418 void handleVideoFrame(TAG*tag, char*prefix)
420 U32 code, version, reference, sizeflags;
421 U32 width=0, height=0;
423 U16 id = swf_GetU16(tag);
424 U16 frame = swf_GetU16(tag);
425 U8 deblock,flags, tmp, bit;
427 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
428 printf(" (frame %d) ", frame);
430 /* video packet follows */
431 code = swf_GetBits(tag, 17);
432 version = swf_GetBits(tag, 5);
433 reference = swf_GetBits(tag, 8);
435 sizeflags = swf_GetBits(tag, 3);
438 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
439 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
440 case 2: width = 352; height = 288; break;
441 case 3: width = 176; height = 144; break;
442 case 4: width = 128; height = 96; break;
443 case 5: width = 320; height = 240; break;
444 case 6: width = 160; height = 120; break;
445 case 7: width = -1; height = -1;/*reserved*/ break;
447 printf("%dx%d ", width, height);
448 type = swf_GetBits(tag, 2);
449 printf("%s", types[type]);
451 deblock = swf_GetBits(tag, 1);
453 printf(" deblock ", deblock);
454 quantizer = swf_GetBits(tag, 5);
455 printf(" quant: %d ", quantizer);
458 void handlePlaceObject2(TAG*tag, char*prefix)
460 U8 flags = swf_GetU8(tag);
464 int ppos[3] = {0,0,0};
465 swf_GetU16(tag); //depth
468 if(flags&2) swf_GetU16(tag); //id
470 swf_GetMatrix(tag,&m);
472 ppos[0] += sprintf(pstr[0], "| Matrix ");
473 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
474 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
478 swf_GetCXForm(tag, &cx, 1);
480 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
481 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);
482 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
486 U16 ratio = swf_GetU16(tag); //ratio
488 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
489 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
490 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
494 U16 clip = swf_GetU16(tag); //clip
496 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
497 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
498 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
501 if(flags&32) { while(swf_GetU8(tag)); }
502 if(placements && ppos[0]) {
504 printf("%s %s\n", prefix, pstr[0]);
505 printf("%s %s\n", prefix, pstr[1]);
506 printf("%s %s", prefix, pstr[2]);
515 reserved = swf_GetU16(tag); // must be 0
516 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
518 printf("Unknown parameter field not zero: %04x\n", reserved);
521 printf("global flags: %04x\n", globalflags);
523 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
525 handlerflags = swf_GetU32(tag);
528 while(handlerflags) {
533 globalflags &= ~handlerflags;
534 printf("%s flags %08x ",prefix, handlerflags);
535 printhandlerflags(handlerflags);
536 length = swf_GetU32(tag);
537 printf(", %d bytes actioncode\n",length);
538 a = swf_ActionGet(tag);
539 swf_DumpActions(a,prefix);
542 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
544 if(globalflags) // should go to sterr.
545 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
547 printf(" has action code\n");
552 void handlePlaceObject(TAG*tag, char*prefix)
557 void fontcallback1(U16 id,U8 * name)
561 void fontcallback2(U16 id,U8 * name)
563 swf_FontExtract(&swf,id,&fonts[fontnum]);
567 static U8 printable(U8 a)
569 if(a<32 || a==127) return '.';
572 void hexdumpTag(TAG*tag, char* prefix)
576 printf(" %s-=> ",prefix);
577 for(t=0;t<tag->len;t++) {
578 printf("%02x ", tag->data[t]);
579 ascii[t&15] = printable(tag->data[t]);
580 if((t && ((t&15)==15)) || (t==tag->len-1))
582 int s,p=((t-1)&15)+1;
588 printf(" %s\n", ascii);
590 printf(" %s\n %s-=> ",ascii,prefix);
595 void handleExportAssets(TAG*tag, char* prefix)
601 num = swf_GetU16(tag);
604 id = swf_GetU16(tag);
605 name = swf_GetString(tag);
606 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
610 void dumperror(const char* format, ...)
615 va_start(arglist, format);
616 vsprintf(buf, format, arglist);
620 printf("==== Error: %s ====\n", buf);
623 static char strbuf[800];
626 char* timestring(double f)
628 int hours = (int)(f/3600);
629 int minutes = (int)((f-hours*3600)/60);
630 int seconds = (int)((f-hours*3600-minutes*60));
631 int useconds = (int)((f-(int)f)*1000+0.5);
634 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
635 return &strbuf[bufpos];
638 int main (int argc,char ** argv)
646 char issprite = 0; // are we inside a sprite definition?
649 char* spriteframelabel = 0;
650 char* framelabel = 0;
654 memset(idtab,0,65536);
656 processargs(argc, argv);
660 fprintf(stderr, "You must supply a filename.\n");
664 f = open(filename,O_RDONLY|O_BINARY);
669 sprintf(buffer, "Couldn't open %s", filename);
673 if FAILED(swf_ReadSWF(f,&swf))
675 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
682 if(statbuf.st_size != swf.fileSize && !swf.compressed)
683 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
684 statbuf.st_size, swf.fileSize);
685 filesize = statbuf.st_size;
690 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
691 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
695 printf("-X %d", xsize);
701 printf("-Y %d", ysize);
707 printf("-r %.2f", swf.frameRate/256.0);
713 printf("-f %d", swf.frameCount);
720 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
721 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0"};
722 if(swf.fileVersion>8) {
723 fprintf(stderr, "Fileversion>8\n");
726 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
728 //" BGCOLOR=#ffffffff\n"?
730 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
731 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
732 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
733 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
734 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
735 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
736 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
737 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
738 " TYPE=\"application/x-shockwave-flash\"\n"
739 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
741 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
742 filename, filename, xsize, ysize);
745 printf("[HEADER] File version: %d\n", swf.fileVersion);
747 printf("[HEADER] File is zlib compressed.");
748 if(filesize && swf.fileSize)
749 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
753 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
754 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
755 printf("[HEADER] Frame count: %d\n",swf.frameCount);
756 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
757 if(swf.movieSize.xmin)
758 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
761 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
762 if(swf.movieSize.ymin)
763 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
771 swf_FontEnumerate(&swf,&fontcallback1);
772 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
774 swf_FontEnumerate(&swf,&fontcallback2);
778 char*name = swf_TagGetName(tag);
781 dumperror("Unknown tag:0x%03x", tag->id);
785 if(swf_TagGetName(tag)) {
786 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
788 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
791 if(tag->id == ST_FREECHARACTER) {
792 U16 id = swf_GetU16(tag);
796 if(swf_isDefiningTag(tag)) {
797 U16 id = swf_GetDefineID(tag);
798 printf(" defines id %04d", id);
800 dumperror("Id %04d is defined more than once.", id);
803 else if(swf_isPseudoDefiningTag(tag)) {
804 U16 id = swf_GetDefineID(tag);
805 printf(" adds information to id %04d", id);
807 dumperror("Id %04d is not yet defined.\n", id);
809 else if(tag->id == ST_PLACEOBJECT) {
810 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
812 printf(" name \"%s\"",swf_GetName(tag));
813 handlePlaceObject(tag, myprefix);
815 else if(tag->id == ST_PLACEOBJECT2) {
822 printf(" id %04d",swf_GetPlaceID(tag));
826 printf(" at depth %04d", swf_GetDepth(tag));
828 printf(" name \"%s\"",swf_GetName(tag));
830 else if(tag->id == ST_REMOVEOBJECT) {
831 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
833 else if(tag->id == ST_REMOVEOBJECT2) {
834 printf(" removes object from depth %04d", swf_GetDepth(tag));
836 else if(tag->id == ST_FREECHARACTER) {
837 printf(" frees object %04d", swf_GetPlaceID(tag));
839 else if(tag->id == ST_STARTSOUND) {
842 id = swf_GetU16(tag);
843 flags = swf_GetU8(tag);
845 printf(" stops sound with id %04d", id);
847 printf(" starts sound with id %04d", id);
849 printf(" (if not already playing)");
855 printf(" looping %d times", swf_GetU16(tag));
858 else if(tag->id == ST_FRAMELABEL) {
859 int l = strlen(tag->data);
860 printf(" \"%s\"", tag->data);
862 printf(" has %d extra bytes", tag->len-1-l);
863 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
866 if((framelabel && !issprite) ||
867 (spriteframelabel && issprite)) {
868 dumperror("Frame %d has more than one label",
869 issprite?spriteframe:mainframe);
871 if(issprite) spriteframelabel = tag->data;
872 else framelabel = tag->data;
874 else if(tag->id == ST_SHOWFRAME) {
875 char*label = issprite?spriteframelabel:framelabel;
876 int frame = issprite?spriteframe:mainframe;
879 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
881 if(issprite) spriteframe++;
887 printf(" %d (%s)", frame, timestring(frame*(256.0/(swf.frameRate+0.1))));
889 printf(" %d-%d (%s-%s)", frame, nframe,
890 timestring(frame*(256.0/(swf.frameRate+0.1))),
891 timestring(nframe*(256.0/(swf.frameRate+0.1)))
894 printf(" (label \"%s\")", label);
895 if(issprite) {spriteframe++; spriteframelabel = 0;}
896 if(!issprite) {mainframe++; framelabel = 0;}
899 if(tag->id == ST_SETBACKGROUNDCOLOR) {
900 U8 r = swf_GetU8(tag);
901 U8 g = swf_GetU8(tag);
902 U8 b = swf_GetU8(tag);
903 printf(" (%02x/%02x/%02x)\n",r,g,b);
905 else if(tag->id == ST_PROTECT) {
907 printf(" %s\n", swf_GetString(tag));
910 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
911 tag->id == ST_DEFINEBITSLOSSLESS2) {
912 handleDefineBits(tag);
915 else if(tag->id == ST_DEFINESOUND) {
916 handleDefineSound(tag);
919 else if(tag->id == ST_VIDEOFRAME) {
920 handleVideoFrame(tag, myprefix);
923 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
924 handleVideoStream(tag, myprefix);
927 else if(tag->id == ST_DEFINEEDITTEXT) {
931 else if(tag->id == ST_DEFINEMOVIE) {
932 U16 id = swf_GetU16(tag);
933 char*s = swf_GetString(tag);
934 printf(" URL: %s\n", s);
936 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
942 else if(tag->id == ST_PLACEOBJECT2) {
944 else if(tag->id == ST_NAMECHARACTER) {
946 printf(" \"%s\"\n", swf_GetString(tag));
952 sprintf(myprefix, " %s", prefix);
954 if(tag->id == ST_DEFINESPRITE) {
955 sprintf(prefix, " ");
957 dumperror("Sprite definition inside a sprite definition");
961 spriteframelabel = 0;
963 else if(tag->id == ST_END) {
966 spriteframelabel = 0;
968 dumperror("End Tag not empty");
970 else if(tag->id == ST_EXPORTASSETS) {
971 handleExportAssets(tag, myprefix);
973 else if(tag->id == ST_DOACTION && action) {
975 actions = swf_ActionGet(tag);
976 swf_DumpActions(actions, myprefix);
978 else if(tag->id == ST_DEFINEBUTTON && action) {
979 dumpButtonActions(tag, myprefix);
981 else if(tag->id == ST_DEFINEBUTTON2 && action) {
982 dumpButton2Actions(tag, myprefix);
984 else if(tag->id == ST_PLACEOBJECT2) {
985 handlePlaceObject2(tag, myprefix);
988 if(tag->len && used) {
989 int num = swf_GetNumUsedIDs(tag);
993 used = (int*)malloc(sizeof(int)*num);
994 swf_GetUsedIDs(tag, used);
995 printf("%s%suses IDs: ", indent, prefix);
997 swf_SetTagPos(tag, used[t]);
998 printf("%d%s", swf_GetU16(tag), t<num-1?", ":"");
1004 if(tag->len && hex) {
1005 hexdumpTag(tag, prefix);