fixed pointer arithmetric bug
[swftools.git] / src / swfdump.c
blob0828ea45b2de542e1b0f4c340917af81db545e57
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 handleExportAssets(TAG*tag, char* prefix)
957 int num;
958 U16 id;
959 char* name;
960 int t;
961 num = swf_GetU16(tag);
962 for(t=0;t<num;t++)
964 id = swf_GetU16(tag);
965 name = swf_GetString(tag);
966 printf("%sexports %04d as \"%s\"\n", prefix, id, name);
970 static void handleFontAlign1(TAG*tag)
972 swf_SetTagPos(tag, 0);
973 U16 id = swf_GetU16(tag);
974 U8 flags = swf_GetU8(tag);
975 printf(" for font %04d, ", id);
976 if((flags&3)==0) printf("thin, ");
977 else if((flags&3)==1) printf("medium, ");
978 else if((flags&3)==2) printf("thick, ");
979 else printf("?, ");
980 int num=0;
981 while(tag->pos < tag->len) {
982 int nr = swf_GetU8(tag); // should be 2
983 int t;
984 if(nr>2) {
985 printf("*** unsupported multiboxes ***, ");
986 break;
988 for(t=0;t<nr;t++) {
989 float v1 = swf_GetF16(tag);
990 float v2 = swf_GetF16(tag);
992 U8 xyflags = swf_GetU8(tag);
993 num++;
995 printf(" %d glyphs", num);
998 #define ALIGN_WITH_GLYPHS
999 static void handleFontAlign2(TAG*tag, char*prefix)
1001 if(!showfonts)
1002 return;
1003 swf_SetTagPos(tag, 0);
1004 U16 id = swf_GetU16(tag);
1005 swf_GetU8(tag);
1006 int num = 0;
1007 #ifdef ALIGN_WITH_GLYPHS
1008 SWF swf;
1009 swf.firstTag = tag;
1010 while(swf.firstTag->prev) swf.firstTag = swf.firstTag->prev;
1011 SWFFONT* font = 0;
1012 swf_FontExtract(&swf, id, &font);
1013 #endif
1014 swf_SetTagPos(tag, 3);
1015 while(tag->pos < tag->len) {
1016 printf("%sglyph %d) ", prefix, num);
1017 int nr = swf_GetU8(tag); // should be 2
1018 int t;
1019 for(t=0;t<2;t++) {
1020 // pos
1021 float v = swf_GetF16(tag);
1022 printf("%f ", v*1024.0);
1024 int s;
1025 for(s=0;s<nr-1;s++) {
1026 for(t=0;t<2;t++) {
1027 // width
1028 float v = swf_GetF16(tag);
1029 printf("+%f ", v*1024.0);
1032 U8 xyflags = swf_GetU8(tag);
1033 printf("xy:%02x\n", xyflags);
1035 #ifdef ALIGN_WITH_GLYPHS
1036 if(font && num<font->numchars) {
1037 SHAPE2* shape = swf_ShapeToShape2(font->glyph[num].shape);
1038 SHAPELINE*line = shape->lines;
1039 while(line) {
1040 if(line->type == moveTo) {
1041 printf("%smoveTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
1042 } else if(line->type == lineTo) {
1043 printf("%slineTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
1044 } else if(line->type == splineTo) {
1045 printf("%ssplineTo (%.2f %.2f) %.2f %.2f\n", prefix,
1046 line->sx/20.0, line->sy/20.0,
1047 line->x/20.0, line->y/20.0
1050 line = line->next;
1052 swf_Shape2Free(shape);
1053 free(shape);
1055 if(num==font->numchars-1) break;
1056 #endif
1057 num++;
1062 void dumperror(const char* format, ...)
1064 char buf[1024];
1065 va_list arglist;
1067 va_start(arglist, format);
1068 vsnprintf(buf, sizeof(buf)-1, format, arglist);
1069 va_end(arglist);
1071 if(!html && !xy)
1072 printf("==== Error: %s ====\n", buf);
1075 static char strbuf[800];
1076 static int bufpos=0;
1078 char* timestring(double f)
1080 int hours = (int)(f/3600);
1081 int minutes = (int)((f-hours*3600)/60);
1082 int seconds = (int)((f-hours*3600-minutes*60));
1083 int useconds = (int)((f-(int)f)*1000+0.5);
1084 bufpos+=100;
1085 bufpos%=800;
1086 sprintf(&strbuf[bufpos], "%02d:%02d:%02d,%03d",hours,minutes,seconds,useconds);
1087 return &strbuf[bufpos];
1090 int main (int argc,char ** argv)
1092 TAG*tag;
1093 #ifdef HAVE_STAT
1094 struct stat statbuf;
1095 #endif
1096 int f;
1097 int xsize,ysize;
1098 char issprite = 0; // are we inside a sprite definition?
1099 int spriteframe = 0;
1100 int mainframe=0;
1101 char* spriteframelabel = 0;
1102 char* framelabel = 0;
1103 char prefix[128];
1104 int filesize = 0;
1105 int filepos = 0;
1106 prefix[0] = 0;
1107 memset(idtab,0,65536);
1109 processargs(argc, argv);
1111 if(!filename)
1113 fprintf(stderr, "You must supply a filename.\n");
1114 return 1;
1117 f = open(filename,O_RDONLY|O_BINARY);
1118 if (f<0)
1120 char buffer[256];
1121 sprintf(buffer, "Couldn't open %.200s", filename);
1122 perror(buffer);
1123 exit(1);
1125 char header[3];
1126 read(f, header, 3);
1127 char compressed = (header[0]=='C');
1128 char isflash = (header[0]=='F' && header[1] == 'W' && header[2] == 'S') ||
1129 (header[0]=='C' && header[1] == 'W' && header[2] == 'S');
1130 close(f);
1132 int fl=strlen(filename);
1133 if(!isflash && fl>3 && !strcmp(&filename[fl-4], ".abc")) {
1134 swf_ReadABCfile(filename, &swf);
1135 } else {
1136 f = open(filename,O_RDONLY|O_BINARY);
1137 if FAILED(swf_ReadSWF(f,&swf))
1139 fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
1140 close(f);
1141 exit(1);
1144 #ifdef HAVE_STAT
1145 fstat(f, &statbuf);
1146 if(statbuf.st_size != swf.fileSize && !compressed)
1147 dumperror("Real Filesize (%d) doesn't match header Filesize (%d)",
1148 statbuf.st_size, swf.fileSize);
1149 filesize = statbuf.st_size;
1150 #endif
1151 close(f);
1154 //if(action && swf.fileVersion>=9) {
1155 // fprintf(stderr, "Actionscript parsing (-a) not yet supported for SWF versions>=9\n");
1156 // action = 0;
1159 xsize = (swf.movieSize.xmax-swf.movieSize.xmin)/20;
1160 ysize = (swf.movieSize.ymax-swf.movieSize.ymin)/20;
1161 if(xy)
1163 if(xy&1)
1164 printf("-X %d", xsize);
1166 if((xy&1) && (xy&6))
1167 printf(" ");
1169 if(xy&2)
1170 printf("-Y %d", ysize);
1172 if((xy&3) && (xy&4))
1173 printf(" ");
1175 if(xy&4)
1176 printf("-r %.2f", swf.frameRate/256.0);
1178 if((xy&7) && (xy&8))
1179 printf(" ");
1181 if(xy&8)
1182 printf("-f %d", swf.frameCount);
1184 printf("\n");
1185 return 0;
1187 if(html)
1189 char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
1190 "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"};
1191 if(swf.fileVersion>10) {
1192 fprintf(stderr, "Fileversion>10\n");
1193 exit(1);
1196 if(xhtml) {
1197 printf("<object type=\"application/x-shockwave-flash\" data=\"%s\" width=\"%d\" height=\"%d\">\n"
1198 "<param name=\"movie\" value=\"%s\"/>\n"
1199 "<param name=\"play\" value=\"true\"/>\n"
1200 "<param name=\"loop\" value=\"false\"/>\n"
1201 "<param name=\"quality\" value=\"high\"/>\n"
1202 "<param name=\"loop\" value=\"false\"/>\n"
1203 "</object>\n\n", filename, xsize, ysize, filename);
1204 } else {
1205 printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
1206 " WIDTH=\"%d\"\n"
1207 //" BGCOLOR=#ffffffff\n"?
1208 " HEIGHT=\"%d\"\n"
1209 //http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,23,0?
1210 " CODEBASE=\"http://active.macromedia.com/flash5/cabs/swflash.cab#version=%s\">\n"
1211 " <PARAM NAME=\"MOVIE\" VALUE=\"%s\">\n"
1212 " <PARAM NAME=\"PLAY\" VALUE=\"true\">\n"
1213 " <PARAM NAME=\"LOOP\" VALUE=\"true\">\n"
1214 " <PARAM NAME=\"QUALITY\" VALUE=\"high\">\n"
1215 " <PARAM NAME=\"ALLOWSCRIPTACCESS\" VALUE=\"always\">\n"
1216 " <EMBED SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\"\n" //bgcolor=#ffffff?
1217 " PLAY=\"true\" ALIGN=\"\" LOOP=\"true\" QUALITY=\"high\"\n"
1218 " TYPE=\"application/x-shockwave-flash\"\n"
1219 " ALLOWSCRIPTACCESS=\"always\"\n"
1220 " PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">\n"
1221 " </EMBED>\n"
1222 "</OBJECT>\n", xsize, ysize, fileversions[swf.fileVersion],
1223 filename, filename, xsize, ysize);
1225 return 0;
1227 printf("[HEADER] File version: %d\n", swf.fileVersion);
1228 if(compressed) {
1229 printf("[HEADER] File is zlib compressed.");
1230 if(filesize && swf.fileSize)
1231 printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
1232 else
1233 printf("\n");
1235 printf("[HEADER] File size: %d%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
1236 printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0);
1237 printf("[HEADER] Frame count: %d\n",swf.frameCount);
1238 printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
1239 if(swf.movieSize.xmin)
1240 printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
1241 else
1242 printf("\n");
1243 printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
1244 if(swf.movieSize.ymin)
1245 printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
1246 else
1247 printf("\n");
1249 tag = swf.firstTag;
1251 if(showtext) {
1252 fontnum = 0;
1253 swf_FontEnumerate(&swf,&fontcallback1, 0);
1254 fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
1255 fontnum = 0;
1256 swf_FontEnumerate(&swf,&fontcallback2, 0);
1259 while(tag) {
1260 char*name = swf_TagGetName(tag);
1261 char myprefix[128];
1262 if(!name) {
1263 dumperror("Unknown tag:0x%03x", tag->id);
1264 //tag = tag->next;
1265 //continue;
1267 if(!name) {
1268 name = "UNKNOWN TAG";
1270 if(cumulative) {
1271 filepos += tag->len;
1272 printf("[%03x] %9d %9d %s%s", tag->id, tag->len, filepos, prefix, swf_TagGetName(tag));
1273 } else {
1274 printf("[%03x] %9d %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
1277 if(tag->id == ST_PLACEOBJECT) {
1278 printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
1279 if(swf_GetName(tag))
1280 printf(" name \"%s\"",swf_GetName(tag));
1282 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1283 if(tag->data[0]&1)
1284 printf(" moves");
1285 else
1286 printf(" places");
1288 if(tag->data[0]&2)
1289 printf(" id %04d",swf_GetPlaceID(tag));
1290 else
1291 printf(" object");
1293 printf(" at depth %04d", swf_GetDepth(tag));
1295 if(tag->id == ST_PLACEOBJECT3 && tag->data[1]&4)
1296 printf(" as bitmap");
1298 swf_SetTagPos(tag, 0);
1299 if(tag->data[0]&64) {
1300 SWFPLACEOBJECT po;
1301 swf_GetPlaceObject(tag, &po);
1302 printf(" (clip to %04d)", po.clipdepth);
1303 swf_PlaceObjectFree(&po);
1305 if(swf_GetName(tag))
1306 printf(" name \"%s\"",swf_GetName(tag));
1309 else if(tag->id == ST_REMOVEOBJECT) {
1310 printf(" removes id %04d from depth %04d", swf_GetPlaceID(tag), swf_GetDepth(tag));
1312 else if(tag->id == ST_REMOVEOBJECT2) {
1313 printf(" removes object from depth %04d", swf_GetDepth(tag));
1315 else if(tag->id == ST_FREECHARACTER) {
1316 printf(" frees object %04d", swf_GetPlaceID(tag));
1318 else if(tag->id == ST_FILEATTRIBUTES) {
1319 swf_SetTagPos(tag, 0);
1320 U32 flags = swf_GetU32(tag);
1321 if(flags&FILEATTRIBUTE_USENETWORK) printf(" usenetwork");
1322 if(flags&FILEATTRIBUTE_AS3) printf(" as3");
1323 if(flags&FILEATTRIBUTE_SYMBOLCLASS) printf(" symbolclass");
1324 if(flags&FILEATTRIBUTE_USEHARDWAREGPU) printf(" hardware-gpu");
1325 if(flags&FILEATTRIBUTE_USEACCELERATEDBLIT) printf(" accelerated-blit");
1326 if(flags&~(1|8|16|32|64))
1327 printf(" flags=%02x", flags);
1329 else if(tag->id == ST_DOABC) {
1330 swf_SetTagPos(tag, 0);
1331 U32 flags = swf_GetU32(tag);
1332 char*s = swf_GetString(tag);
1333 if(flags&~1) {
1334 printf(" flags=%08x", flags);
1336 if(*s) {
1337 printf(" \"%s\"", s);
1339 if(flags&1) {
1340 if(name)
1341 printf(",");
1342 printf(" lazy load");
1344 swf_SetTagPos(tag, 0);
1346 else if(tag->id == ST_STARTSOUND) {
1347 U8 flags;
1348 U16 id;
1349 id = swf_GetU16(tag);
1350 flags = swf_GetU8(tag);
1351 if(flags & 32)
1352 printf(" stops sound with id %04d", id);
1353 else
1354 printf(" starts sound with id %04d", id);
1355 if(flags & 16)
1356 printf(" (if not already playing)");
1357 if(flags & 1)
1358 swf_GetU32(tag);
1359 if(flags & 2)
1360 swf_GetU32(tag);
1361 if(flags & 4) {
1362 printf(" looping %d times", swf_GetU16(tag));
1365 else if(tag->id == ST_FRAMELABEL) {
1366 int l = strlen((char*)tag->data);
1367 printf(" \"%s\"", tag->data);
1368 if((l+1) < tag->len) {
1369 printf(" has %d extra bytes", tag->len-1-l);
1370 if(tag ->len - (l+1) == 1 && tag->data[tag->len-1] == 1)
1371 printf(" (ANCHOR)");
1373 if((framelabel && !issprite) ||
1374 (spriteframelabel && issprite)) {
1375 dumperror("Frame %d has more than one label",
1376 issprite?spriteframe:mainframe);
1378 if(issprite) spriteframelabel = (char*)tag->data;
1379 else framelabel = (char*)tag->data;
1381 else if(tag->id == ST_SHOWFRAME) {
1382 char*label = issprite?spriteframelabel:framelabel;
1383 int frame = issprite?spriteframe:mainframe;
1384 int nframe = frame;
1385 if(!label) {
1386 while(tag->next && tag->next->id == ST_SHOWFRAME && tag->next->len == 0) {
1387 tag = tag->next;
1388 if(issprite) spriteframe++;
1389 else mainframe++;
1390 nframe++;
1393 if(nframe == frame)
1394 printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
1395 else
1396 printf(" %d-%d (%s-%s)", frame+1, nframe+1,
1397 timestring(frame*(256.0/(swf.frameRate+0.1))),
1398 timestring(nframe*(256.0/(swf.frameRate+0.1)))
1400 if(label)
1401 printf(" (label \"%s\")", label);
1402 if(issprite) {spriteframe++; spriteframelabel = 0;}
1403 if(!issprite) {mainframe++; framelabel = 0;}
1405 else if(tag->id == ST_SETBACKGROUNDCOLOR) {
1406 U8 r = swf_GetU8(tag);
1407 U8 g = swf_GetU8(tag);
1408 U8 b = swf_GetU8(tag);
1409 printf(" (%02x/%02x/%02x)",r,g,b);
1411 else if(tag->id == ST_PROTECT) {
1412 if(tag->len>0) {
1413 printf(" %s", swf_GetString(tag));
1416 else if(tag->id == ST_DEFINEFONTALIGNZONES) {
1417 handleFontAlign1(tag);
1419 else if(tag->id == ST_CSMTEXTSETTINGS) {
1420 U16 id = swf_GetU16(tag);
1421 U8 flags = swf_GetU8(tag);
1422 printf(" (");
1423 if(flags&0x40) {
1424 printf("flashtype,");
1426 switch(((flags>>3)&7)) {
1427 case 0:printf("no grid,");break;
1428 case 1:printf("pixel grid,");break;
1429 case 2:printf("subpixel grid,");break;
1430 case 3:printf("unknown grid,");break;
1432 if(flags&0x87)
1433 printf("unknown[%08x],", flags);
1434 float thickness = swf_GetFixed(tag);
1435 float sharpness = swf_GetFixed(tag);
1436 printf("s=%.2f,t=%.2f)", thickness, sharpness);
1437 swf_GetU8(tag);
1439 else if(swf_isDefiningTag(tag)) {
1440 U16 id = swf_GetDefineID(tag);
1441 printf(" defines id %04d", id);
1442 if(idtab[id])
1443 dumperror("Id %04d is defined more than once.", id);
1444 idtab[id] = 1;
1446 else if(swf_isPseudoDefiningTag(tag)) {
1447 U16 id = swf_GetDefineID(tag);
1448 printf(" adds information to id %04d", id);
1449 if(!idtab[id])
1450 dumperror("Id %04d is not yet defined.\n", id);
1453 if(tag->id == ST_DEFINEBITSLOSSLESS ||
1454 tag->id == ST_DEFINEBITSLOSSLESS2) {
1455 handleDefineBits(tag);
1456 printf("\n");
1458 else if(tag->id == ST_DEFINESOUND) {
1459 handleDefineSound(tag);
1460 printf("\n");
1462 else if(tag->id == ST_VIDEOFRAME) {
1463 handleVideoFrame(tag, myprefix);
1464 printf("\n");
1466 else if(tag->id == ST_DEFINEVIDEOSTREAM) {
1467 handleVideoStream(tag, myprefix);
1468 printf("\n");
1470 else if(tag->id == ST_DEFINEEDITTEXT) {
1471 handleEditText(tag);
1472 printf("\n");
1474 else if(tag->id == ST_DEFINEMOVIE) {
1475 U16 id = swf_GetU16(tag);
1476 char*s = swf_GetString(tag);
1477 printf(" URL: %s\n", s);
1479 else if(tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) {
1480 handleText(tag, myprefix);
1482 else if(tag->id == ST_DEFINESCALINGGRID) {
1483 U16 id = swf_GetU16(tag);
1484 SRECT r;
1485 swf_GetRect(tag, &r);
1486 printf(" (%.2f,%.2f)-(%.2f,%.2f)\n", r.xmin/20.0, r.ymin/20.0, r.xmax/20.0, r.ymax/20.0);
1488 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1490 else if(tag->id == ST_NAMECHARACTER || tag->id==ST_DEFINEFONTNAME) {
1491 swf_GetU16(tag);
1492 printf(" \"%s\"\n", swf_GetString(tag));
1494 else {
1495 printf("\n");
1498 if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
1499 SRECT r = swf_GetDefineBBox(tag);
1500 printf(" %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
1501 r.xmin/20.0,
1502 r.ymin/20.0,
1503 r.xmax/20.0,
1504 r.ymax/20.0);
1507 sprintf(myprefix, " %s", prefix);
1509 if(tag->id == ST_DEFINESPRITE) {
1510 sprintf(prefix, " ");
1511 if(issprite) {
1512 dumperror("Sprite definition inside a sprite definition");
1514 issprite = 1;
1515 spriteframe = 0;
1516 spriteframelabel = 0;
1518 else if(tag->id == ST_END) {
1519 *prefix = 0;
1520 issprite = 0;
1521 spriteframelabel = 0;
1522 if(tag->len)
1523 dumperror("End Tag not empty");
1525 else if(tag->id == ST_EXPORTASSETS || tag->id == ST_SYMBOLCLASS) {
1526 handleExportAssets(tag, myprefix);
1528 else if(tag->id == ST_DOACTION && action) {
1529 ActionTAG*actions;
1530 actions = swf_ActionGet(tag);
1531 swf_DumpActions(actions, myprefix);
1533 else if((tag->id == ST_DOABC || tag->id == ST_RAWABC) && action) {
1534 void*abccode = swf_ReadABC(tag);
1535 swf_DumpABC(stdout, abccode, "");
1536 swf_FreeABC(abccode);
1538 else if(tag->id == ST_DOINITACTION && action) {
1539 ActionTAG*actions;
1540 swf_GetU16(tag); // id
1541 actions = swf_ActionGet(tag);
1542 swf_DumpActions(actions, myprefix);
1544 else if(tag->id == ST_DEFINEBUTTON) {
1545 if(showbuttons) {
1546 dumpButton(tag, myprefix);
1548 if(action) {
1549 dumpButtonActions(tag, myprefix);
1552 else if(swf_isFontTag(tag) && showfonts) {
1553 dumpFont(tag, myprefix);
1555 else if(tag->id == ST_DEFINEBUTTON2) {
1556 if(action) {
1557 dumpButton2Actions(tag, myprefix);
1560 else if(tag->id == ST_PLACEOBJECT) {
1561 handlePlaceObject(tag, myprefix);
1563 else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
1564 handlePlaceObject23(tag, myprefix);
1566 else if(tag->id == ST_DEFINEFONTALIGNZONES) {
1567 handleFontAlign2(tag, myprefix);
1569 else if(tag->id == ST_DEFINEFONTNAME) {
1570 swf_SetTagPos(tag, 0);
1571 swf_GetU16(tag); //id
1572 swf_GetString(tag); //name
1573 char* copyright = swf_GetString(tag);
1574 printf("%s%s\n", myprefix, copyright);
1576 else if(tag->id == ST_DEFINESHAPE ||
1577 tag->id == ST_DEFINESHAPE2 ||
1578 tag->id == ST_DEFINESHAPE3 ||
1579 tag->id == ST_DEFINESHAPE4) {
1580 if(showshapes)
1581 handleShape(tag, myprefix);
1584 if(tag->len && used) {
1585 int num = swf_GetNumUsedIDs(tag);
1586 int* used;
1587 int t;
1588 if(num) {
1589 used = (int*)malloc(sizeof(int)*num);
1590 swf_GetUsedIDs(tag, used);
1591 printf("%s%suses IDs: ", indent, prefix);
1592 for(t=0;t<num;t++) {
1593 int id;
1594 swf_SetTagPos(tag, used[t]);
1595 id = swf_GetU16(tag);
1596 printf("%d%s", id, t<num-1?", ":"");
1597 if(!idtab[id]) {
1598 dumperror("Id %04d is not yet defined.\n", id);
1601 printf("\n");
1605 if(tag->id == ST_FREECHARACTER) {
1606 U16 id;
1607 swf_SetTagPos(tag, 0);
1608 id = swf_GetU16(tag);
1609 idtab[id] = 0;
1612 if(tag->len && hex) {
1613 hexdumpTag(tag, prefix);
1615 tag = tag->next;
1616 fflush(stdout);
1619 swf_FreeTags(&swf);
1620 return 0;