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
467 if(flags&2) swf_GetU16(tag); //id
469 swf_GetMatrix(tag,&m);
471 ppos[0] += sprintf(pstr[0], "| Matrix ");
472 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
473 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
477 swf_GetCXForm(tag, &cx, 1);
479 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
480 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);
481 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
485 U16 ratio = swf_GetU16(tag); //ratio
487 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
488 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
489 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
493 U16 clip = swf_GetU16(tag); //clip
495 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
496 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", clip);
497 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
500 if(flags&32) { while(swf_GetU8(tag)); }
501 if(placements && ppos[0]) {
503 printf("%s %s\n", prefix, pstr[0]);
504 printf("%s %s\n", prefix, pstr[1]);
505 printf("%s %s", prefix, pstr[2]);
514 reserved = swf_GetU16(tag); // must be 0
515 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
517 printf("Unknown parameter field not zero: %04x\n", reserved);
520 printf("global flags: %04x\n", globalflags);
522 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
524 handlerflags = swf_GetU32(tag);
527 while(handlerflags) {
532 globalflags &= ~handlerflags;
533 printf("%s flags %08x ",prefix, handlerflags);
534 printhandlerflags(handlerflags);
535 length = swf_GetU32(tag);
536 printf(", %d bytes actioncode\n",length);
537 a = swf_ActionGet(tag);
538 swf_DumpActions(a,prefix);
541 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
543 if(globalflags) // should go to sterr.
544 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
546 printf(" has action code\n");
551 void handlePlaceObject(TAG*tag, char*prefix)
556 void fontcallback1(U16 id,U8 * name)
560 void fontcallback2(U16 id,U8 * name)
562 swf_FontExtract(&swf,id,&fonts[fontnum]);
566 static U8 printable(U8 a)
568 if(a<32 || a==127) return '.';
571 void hexdumpTag(TAG*tag, char* prefix)
575 printf(" %s-=> ",prefix);
576 for(t=0;t<tag->len;t++) {
577 printf("%02x ", tag->data[t]);
578 ascii[t&15] = printable(tag->data[t]);
579 if((t && ((t&15)==15)) || (t==tag->len-1))
581 int s,p=((t-1)&15)+1;
587 printf(" %s\n", ascii);
589 printf(" %s\n %s-=> ",ascii,prefix);
594 void handleExportAssets(TAG*tag, char* prefix)
600 num = swf_GetU16(tag);
603 id = swf_GetU16(tag);
604 name = swf_GetString(tag);
605 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
609 void dumperror(const char* format, ...)
614 va_start(arglist, format);
615 vsprintf(buf, format, arglist);
619 printf("==== Error: %s ====\n", buf);
622 static char strbuf[800];
625 char* timestring(double f)
627 int hours = (int)(f/3600);
628 int minutes = (int)((f-hours*3600)/60);
629 int seconds = (int)((f-hours*3600-minutes*60));
630 int useconds = (int)((f-(int)f)*1000+0.5);
633 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
634 return &strbuf[bufpos];
637 int main (int argc,char ** argv)
645 char issprite = 0; // are we inside a sprite definition?
648 char* spriteframelabel = 0;
649 char* framelabel = 0;
653 memset(idtab,0,65536);
655 processargs(argc, argv);
659 fprintf(stderr, "You must supply a filename.\n");
663 f = open(filename,O_RDONLY|O_BINARY);
668 sprintf(buffer, "Couldn't open %s", filename);
672 if FAILED(swf_ReadSWF(f,&swf))
674 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
681 if(statbuf.st_size != swf.fileSize && !swf.compressed)
682 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
683 statbuf.st_size, swf.fileSize);
684 filesize = statbuf.st_size;
689 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
690 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
694 printf("-X %d", xsize);
700 printf("-Y %d", ysize);
706 printf("-r %d", swf.frameRate*100/256);
712 printf("-f %d", swf.frameCount);
719 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
720 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0"};
721 if(swf.fileVersion>8) {
722 fprintf(stderr, "Fileversion>8\n");
725 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
727 //" BGCOLOR=#ffffffff\n"?
729 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
730 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
731 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
732 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
733 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
734 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
735 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
736 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
737 " TYPE=\"application/x-shockwave-flash\"\n"
738 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
740 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
741 filename, filename, xsize, ysize);
744 printf("[HEADER] File version: %d\n", swf.fileVersion);
746 printf("[HEADER] File is zlib compressed.");
747 if(filesize && swf.fileSize)
748 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
752 printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
753 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
754 printf("[HEADER] Frame count: %d\n",swf.frameCount);
755 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
756 if(swf.movieSize.xmin)
757 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
760 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
761 if(swf.movieSize.ymin)
762 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
770 swf_FontEnumerate(&swf,&fontcallback1);
771 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
773 swf_FontEnumerate(&swf,&fontcallback2);
777 char*name = swf_TagGetName(tag);
780 dumperror("Unknown tag:0x%03x", tag->id);
784 if(swf_TagGetName(tag)) {
785 printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
787 printf("[%03x] %9ld %sUNKNOWN TAG %03x", tag->id, tag->len, prefix, tag->id);
790 if(tag->id == ST_FREECHARACTER) {
791 U16 id = swf_GetU16(tag);
795 if(swf_isDefiningTag(tag)) {
796 U16 id = swf_GetDefineID(tag);
797 printf(" defines id %04d", id);
799 dumperror("Id %04d is defined more than once.", id);
802 else if(swf_isPseudoDefiningTag(tag)) {
803 U16 id = swf_GetDefineID(tag);
804 printf(" adds information to id %04d", id);
806 dumperror("Id %04d is not yet defined.\n", id);
808 else if(tag->id == ST_PLACEOBJECT) {
809 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
811 printf(" name \"%s\"",swf_GetName(tag));
812 handlePlaceObject(tag, myprefix);
814 else if(tag->id == ST_PLACEOBJECT2) {
821 printf(" id %04d",swf_GetPlaceID(tag));
825 printf(" at depth %04d", swf_GetDepth(tag));
827 printf(" name \"%s\"",swf_GetName(tag));
829 else if(tag->id == ST_REMOVEOBJECT) {
830 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
832 else if(tag->id == ST_REMOVEOBJECT2) {
833 printf(" removes object from depth %04d", swf_GetDepth(tag));
835 else if(tag->id == ST_FREECHARACTER) {
836 printf(" frees object %04d", swf_GetPlaceID(tag));
838 else if(tag->id == ST_STARTSOUND) {
841 id = swf_GetU16(tag);
842 flags = swf_GetU8(tag);
844 printf(" stops sound with id %04d", id);
846 printf(" starts sound with id %04d", id);
848 printf(" (if not already playing)");
854 printf(" looping %d times", swf_GetU16(tag));
857 else if(tag->id == ST_FRAMELABEL) {
858 int l = strlen(tag->data);
859 printf(" \"%s\"", tag->data);
861 printf(" has %d extra bytes", tag->len-1-l);
862 if(tag ->len-1-l == 1 && tag->data[tag->len-1] == 1)
865 if((framelabel && !issprite) ||
866 (spriteframelabel && issprite)) {
867 dumperror("Frame %d has more than one label",
868 issprite?spriteframe:mainframe);
870 if(issprite) spriteframelabel = tag->data;
871 else framelabel = tag->data;
873 else if(tag->id == ST_SHOWFRAME) {
874 char*label = issprite?spriteframelabel:framelabel;
875 int frame = issprite?spriteframe:mainframe;
878 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
880 if(issprite) spriteframe++;
886 printf(" %d (%s)", frame, timestring(frame*(256.0/(swf.frameRate+0.1))));
888 printf(" %d-%d (%s-%s)", frame, nframe,
889 timestring(frame*(256.0/(swf.frameRate+0.1))),
890 timestring(nframe*(256.0/(swf.frameRate+0.1)))
893 printf(" (label \"%s\")", label);
894 if(issprite) {spriteframe++; spriteframelabel = 0;}
895 if(!issprite) {mainframe++; framelabel = 0;}
898 if(tag->id == ST_SETBACKGROUNDCOLOR) {
899 U8 r = swf_GetU8(tag);
900 U8 g = swf_GetU8(tag);
901 U8 b = swf_GetU8(tag);
902 printf(" (%02x/%02x/%02x)\n",r,g,b);
904 else if(tag->id == ST_PROTECT) {
906 printf(" %s\n", swf_GetString(tag));
909 else if(tag->id == ST_DEFINEBITSLOSSLESS ||
910 tag->id == ST_DEFINEBITSLOSSLESS2) {
911 handleDefineBits(tag);
914 else if(tag->id == ST_DEFINESOUND) {
915 handleDefineSound(tag);
918 else if(tag->id == ST_VIDEOFRAME) {
919 handleVideoFrame(tag, myprefix);
922 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
923 handleVideoStream(tag, myprefix);
926 else if(tag->id == ST_DEFINEEDITTEXT) {
930 else if(tag->id == ST_DEFINEMOVIE) {
931 U16 id = swf_GetU16(tag);
932 char*s = swf_GetString(tag);
933 printf(" URL: %s\n", s);
935 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
941 else if(tag->id == ST_PLACEOBJECT2) {
943 else if(tag->id == ST_NAMECHARACTER) {
945 printf(" \"%s\"\n", swf_GetString(tag));
951 sprintf(myprefix, " %s", prefix);
953 if(tag->id == ST_DEFINESPRITE) {
954 sprintf(prefix, " ");
956 dumperror("Sprite definition inside a sprite definition");
960 spriteframelabel = 0;
962 else if(tag->id == ST_END) {
965 spriteframelabel = 0;
967 dumperror("End Tag not empty");
969 else if(tag->id == ST_EXPORTASSETS) {
970 handleExportAssets(tag, myprefix);
972 else if(tag->id == ST_DOACTION && action) {
974 actions = swf_ActionGet(tag);
975 swf_DumpActions(actions, myprefix);
977 else if(tag->id == ST_DEFINEBUTTON && action) {
978 dumpButtonActions(tag, myprefix);
980 else if(tag->id == ST_DEFINEBUTTON2 && action) {
981 dumpButton2Actions(tag, myprefix);
983 else if(tag->id == ST_PLACEOBJECT2) {
984 handlePlaceObject2(tag, myprefix);
987 if(tag->len && used) {
988 int num = swf_GetNumUsedIDs(tag);
992 used = (int*)malloc(sizeof(int)*num);
993 swf_GetUsedIDs(tag, used);
994 printf("%s%suses IDs: ", indent, prefix);
996 swf_SetTagPos(tag, used[t]);
997 printf("%d%s", swf_GetU16(tag), t<num-1?", ":"");
1003 if(tag->len && hex) {
1004 hexdumpTag(tag, prefix);