applied patches from Vicente Jimenez Aguilar
[swftools.git] / src / swfdump.c
blob1500d0b50452eb425a93af7b83d49677c3bde067
1 /* swfdump.c
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
25 #include <sys/stat.h>
26 #else
27 #undef HAVE_STAT
28 #endif
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #else
33 #undef HAVE_STAT
34 #endif
36 #include <unistd.h>
37 #include <stdio.h>
38 #include <fcntl.h>
39 #include <stdarg.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
47 once */
48 static char idtab[65536];
49 static char * indent = " ";
51 static int placements = 0;
52 static int action = 0;
53 static int html = 0;
54 static int xhtml = 0;
55 static int xy = 0;
56 static int showtext = 0;
57 static int showshapes = 0;
58 static int hex = 0;
59 static int used = 0;
60 static int bbox = 0;
61 static int cumulative = 0;
62 static int showfonts = 0;
63 static int showbuttons = 0;
65 static struct options_t options[] = {
66 {"h", "help"},
67 {"D", "full"},
68 {"V", "version"},
69 {"e", "html"},
70 {"E", "xhtml"},
71 {"a", "action"},
72 {"t", "text"},
73 {"s", "shapes"},
74 {"F", "fonts"},
75 {"p", "placements"},
76 {"B", "buttons"},
77 {"b", "bbox"},
78 {"X", "width"},
79 {"Y", "height"},
80 {"r", "rate"},
81 {"f", "frames"},
82 {"d", "hex"},
83 {"u", "used"},
84 {0,0}
87 int args_callback_option(char*name,char*val)
89 if(!strcmp(name, "V")) {
90 printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
91 exit(0);
93 else if(name[0]=='a') {
94 action = 1;
95 return 0;
97 else if(name[0]=='p') {
98 placements = 1;
99 return 0;
101 else if(name[0]=='t') {
102 showtext = 1;
103 return 0;
105 else if(name[0]=='s') {
106 showshapes = 1;
107 return 0;
109 else if(name[0]=='e') {
110 html = 1;
111 return 0;
113 else if(name[0]=='c') {
114 cumulative = 1;
115 return 0;
117 else if(name[0]=='E') {
118 html = 1;
119 xhtml = 1;
120 return 0;
122 else if(name[0]=='X') {
123 xy |= 1;
124 return 0;
126 else if(name[0]=='Y') {
127 xy |= 2;
128 return 0;
130 else if(name[0]=='r') {
131 xy |= 4;
132 return 0;
134 else if(name[0]=='f') {
135 xy |= 8;
136 return 0;
138 else if(name[0]=='F') {
139 showfonts = 1;
140 return 0;
142 else if(name[0]=='d') {
143 hex = 1;
144 return 0;
146 else if(name[0]=='u') {
147 used = 1;
148 return 0;
150 else if(name[0]=='b') {
151 bbox = 1;
152 return 0;
154 else if(name[0]=='B') {
155 showbuttons = 1;
156 return 0;
158 else if(name[0]=='D') {
159 showbuttons = action = placements = showtext = showshapes = 1;
160 return 0;
162 else {
163 printf("Unknown option: -%s\n", name);
164 exit(1);
167 return 0;
169 int args_callback_longoption(char*name,char*val)
171 return args_long2shortoption(options, name, val);
173 void args_callback_usage(char *name)
175 printf("\n");
176 printf("Usage: %s [-atpdu] file.swf\n", name);
177 printf("\n");
178 printf("-h , --help Print short help message and exit\n");
179 printf("-D , --full Show everything. Same as -atp\n");
180 printf("-V , --version Print version info and exit\n");
181 printf("-e , --html Print out html code for embedding the file\n");
182 printf("-E , --xhtml Print out xhtml code for embedding the file\n");
183 printf("-a , --action Disassemble action tags\n");
184 printf("-t , --text Show text fields (like swfstrings).\n");
185 printf("-s , --shapes Show shape coordinates/styles\n");
186 printf("-F , --fonts Show font information\n");
187 printf("-p , --placements Show placement information\n");
188 printf("-B , --buttons Show button information\n");
189 printf("-b , --bbox Print tag's bounding boxes\n");
190 printf("-X , --width Prints out a string of the form \"-X width\".\n");
191 printf("-Y , --height Prints out a string of the form \"-Y height\".\n");
192 printf("-r , --rate Prints out a string of the form \"-r rate\".\n");
193 printf("-f , --frames Prints out a string of the form \"-f framenum\".\n");
194 printf("-d , --hex Print hex output of tag data, too.\n");
195 printf("-u , --used Show referred IDs for each Tag.\n");
196 printf("\n");
198 int args_callback_command(char*name,char*val)
200 if(filename) {
201 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
202 filename, name);
204 filename = name;
205 return 0;
208 char* what;
209 char* testfunc(char*str)
211 printf("%s: %s\n", what, str);
212 return 0;
215 void dumpButton2Actions(TAG*tag, char*prefix)
217 U32 oldTagPos;
218 U32 offsetpos;
219 U32 condition;
221 oldTagPos = swf_GetTagPos(tag);
223 // scan DefineButton2 Record
225 swf_GetU16(tag); // Character ID
226 swf_GetU8(tag); // Flags;
228 offsetpos = swf_GetTagPos(tag); // first offset
229 swf_GetU16(tag);
231 while (swf_GetU8(tag)) // state -> parse ButtonRecord
232 { swf_GetU16(tag); // id
233 swf_GetU16(tag); // layer
234 swf_GetMatrix(tag,NULL); // matrix
235 swf_GetCXForm(tag,NULL,1); // cxform
238 while(offsetpos)
239 { U8 a;
240 ActionTAG*actions;
242 if(tag->pos >= tag->len)
243 break;
245 offsetpos = swf_GetU16(tag);
246 condition = swf_GetU16(tag); // condition
248 actions = swf_ActionGet(tag);
249 printf("%s condition %04x\n", prefix, condition);
250 swf_DumpActions(actions, prefix);
253 swf_SetTagPos(tag,oldTagPos);
254 return;
257 void dumpButtonActions(TAG*tag, char*prefix)
259 ActionTAG*actions;
260 swf_SetTagPos(tag, 0);
261 swf_GetU16(tag); // id
262 while (swf_GetU8(tag)) // state -> parse ButtonRecord
263 { swf_GetU16(tag); // id
264 swf_GetU16(tag); // layer
265 swf_GetMatrix(tag,NULL); // matrix
267 actions = swf_ActionGet(tag);
268 swf_DumpActions(actions, prefix);
269 swf_ActionFree(actions);
272 void dumpButton(TAG*tag, char*prefix)
274 swf_SetTagPos(tag, 0);
275 swf_GetU16(tag); // id
276 while (1) {
277 U8 flags = swf_GetU8(tag);
278 if(!flags)
279 break;
280 U16 id = swf_GetU16(tag);
281 U16 depth = swf_GetU16(tag);
282 char event[80];
283 sprintf(event, "%s%s%s%s",
284 (flags&BS_HIT)?"[hit]":"",
285 (flags&BS_DOWN)?"[down]":"",
286 (flags&BS_OVER)?"[over]":"",
287 (flags&BS_UP)?"[up]":"");
288 if(flags&0xf0) {
289 printf("%s | Show %d at depth %d for %s flags=%02x\n", prefix, id, depth, event, flags);
290 } else {
291 printf("%s | Show %d at depth %d for %s\n", prefix, id, depth, event);
293 swf_GetMatrix(tag,NULL); // matrix
297 void dumpFont(TAG*tag, char*prefix)
299 SWFFONT* font = malloc(sizeof(SWFFONT));
300 memset(font, 0, sizeof(SWFFONT));
301 if(tag->id == ST_DEFINEFONT2 || tag->id == ST_DEFINEFONT3) {
302 swf_FontExtract_DefineFont2(0, font, tag);
303 } else if(tag->id == ST_DEFINEFONT) {
304 swf_FontExtract_DefineFont(0, font, tag);
305 } else {
306 printf("%sCan't parse %s yet\n", prefix,swf_TagGetName(tag));
308 printf("%sID: %d\n", prefix,font->id);
309 printf("%sVersion: %d\n", prefix,font->version);
310 printf("%sname: %s\n", prefix,font->name);
311 printf("%scharacters: %d\n", prefix,font->numchars);
312 printf("%shightest mapped unicode value: %d\n", prefix,font->maxascii);
313 if(font->layout)
315 printf("%sascent:%.2f\n", prefix,font->layout->ascent / 20.0);
316 printf("%sdescent:%.2f\n", prefix,font->layout->descent / 20.0);
317 printf("%sleading:%.2f\n", prefix,font->layout->leading / 20.0);
318 printf("%skerning records:%d\n", prefix,font->layout->kerningcount);
320 printf("%sstyle: %d\n", prefix,font->style);
321 printf("%sencoding: %02x\n", prefix,font->encoding);
322 printf("%slanguage: %02x\n", prefix,font->language);
323 int t;
324 for(t=0;t<font->numchars;t++) {
325 int u = font->glyph2ascii?font->glyph2ascii[t]:-1;
326 char ustr[16];
327 if(u>=32) sprintf(ustr, " '%c'", u);
328 else sprintf(ustr, " 0x%02x", u);
329 printf("%s== Glyph %d: advance=%d encoding=%d%s ==\n", prefix, t, font->glyph[t].advance, u, ustr);
330 SHAPE2* shape = swf_ShapeToShape2(font->glyph[t].shape);
331 SHAPELINE*line = shape->lines;
333 while(line) {
334 if(line->type == moveTo) {
335 printf("%smoveTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
336 } else if(line->type == lineTo) {
337 printf("%slineTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
338 } else if(line->type == splineTo) {
339 printf("%ssplineTo (%.2f %.2f) %.2f %.2f\n", prefix,
340 line->sx/20.0, line->sy/20.0,
341 line->x/20.0, line->y/20.0
344 line = line->next;
346 swf_Shape2Free(shape);
347 free(shape);
351 not part of the file
353 printf("%sencoding table:", prefix, prefix);
354 char filled0=0, lastfilled=0;
355 for(t=0;t<font->maxascii;t++) {
356 if((t&15)==0) {
357 printf("\n%s%08x ", prefix, t);
358 int s;
359 if(!filled0 && t) {
360 for(s=t;s<font->maxascii;s++) {
361 if(font->ascii2glyph[s]>=0) break;
363 if(s>t+32) {
364 printf("*");
365 t = ((s-16)&~15)-1;
366 continue;
369 filled0 = 0;
370 for(s=t;s<t+16 && s<font->maxascii;s++) {
371 if(font->ascii2glyph[s]>=0) filled0=1;
374 printf("%4d ", font->ascii2glyph[t]);
376 printf("\n");*/
378 swf_FontFree(font);
381 static SWF swf;
382 static int fontnum = 0;
383 static SWFFONT**fonts;
385 void textcallback(void*self, int*glyphs, int*xpos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color)
387 int font=-1,t;
388 if(nr<1)
389 return;
390 printf(" <%2d glyphs in font %04d size %d, color #%02x%02x%02x%02x at %.2f,%.2f> ",nr, fontid, fontsize, color->r, color->g, color->b, color->a, (startx+xpos[0])/20.0, starty/20.0);
391 for(t=0;t<fontnum;t++)
393 if(fonts[t]->id == fontid) {
394 font = t;
395 break;
399 for(t=0;t<nr;t++)
401 unsigned char a;
402 if(font>=0) {
403 if(glyphs[t] >= fonts[font]->numchars /*glyph is in range*/
404 || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
405 ) a = glyphs[t];
406 else {
407 if(fonts[font]->glyph2ascii[glyphs[t]])
408 a = fonts[font]->glyph2ascii[glyphs[t]];
409 else
410 a = glyphs[t];
412 } else {
413 a = glyphs[t];
415 if(a>=32)
416 printf("%c", a);
417 else
418 printf("\\x%x", (int)a);
420 printf("\n");
423 void handleText(TAG*tag, char*prefix)
425 printf("\n");
426 if(placements) {
427 swf_SetTagPos(tag, 0);
428 swf_GetU16(tag);
429 swf_GetRect(tag, 0);
430 swf_ResetReadBits(tag);
431 MATRIX m;
432 swf_GetMatrix(tag, &m);
433 printf("%s| Matrix\n",prefix);
434 printf("%s| %5.3f %5.3f %6.2f\n", prefix, m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
435 printf("%s| %5.3f %5.3f %6.2f\n", prefix, m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
436 swf_SetTagPos(tag, 0);
438 if(showtext) {
439 swf_ParseDefineText(tag,textcallback, 0);
443 void handleDefineSound(TAG*tag)
445 U16 id = swf_GetU16(tag);
446 U8 flags = swf_GetU8(tag);
447 int compression = (flags>>4)&7;
448 int rate = (flags>>2)&3;
449 int bits = flags&2?16:8;
450 int stereo = flags&1;
451 printf(" (");
452 if(compression == 0) printf("Raw ");
453 else if(compression == 1) printf("ADPCM ");
454 else if(compression == 2) printf("MP3 ");
455 else if(compression == 3) printf("Raw little-endian ");
456 else if(compression == 6) printf("ASAO ");
457 else printf("? ");
458 if(rate == 0) printf("5.5Khz ");
459 if(rate == 1) printf("11Khz ");
460 if(rate == 2) printf("22Khz ");
461 if(rate == 3) printf("44Khz ");
462 printf("%dBit ", bits);
463 if(stereo) printf("stereo");
464 else printf("mono");
465 printf(")");
468 void handleDefineBits(TAG*tag)
470 U16 id;
471 U8 mode;
472 U16 width,height;
473 int bpp;
474 id = swf_GetU16(tag);
475 mode = swf_GetU8(tag);
476 width = swf_GetU16(tag);
477 height = swf_GetU16(tag);
478 printf(" image %dx%d",width,height);
479 if(mode == 3) printf(" (8 bpp)");
480 else if(mode == 4) printf(" (16 bpp)");
481 else if(mode == 5) printf(" (32 bpp)");
482 else printf(" (? bpp)");
485 void handleEditText(TAG*tag)
487 U16 id ;
488 U16 flags;
489 int t;
490 id = swf_GetU16(tag);
491 swf_GetRect(tag,0);
493 //swf_ResetReadBits(tag);
495 if (tag->readBit)
496 { tag->pos++;
497 tag->readBit = 0;
499 flags = swf_GetBits(tag,16);
500 if(flags & ET_HASFONT) {
501 swf_GetU16(tag); //font
502 swf_GetU16(tag); //fontheight
504 if(flags & ET_HASTEXTCOLOR) {
505 swf_GetU8(tag); //rgba
506 swf_GetU8(tag);
507 swf_GetU8(tag);
508 swf_GetU8(tag);
510 if(flags & ET_HASMAXLENGTH) {
511 swf_GetU16(tag); //maxlength
513 if(flags & ET_HASLAYOUT) {
514 swf_GetU8(tag); //align
515 swf_GetU16(tag); //left margin
516 swf_GetU16(tag); //right margin
517 swf_GetU16(tag); //indent
518 swf_GetU16(tag); //leading
520 printf(" variable \"%s\" ", &tag->data[tag->pos]);
521 if(flags & ET_HTML) printf("(html)");
522 if(flags & ET_NOSELECT) printf("(noselect)");
523 if(flags & ET_PASSWORD) printf("(password)");
524 if(flags & ET_READONLY) printf("(readonly)");
526 if(flags & (ET_X1 | ET_X3 ))
528 printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
531 while(tag->data[tag->pos++]);
532 if(flags & ET_HASTEXT)
533 // printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
536 void printhandlerflags(U32 handlerflags)
538 if(handlerflags&1) printf("[on load]");
539 if(handlerflags&2) printf("[enter frame]");
540 if(handlerflags&4) printf("[unload]");
541 if(handlerflags&8) printf("[mouse move]");
542 if(handlerflags&16) printf("[mouse down]");
543 if(handlerflags&32) printf("[mouse up]");
544 if(handlerflags&64) printf("[key down]");
545 if(handlerflags&128) printf("[key up]");
547 if(handlerflags&256) printf("[data]");
548 if(handlerflags&512) printf("[initialize]");
549 if(handlerflags&1024) printf("[mouse press]");
550 if(handlerflags&2048) printf("[mouse release]");
551 if(handlerflags&4096) printf("[mouse release outside]");
552 if(handlerflags&8192) printf("[mouse rollover]");
553 if(handlerflags&16384) printf("[mouse rollout]");
554 if(handlerflags&32768) printf("[mouse drag over]");
556 if(handlerflags&0x10000) printf("[mouse drag out]");
557 if(handlerflags&0x20000) printf("[key press]");
558 if(handlerflags&0x40000) printf("[construct even]");
559 if(handlerflags&0xfff80000) printf("[???]");
561 void handleVideoStream(TAG*tag, char*prefix)
563 U16 id = swf_GetU16(tag);
564 U16 frames = swf_GetU16(tag);
565 U16 width = swf_GetU16(tag);
566 U16 height = swf_GetU16(tag);
567 U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
568 U8 codec = swf_GetU8(tag);
569 printf(" (%d frames, %dx%d", frames, width, height);
570 if(flags&1)
571 printf(" smoothed");
572 if(codec == 2)
573 printf(" sorenson h.263)");
574 else
575 printf(" codec 0x%02x)", codec);
577 void handleVideoFrame(TAG*tag, char*prefix)
579 U32 code, version, reference, sizeflags;
580 U32 width=0, height=0;
581 U8 type;
582 U16 id = swf_GetU16(tag);
583 U16 frame = swf_GetU16(tag);
584 U8 deblock,flags, tmp, bit;
585 U32 quantizer;
586 char*types[] = {"I-frame", "P-frame", "disposable P-frame", "<reserved>"};
587 printf(" (frame %d) ", frame);
589 /* video packet follows */
590 code = swf_GetBits(tag, 17);
591 version = swf_GetBits(tag, 5);
592 reference = swf_GetBits(tag, 8);
594 sizeflags = swf_GetBits(tag, 3);
595 switch(sizeflags)
597 case 0: width = swf_GetBits(tag, 8); height = swf_GetBits(tag, 8); break;
598 case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
599 case 2: width = 352; height = 288; break;
600 case 3: width = 176; height = 144; break;
601 case 4: width = 128; height = 96; break;
602 case 5: width = 320; height = 240; break;
603 case 6: width = 160; height = 120; break;
604 case 7: width = -1; height = -1;/*reserved*/ break;
606 printf("%dx%d ", width, height);
607 type = swf_GetBits(tag, 2);
608 printf("%s", types[type]);
610 deblock = swf_GetBits(tag, 1);
611 if(deblock)
612 printf(" deblock %d ", deblock);
613 quantizer = swf_GetBits(tag, 5);
614 printf(" quant: %d ", quantizer);
617 void dumpFilter(FILTER*filter)
619 if(filter->type == FILTERTYPE_BLUR) {
620 FILTER_BLUR*f = (FILTER_BLUR*)filter;
621 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
622 printf("passes: %d\n", f->passes);
623 } if(filter->type == FILTERTYPE_GLOW) {
624 FILTER_GLOW*f = (FILTER_GLOW*)filter;
625 printf("color %02x%02x%02x%02x\n", f->rgba.r,f->rgba.g,f->rgba.b,f->rgba.a);
626 printf("blurx: %f blury: %f strength: %f\n", f->blurx, f->blury, f->strength);
627 printf("passes: %d\n", f->passes);
628 printf("flags: %s%s%s\n",
629 f->knockout?"knockout ":"",
630 f->composite?"composite ":"",
631 f->innerglow?"innerglow":"");
632 } if(filter->type == FILTERTYPE_DROPSHADOW) {
633 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)filter;
634 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
635 printf("passes: %d\n", f->passes);
636 printf("angle: %f distance: %f\n", f->angle, f->distance);
637 printf("strength: %f passes: %d\n", f->strength, f->passes);
638 printf("flags: %s%s%s\n",
639 f->knockout?"knockout ":"",
640 f->composite?"composite ":"",
641 f->innershadow?"innershadow ":"");
642 } if(filter->type == FILTERTYPE_BEVEL) {
643 FILTER_BEVEL*f = (FILTER_BEVEL*)filter;
644 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
645 printf("passes: %d\n", f->passes);
646 printf("angle: %f distance: %f\n", f->angle, f->distance);
647 printf("strength: %f passes: %d\n", f->strength, f->passes);
648 printf("flags: %s%s%s%s\n",
649 f->ontop?"ontop":"",
650 f->knockout?"knockout ":"",
651 f->composite?"composite ":"",
652 f->innershadow?"innershadow ":"");
653 } if(filter->type == FILTERTYPE_GRADIENTGLOW) {
654 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)filter;
655 swf_DumpGradient(stdout, f->gradient);
656 printf("blurx: %f blury: %f\n", f->blurx, f->blury);
657 printf("angle: %f distance: %f\n", f->angle, f->distance);
658 printf("strength: %f passes: %d\n", f->strength, f->passes);
659 printf("flags: %s%s%s%s\n",
660 f->knockout?"knockout ":"",
661 f->ontop?"ontop ":"",
662 f->composite?"composite ":"",
663 f->innershadow?"innershadow ":"");
665 rfx_free(filter);
668 void handlePlaceObject23(TAG*tag, char*prefix)
670 U8 flags,flags2=0;
671 MATRIX m;
672 CXFORM cx;
673 char pstr[3][256];
674 int ppos[3] = {0,0,0};
675 swf_SetTagPos(tag, 0);
676 flags = swf_GetU8(tag);
677 if(tag->id == ST_PLACEOBJECT3)
678 flags2 = swf_GetU8(tag);
679 swf_GetU16(tag); //depth
681 //flags&1: move
682 if(flags&2) swf_GetU16(tag); //id
683 if(flags&4) {
684 swf_GetMatrix(tag,&m);
685 if(placements) {
686 ppos[0] += sprintf(pstr[0], "| Matrix ");
687 ppos[1] += sprintf(pstr[1], "| %5.3f %5.3f %6.2f ", m.sx/65536.0, m.r1/65536.0, m.tx/20.0);
688 ppos[2] += sprintf(pstr[2], "| %5.3f %5.3f %6.2f ", m.r0/65536.0, m.sy/65536.0, m.ty/20.0);
691 if(flags&8) {
692 swf_GetCXForm(tag, &cx, 1);
693 if(placements) {
694 ppos[0] += sprintf(pstr[0]+ppos[0], "| CXForm r g b a ");
695 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);
696 ppos[2] += sprintf(pstr[2]+ppos[2], "| add %4d %4d %4d %4d ", cx.r1, cx.g1, cx.b1, cx.a1);
699 if(flags&16) {
700 U16 ratio = swf_GetU16(tag); //ratio
701 if(placements) {
702 ppos[0] += sprintf(pstr[0]+ppos[0], "| Ratio ");
703 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-5d ", ratio);
704 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
707 if(flags&64) {
708 U16 clip = swf_GetU16(tag); //clip
709 if(placements) {
710 ppos[0] += sprintf(pstr[0]+ppos[0], "| Clip ");
711 ppos[1] += sprintf(pstr[1]+ppos[1], "| %-4d ", clip);
712 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
715 if(flags&32) { while(swf_GetU8(tag)); }
717 if(flags2&1) { // filter list
718 U8 num = swf_GetU8(tag);
719 if(placements)
720 printf("\n%d filters\n", num);
721 char*filtername[] = {"dropshadow","blur","glow","bevel","gradientglow","convolution","colormatrix","gradientbevel"};
722 int t;
723 for(t=0;t<num;t++) {
724 FILTER*filter = swf_GetFilter(tag);
725 if(!filter) {
726 printf("\n");
727 return;
729 if(placements) {
730 printf("filter %d: %02x (%s)\n", t, filter->type, (filter->type<sizeof(filtername)/sizeof(filtername[0]))?filtername[filter->type]:"?");
731 dumpFilter(filter);
735 if(flags2&2) { // blend mode
736 U8 blendmode = swf_GetU8(tag);
737 if(placements) {
738 int t;
739 char name[80];
740 sprintf(name, "%-5d", blendmode);
741 for(t=0;blendModeNames[t];t++) {
742 if(blendmode==t) {
743 sprintf(name, "%-5s", blendModeNames[t]);
744 break;
747 ppos[0] += sprintf(pstr[0]+ppos[0], "| Blend ");
748 ppos[1] += sprintf(pstr[1]+ppos[1], "| %s ", name);
749 ppos[2] += sprintf(pstr[2]+ppos[2], "| ");
753 if(placements && ppos[0]) {
754 printf("\n");
755 printf("%s %s\n", prefix, pstr[0]);
756 printf("%s %s\n", prefix, pstr[1]);
757 printf("%s %s", prefix, pstr[2]);
759 if(flags&128) {
760 if (action) {
761 U16 reserved;
762 U32 globalflags;
763 U32 handlerflags;
764 char is32 = 0;
765 printf("\n");
766 reserved = swf_GetU16(tag); // must be 0
767 globalflags = swf_GetU16(tag); //TODO: 32 if version>=6
768 if(reserved) {
769 printf("Unknown parameter field not zero: %04x\n", reserved);
770 return;
772 printf("global flags: %04x\n", globalflags);
774 handlerflags = swf_GetU16(tag); //TODO: 32 if version>=6
775 if(!handlerflags) {
776 handlerflags = swf_GetU32(tag);
777 is32 = 1;
779 while(handlerflags) {
780 int length;
781 int t;
782 ActionTAG*a;
784 globalflags &= ~handlerflags;
785 printf("%s flags %08x ",prefix, handlerflags);
786 printhandlerflags(handlerflags);
787 length = swf_GetU32(tag);
788 printf(", %d bytes actioncode\n",length);
789 a = swf_ActionGet(tag);
790 swf_DumpActions(a,prefix);
791 swf_ActionFree(a);
793 handlerflags = is32?swf_GetU32(tag):swf_GetU16(tag); //TODO: 32 if version>=6
795 if(globalflags) // should go to sterr.
796 printf("ERROR: unsatisfied handlerflags: %02x\n", globalflags);
797 } else {
798 printf(" has action code\n");
800 } else printf("\n");
803 void handlePlaceObject(TAG*tag, char*prefix)
805 TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
806 U16 id, depth;
807 MATRIX matrix;
808 CXFORM cxform;
810 swf_SetTagPos(tag, 0);
811 id = swf_GetU16(tag);
812 depth = swf_GetU16(tag);
813 swf_GetMatrix(tag, &matrix);
814 swf_GetCXForm(tag, &cxform, 0);
816 swf_SetU8(tag2, 14 /* char, matrix, cxform */);
817 swf_SetU16(tag2, depth);
818 swf_SetU16(tag2, id);
819 swf_SetMatrix(tag2, &matrix);
820 swf_SetCXForm(tag2, &cxform, 1);
822 handlePlaceObject23(tag2, prefix);
824 char stylebuf[256];
825 char* fillstyle2str(FILLSTYLE*style)
827 switch(style->type) {
828 case 0x00:
829 sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
830 break;
831 case 0x10: case 0x11: case 0x12: case 0x13:
832 sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
833 break;
834 case 0x40: case 0x42:
835 /* TODO: display information about that bitmap */
836 sprintf(stylebuf, "BITMAPt%s %d", (style->type&2)?"n":"", style->id_bitmap);
837 /* TODO: show matrix */
838 //swf_DumpMatrix(stdout, &style->m);
839 break;
840 case 0x41: case 0x43:
841 /* TODO: display information about that bitmap */
842 sprintf(stylebuf, "BITMAPc%s %d", (style->type&2)?"n":"", style->id_bitmap);
843 /* TODO: show matrix */
844 //swf_DumpMatrix(stdout, &style->m);
845 break;
846 default:
847 sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
849 return stylebuf;
851 char* linestyle2str(LINESTYLE*style)
853 sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
854 return stylebuf;
857 void handleShape(TAG*tag, char*prefix)
859 SHAPE2 shape;
860 SHAPELINE*line;
861 int t,max;
863 tag->pos = 0;
864 tag->readBit = 0;
865 swf_ParseDefineShape(tag, &shape);
867 max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
869 if(max) printf("%s | fillstyles(%02d) linestyles(%02d)\n",
870 prefix,
871 shape.numfillstyles,
872 shape.numlinestyles
874 else printf("%s | (Neither line nor fill styles)\n", prefix);
876 for(t=0;t<max;t++) {
877 printf("%s", prefix);
878 if(t < shape.numfillstyles) {
879 printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
880 } else {
881 printf(" ");
883 if(t < shape.numlinestyles) {
884 printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
886 printf("\n");
887 //if(shape.fillstyles[t].type&0x40) {
888 // MATRIX m = shape.fillstyles[t].m;
889 // swf_DumpMatrix(stdout, &m);
893 printf("%s |\n", prefix);
895 line = shape.lines;
896 while(line) {
897 printf("%s | fill: %02d/%02d line:%02d - ",
898 prefix,
899 line->fillstyle0,
900 line->fillstyle1,
901 line->linestyle);
902 if(line->type == moveTo) {
903 printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
904 } else if(line->type == lineTo) {
905 printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
906 } else if(line->type == splineTo) {
907 printf("splineTo (%.2f %.2f) %.2f %.2f\n",
908 line->sx/20.0, line->sy/20.0,
909 line->x/20.0, line->y/20.0
912 line = line->next;
914 printf("%s |\n", prefix);
917 void fontcallback1(void*self, U16 id,U8 * name)
918 { fontnum++;
921 void fontcallback2(void*self, U16 id,U8 * name)
923 swf_FontExtract(&swf,id,&fonts[fontnum]);
924 fontnum++;
927 static U8 printable(U8 a)
929 if(a<32 || a==127) return '.';
930 else return a;
932 void hexdumpTag(TAG*tag, char* prefix)
934 int t;
935 char ascii[32];
936 printf(" %s-=> ",prefix);
937 for(t=0;t<tag->len;t++) {
938 printf("%02x ", tag->data[t]);
939 ascii[t&15] = printable(tag->data[t]);
940 if((t && ((t&15)==15)) || (t==tag->len-1))
942 int s,p=((t)&15)+1;
943 ascii[p] = 0;
944 for(s=p-1;s<16;s++) {
945 printf(" ");
947 if(t==tag->len-1)
948 printf(" %s\n", ascii);
949 else
950 printf(" %s\n %s-=> ",ascii,prefix);
955 void handleImportAssets(TAG*tag, char* prefix, int assets2)
957 int num;
958 U16 id;
959 char* url, *name;
960 int t;
961 url = swf_GetString(tag);
962 printf("%sfrom %s\n", prefix, url);
963 if(assets2)
965 swf_GetU8(tag); // Reserved: Must be 1
966 swf_GetU8(tag); // Reserved: Must be 0
968 num = swf_GetU16(tag);
969 for(t=0;t<num;t++)
971 id = swf_GetU16(tag);
972 name = swf_GetString(tag);
973 printf("%s import %04d named \"%s\"\n", prefix, id, name);
977 void handleExportAssets(TAG*tag, char* prefix)
979 int num;
980 U16 id;
981 char* name;
982 int t;
983 num = swf_GetU16(tag);
984 for(t=0;t<num;t++)
986 id = swf_GetU16(tag);
987 name = swf_GetString(tag);
988 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
992 static void handleFontAlign1(TAG*tag)
994 swf_SetTagPos(tag, 0);
995 U16 id = swf_GetU16(tag);
996 U8 flags = swf_GetU8(tag);
997 printf(" for font %04d, ", id);
998 if((flags&3)==0) printf("thin, ");
999 else if((flags&3)==1) printf("medium, ");
1000 else if((flags&3)==2) printf("thick, ");
1001 else printf("?, ");
1002 int num=0;
1003 while(tag->pos < tag->len) {
1004 int nr = swf_GetU8(tag); // should be 2
1005 int t;
1006 if(nr>2) {
1007 printf("*** unsupported multiboxes ***, ");
1008 break;
1010 for(t=0;t<nr;t++) {
1011 float v1 = swf_GetF16(tag);
1012 float v2 = swf_GetF16(tag);
1014 U8 xyflags = swf_GetU8(tag);
1015 num++;
1017 printf(" %d glyphs", num);
1020 #define ALIGN_WITH_GLYPHS
1021 static void handleFontAlign2(TAG*tag, char*prefix)
1023 if(!showfonts)
1024 return;
1025 swf_SetTagPos(tag, 0);
1026 U16 id = swf_GetU16(tag);
1027 swf_GetU8(tag);
1028 int num = 0;
1029 #ifdef ALIGN_WITH_GLYPHS
1030 SWF swf;
1031 swf.firstTag = tag;
1032 while(swf.firstTag->prev) swf.firstTag = swf.firstTag->prev;
1033 SWFFONT* font = 0;
1034 swf_FontExtract(&swf, id, &font);
1035 #endif
1036 swf_SetTagPos(tag, 3);
1037 while(tag->pos < tag->len) {
1038 printf("%sglyph %d) ", prefix, num);
1039 int nr = swf_GetU8(tag); // should be 2
1040 int t;
1041 for(t=0;t<2;t++) {
1042 // pos
1043 float v = swf_GetF16(tag);
1044 printf("%f ", v*1024.0);
1046 int s;
1047 for(s=0;s<nr-1;s++) {
1048 for(t=0;t<2;t++) {
1049 // width
1050 float v = swf_GetF16(tag);
1051 printf("+%f ", v*1024.0);
1054 U8 xyflags = swf_GetU8(tag);
1055 printf("xy:%02x\n", xyflags);
1057 #ifdef ALIGN_WITH_GLYPHS
1058 if(font && num<font->numchars) {
1059 SHAPE2* shape = swf_ShapeToShape2(font->glyph[num].shape);
1060 SHAPELINE*line = shape->lines;
1061 while(line) {
1062 if(line->type == moveTo) {
1063 printf("%smoveTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
1064 } else if(line->type == lineTo) {
1065 printf("%slineTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
1066 } else if(line->type == splineTo) {
1067 printf("%ssplineTo (%.2f %.2f) %.2f %.2f\n", prefix,
1068 line->sx/20.0, line->sy/20.0,
1069 line->x/20.0, line->y/20.0
1072 line = line->next;
1074 swf_Shape2Free(shape);
1075 free(shape);
1077 if(num==font->numchars-1) break;
1078 #endif
1079 num++;
1084 void dumperror(const char* format, ...)
1086 char buf[1024];
1087 va_list arglist;
1089 va_start(arglist, format);
1090 vsnprintf(buf, sizeof(buf)-1, format, arglist);
1091 va_end(arglist);
1093 if(!html && !xy)
1094 printf("==== Error: %s ====\n", buf);
1097 static char strbuf[800];
1098 static int bufpos=0;
1100 char* timestring(double f)
1102 int hours = (int)(f/3600);
1103 int minutes = (int)((f-hours*3600)/60);
1104 int seconds = (int)((f-hours*3600-minutes*60));
1105 int useconds = (int)((f-(int)f)*1000+0.5);
1106 bufpos+=100;
1107 bufpos%=800;
1108 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
1109 return &strbuf[bufpos];
1112 int main (int argc,char ** argv)
1114 TAG*tag;
1115 #ifdef HAVE_STAT
1116 struct stat statbuf;
1117 #endif
1118 int f;
1119 int xsize,ysize;
1120 char issprite = 0; // are we inside a sprite definition?
1121 int spriteframe = 0;
1122 int mainframe=0;
1123 char* spriteframelabel = 0;
1124 char* framelabel = 0;
1125 char prefix[128];
1126 int filesize = 0;
1127 int filepos = 0;
1128 prefix[0] = 0;
1129 memset(idtab,0,65536);
1131 processargs(argc, argv);
1133 if(!filename)
1135 fprintf(stderr, "You must supply a filename.\n");
1136 return 1;
1139 f = open(filename,O_RDONLY|O_BINARY);
1140 if (f<0)
1142 char buffer[256];
1143 sprintf(buffer, "Couldn't open %.200s", filename);
1144 perror(buffer);
1145 exit(1);
1147 char header[3];
1148 read(f, header, 3);
1149 char compressed = (header[0]=='C');
1150 char isflash = (header[0]=='F' && header[1] == 'W' && header[2] == 'S') ||
1151 (header[0]=='C' && header[1] == 'W' && header[2] == 'S');
1152 close(f);
1154 int fl=strlen(filename);
1155 if(!isflash && fl>3 && !strcmp(&filename[fl-4], ".abc")) {
1156 swf_ReadABCfile(filename, &swf);
1157 } else {
1158 f = open(filename,O_RDONLY|O_BINARY);
1159 if FAILED(swf_ReadSWF(f,&swf))
1161 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
1162 close(f);
1163 exit(1);
1166 #ifdef HAVE_STAT
1167 fstat(f, &statbuf);
1168 if(statbuf.st_size != swf.fileSize && !compressed)
1169 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
1170 statbuf.st_size, swf.fileSize);
1171 filesize = statbuf.st_size;
1172 #endif
1173 close(f);
1176 //if(action && swf.fileVersion>=9) {
1177 // fprintf(stderr, "Actionscript parsing (-a) not yet supported for SWF versions>=9\n");
1178 // action = 0;
1181 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
1182 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
1183 if(xy)
1185 if(xy&1)
1186 printf("-X %d", xsize);
1188 if((xy&1) && (xy&6))
1189 printf(" ");
1191 if(xy&2)
1192 printf("-Y %d", ysize);
1194 if((xy&3) && (xy&4))
1195 printf(" ");
1197 if(xy&4)
1198 printf("-r %.2f", swf.frameRate/256.0);
1200 if((xy&7) && (xy&8))
1201 printf(" ");
1203 if(xy&8)
1204 printf("-f %d", swf.frameCount);
1206 printf("\n");
1207 return 0;
1209 if(html)
1211 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
1212 "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0","10,0,0,0", "11,0,0,0", "12,0,0,0"};
1213 if(swf.fileVersion>10) {
1214 fprintf(stderr, "Fileversion>10\n");
1215 exit(1);
1218 if(xhtml) {
1219 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
1220 "<param name=\"movie\" value=\"%s\"/>\n"
1221 "<param name=\"play\" value=\"true\"/>\n"
1222 "<param name=\"loop\" value=\"false\"/>\n"
1223 "<param name=\"quality\" value=\"high\"/>\n"
1224 "<param name=\"loop\" value=\"false\"/>\n"
1225 "</object>\n\n", filename, xsize, ysize, filename);
1226 } else {
1227 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
1228 " WIDTH=\"%d\"\n"
1229 //" BGCOLOR=#ffffffff\n"?
1230 " HEIGHT=\"%d\"\n"
1231 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
1232 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
1233 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
1234 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
1235 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
1236 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
1237 " <PARAM NAME=\"ALLOWSCRIPTACCESS\" VALUE=\"always\">\n"
1238 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
1239 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
1240 " TYPE=\"application/x-shockwave-flash\"\n"
1241 " ALLOWSCRIPTACCESS=\"always\"\n"
1242 " PLUGINSPAGE=\"http://get.adobe.com/flashplayer/\">\n"
1243 " </EMBED>\n"
1244 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
1245 filename, filename, xsize, ysize);
1247 return 0;
1249 printf("[HEADER] File version: %d\n", swf.fileVersion);
1250 if(compressed) {
1251 printf("[HEADER] File is zlib compressed.");
1252 if(filesize && swf.fileSize)
1253 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
1254 else
1255 printf("\n");
1257 printf("[HEADER] File size: %d%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
1258 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
1259 printf("[HEADER] Frame count: %d\n",swf.frameCount);
1260 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
1261 if(swf.movieSize.xmin)
1262 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
1263 else
1264 printf("\n");
1265 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
1266 if(swf.movieSize.ymin)
1267 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
1268 else
1269 printf("\n");
1271 tag = swf.firstTag;
1273 if(showtext) {
1274 fontnum = 0;
1275 swf_FontEnumerate(&swf,&fontcallback1, 0);
1276 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
1277 fontnum = 0;
1278 swf_FontEnumerate(&swf,&fontcallback2, 0);
1281 while(tag) {
1282 char*name = swf_TagGetName(tag);
1283 char myprefix[128];
1284 if(!name) {
1285 dumperror("Unknown tag:0x%03x", tag->id);
1286 //tag = tag->next;
1287 //continue;
1289 if(!name) {
1290 name = "UNKNOWN TAG";
1292 if(cumulative) {
1293 filepos += tag->len;
1294 printf("[%03x] %9d %9d %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
1295 } else {
1296 printf("[%03x] %9d %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
1299 if(tag->id == ST_PLACEOBJECT) {
1300 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
1301 if(swf_GetName(tag))
1302 printf(" name \"%s\"",swf_GetName(tag));
1304 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1305 if(tag->data[0]&1)
1306 printf(" moves");
1307 else
1308 printf(" places");
1310 if(tag->data[0]&2)
1311 printf(" id %04d",swf_GetPlaceID(tag));
1312 else
1313 printf(" object");
1315 printf(" at depth %04d", swf_GetDepth(tag));
1317 if(tag->id == ST_PLACEOBJECT3 && tag->data[1]&4)
1318 printf(" as bitmap");
1320 swf_SetTagPos(tag, 0);
1321 if(tag->data[0]&64) {
1322 SWFPLACEOBJECT po;
1323 swf_GetPlaceObject(tag, &po);
1324 printf(" (clip to %04d)", po.clipdepth);
1325 swf_PlaceObjectFree(&po);
1327 if(swf_GetName(tag))
1328 printf(" name \"%s\"",swf_GetName(tag));
1331 else if(tag->id == ST_REMOVEOBJECT) {
1332 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
1334 else if(tag->id == ST_REMOVEOBJECT2) {
1335 printf(" removes object from depth %04d", swf_GetDepth(tag));
1337 else if(tag->id == ST_FREECHARACTER) {
1338 printf(" frees object %04d", swf_GetPlaceID(tag));
1340 else if(tag->id == ST_FILEATTRIBUTES) {
1341 swf_SetTagPos(tag, 0);
1342 U32 flags = swf_GetU32(tag);
1343 if(flags&FILEATTRIBUTE_USENETWORK) printf(" usenetwork");
1344 if(flags&FILEATTRIBUTE_AS3) printf(" as3");
1345 if(flags&FILEATTRIBUTE_SYMBOLCLASS) printf(" symbolclass");
1346 if(flags&FILEATTRIBUTE_USEHARDWAREGPU) printf(" hardware-gpu");
1347 if(flags&FILEATTRIBUTE_USEACCELERATEDBLIT) printf(" accelerated-blit");
1348 if(flags&~(1|8|16|32|64))
1349 printf(" flags=%02x", flags);
1351 else if(tag->id == ST_DOABC) {
1352 swf_SetTagPos(tag, 0);
1353 U32 flags = swf_GetU32(tag);
1354 char*s = swf_GetString(tag);
1355 if(flags&~1) {
1356 printf(" flags=%08x", flags);
1358 if(*s) {
1359 printf(" \"%s\"", s);
1361 if(flags&1) {
1362 if(name)
1363 printf(",");
1364 printf(" lazy load");
1366 swf_SetTagPos(tag, 0);
1368 else if(tag->id == ST_STARTSOUND) {
1369 U8 flags;
1370 U16 id;
1371 id = swf_GetU16(tag);
1372 flags = swf_GetU8(tag);
1373 if(flags & 32)
1374 printf(" stops sound with id %04d", id);
1375 else
1376 printf(" starts sound with id %04d", id);
1377 if(flags & 16)
1378 printf(" (if not already playing)");
1379 if(flags & 1)
1380 swf_GetU32(tag);
1381 if(flags & 2)
1382 swf_GetU32(tag);
1383 if(flags & 4) {
1384 printf(" looping %d times", swf_GetU16(tag));
1387 else if(tag->id == ST_FRAMELABEL) {
1388 int l = strlen((char*)tag->data);
1389 printf(" \"%s\"", tag->data);
1390 if((l+1) < tag->len) {
1391 printf(" has %d extra bytes", tag->len-1-l);
1392 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1393 printf(" (ANCHOR)");
1395 if((framelabel && !issprite) ||
1396 (spriteframelabel && issprite)) {
1397 dumperror("Frame %d has more than one label",
1398 issprite?spriteframe:mainframe);
1400 if(issprite) spriteframelabel = (char*)tag->data;
1401 else framelabel = (char*)tag->data;
1403 else if(tag->id == ST_SHOWFRAME) {
1404 char*label = issprite?spriteframelabel:framelabel;
1405 int frame = issprite?spriteframe:mainframe;
1406 int nframe = frame;
1407 if(!label) {
1408 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1409 tag = tag->next;
1410 if(issprite) spriteframe++;
1411 else mainframe++;
1412 nframe++;
1415 if(nframe == frame)
1416 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1417 else
1418 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1419 timestring(frame*(256.0/(swf.frameRate+0.1))),
1420 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1422 if(label)
1423 printf(" (label \"%s\")", label);
1424 if(issprite) {spriteframe++; spriteframelabel = 0;}
1425 if(!issprite) {mainframe++; framelabel = 0;}
1427 else if(tag->id == ST_SETBACKGROUNDCOLOR) {
1428 U8 r = swf_GetU8(tag);
1429 U8 g = swf_GetU8(tag);
1430 U8 b = swf_GetU8(tag);
1431 printf(" (%02x/%02x/%02x)",r,g,b);
1433 else if(tag->id == ST_PROTECT) {
1434 if(tag->len>0) {
1435 printf(" %s", swf_GetString(tag));
1438 else if(tag->id == ST_DEFINEFONTALIGNZONES) {
1439 handleFontAlign1(tag);
1441 else if(tag->id == ST_CSMTEXTSETTINGS) {
1442 U16 id = swf_GetU16(tag);
1443 U8 flags = swf_GetU8(tag);
1444 printf(" (");
1445 if(flags&0x40) {
1446 printf("flashtype,");
1448 switch(((flags>>3)&7)) {
1449 case 0:printf("no grid,");break;
1450 case 1:printf("pixel grid,");break;
1451 case 2:printf("subpixel grid,");break;
1452 case 3:printf("unknown grid,");break;
1454 if(flags&0x87)
1455 printf("unknown[%08x],", flags);
1456 float thickness = swf_GetFixed(tag);
1457 float sharpness = swf_GetFixed(tag);
1458 printf("s=%.2f,t=%.2f)", thickness, sharpness);
1459 swf_GetU8(tag);
1461 else if(swf_isDefiningTag(tag)) {
1462 U16 id = swf_GetDefineID(tag);
1463 printf(" defines id %04d", id);
1464 if(idtab[id])
1465 dumperror("Id %04d is defined more than once.", id);
1466 idtab[id] = 1;
1468 else if(swf_isPseudoDefiningTag(tag)) {
1469 U16 id = swf_GetDefineID(tag);
1470 printf(" adds information to id %04d", id);
1471 if(!idtab[id])
1472 dumperror("Id %04d is not yet defined.\n", id);
1475 if(tag->id == ST_DEFINEBITSLOSSLESS ||
1476 tag->id == ST_DEFINEBITSLOSSLESS2) {
1477 handleDefineBits(tag);
1478 printf("\n");
1480 else if(tag->id == ST_DEFINESOUND) {
1481 handleDefineSound(tag);
1482 printf("\n");
1484 else if(tag->id == ST_VIDEOFRAME) {
1485 handleVideoFrame(tag, myprefix);
1486 printf("\n");
1488 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1489 handleVideoStream(tag, myprefix);
1490 printf("\n");
1492 else if(tag->id == ST_DEFINEEDITTEXT) {
1493 handleEditText(tag);
1494 printf("\n");
1496 else if(tag->id == ST_DEFINEMOVIE) {
1497 U16 id = swf_GetU16(tag);
1498 char*s = swf_GetString(tag);
1499 printf(" URL: %s\n", s);
1501 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1502 handleText(tag, myprefix);
1504 else if(tag->id == ST_DEFINESCALINGGRID) {
1505 U16 id = swf_GetU16(tag);
1506 SRECT r;
1507 swf_GetRect(tag, &r);
1508 printf(" (%.2f,%.2f)-(%.2f,%.2f)\n", r.xmin/20.0, r.ymin/20.0, r.xmax/20.0, r.ymax/20.0);
1510 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1512 else if(tag->id == ST_NAMECHARACTER || tag->id==ST_DEFINEFONTNAME) {
1513 swf_GetU16(tag);
1514 printf(" \"%s\"\n", swf_GetString(tag));
1516 else {
1517 printf("\n");
1520 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1521 SRECT r = swf_GetDefineBBox(tag);
1522 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1523 r.xmin/20.0,
1524 r.ymin/20.0,
1525 r.xmax/20.0,
1526 r.ymax/20.0);
1529 sprintf(myprefix, " %s", prefix);
1531 if(tag->id == ST_DEFINESPRITE) {
1532 sprintf(prefix, " ");
1533 if(issprite) {
1534 dumperror("Sprite definition inside a sprite definition");
1536 issprite = 1;
1537 spriteframe = 0;
1538 spriteframelabel = 0;
1540 else if(tag->id == ST_END) {
1541 *prefix = 0;
1542 issprite = 0;
1543 spriteframelabel = 0;
1544 if(tag->len)
1545 dumperror("End Tag not empty");
1547 else if(tag->id == ST_IMPORTASSETS || tag->id == ST_IMPORTASSETS2) {
1548 handleImportAssets(tag, myprefix, tag->id==ST_IMPORTASSETS2?1:0);
1550 else if(tag->id == ST_EXPORTASSETS || tag->id == ST_SYMBOLCLASS) {
1551 handleExportAssets(tag, myprefix);
1553 else if(tag->id == ST_DOACTION && action) {
1554 ActionTAG*actions;
1555 actions = swf_ActionGet(tag);
1556 swf_DumpActions(actions, myprefix);
1558 else if((tag->id == ST_DOABC || tag->id == ST_RAWABC) && action) {
1559 void*abccode = swf_ReadABC(tag);
1560 swf_DumpABC(stdout, abccode, "");
1561 swf_FreeABC(abccode);
1563 else if(tag->id == ST_DOINITACTION && action) {
1564 ActionTAG*actions;
1565 swf_GetU16(tag); // id
1566 actions = swf_ActionGet(tag);
1567 swf_DumpActions(actions, myprefix);
1569 else if(tag->id == ST_DEFINEBUTTON) {
1570 if(showbuttons) {
1571 dumpButton(tag, myprefix);
1573 if(action) {
1574 dumpButtonActions(tag, myprefix);
1577 else if(swf_isFontTag(tag) && showfonts) {
1578 dumpFont(tag, myprefix);
1580 else if(tag->id == ST_DEFINEBUTTON2) {
1581 if(action) {
1582 dumpButton2Actions(tag, myprefix);
1585 else if(tag->id == ST_PLACEOBJECT) {
1586 handlePlaceObject(tag, myprefix);
1588 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1589 handlePlaceObject23(tag, myprefix);
1591 else if(tag->id == ST_DEFINEFONTALIGNZONES) {
1592 handleFontAlign2(tag, myprefix);
1594 else if(tag->id == ST_DEFINEFONTNAME) {
1595 swf_SetTagPos(tag, 0);
1596 swf_GetU16(tag); //id
1597 swf_GetString(tag); //name
1598 char* copyright = swf_GetString(tag);
1599 printf("%s%s\n", myprefix, copyright);
1601 else if(tag->id == ST_DEFINESHAPE ||
1602 tag->id == ST_DEFINESHAPE2 ||
1603 tag->id == ST_DEFINESHAPE3 ||
1604 tag->id == ST_DEFINESHAPE4) {
1605 if(showshapes)
1606 handleShape(tag, myprefix);
1609 if(tag->len && used) {
1610 int num = swf_GetNumUsedIDs(tag);
1611 int* used;
1612 int t;
1613 if(num) {
1614 used = (int*)malloc(sizeof(int)*num);
1615 swf_GetUsedIDs(tag, used);
1616 printf("%s%suses IDs: ", indent, prefix);
1617 for(t=0;t<num;t++) {
1618 int id;
1619 swf_SetTagPos(tag, used[t]);
1620 id = swf_GetU16(tag);
1621 printf("%d%s", id, t<num-1?", ":"");
1622 if(!idtab[id]) {
1623 dumperror("Id %04d is not yet defined.\n", id);
1626 printf("\n");
1630 if(tag->id == ST_FREECHARACTER) {
1631 U16 id;
1632 swf_SetTagPos(tag, 0);
1633 id = swf_GetU16(tag);
1634 idtab[id] = 0;
1637 if(tag->len && hex) {
1638 hexdumpTag(tag, prefix);
1640 tag = tag->next;
1641 fflush(stdout);
1644 swf_FreeTags(&swf);
1645 return 0;