1 /****************************************************************************
2 *
3 * Copyright (C) 2006,2007 A.Kleine
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 ****************************************************************************/
20
21 #define _GNU_SOURCE 1
22
23 #define DEBUGSTACK
24 #define DECOMP_SWITCH
25 // #define DEBUGSWITCH
26
27 //#define STATEMENT_CLASS
28 // I have uncommented some buggy class recognition stuff in decompileIF()
29 // to make work simple code lines like: "if(!a) trace(a);" - ak, November 2006
30
31 // To do: add some free()-calls for allocated blocks
32
33 #include <assert.h>
34
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40
41 #include "read.h"
42 #include "action.h"
43 #include "swftypes.h"
44 #include "../src/blocks/error.h"
45 #include "vasprintf.h"
46
47
48 static char **pool;
49 struct SWF_ACTIONPUSHPARAM *regs[256];
50
51 static char *getName(struct SWF_ACTIONPUSHPARAM *act);
52
53 static int offseoloop; // offset wherever a break can jump to (loops and switch)
54
55 static void
dumpRegs()56 dumpRegs()
57 {
58 int i;
59 for(i=0;i<6;i++)
60 if( regs[i] )
61 printf("reg[%d] %s\n", i, getName(regs[i]));
62 }
63
64 /*
65 * Start Package
66 *
67 * A package to build up a string that can be returned to the caller
68 * ak/2006: Extended for temporary swichting to a 2nd buffer
69 */
70 #define USE_LIB 1
71
72 static int strsize=0;
73 static int strmaxsize=0;
74 static char *dcstr=NULL;
75 static char *dcptr=NULL;
76
77 #define DCSTRSIZE 40960
78 #define PARAM_STRSIZE 512
79 void
dcinit()80 dcinit()
81 {
82 strsize=0;
83 strmaxsize=DCSTRSIZE;
84 dcstr=calloc(DCSTRSIZE,1);
85 dcptr=dcstr;
86 }
87
88 void
dcchkstr(int size)89 dcchkstr(int size)
90 {
91 while( (strsize+size) > strmaxsize ) {
92 dcstr=realloc(dcstr,strmaxsize+DCSTRSIZE);
93 strmaxsize+=DCSTRSIZE;
94 dcptr=dcstr+strsize;
95 }
96
97 }
98
99 void
dcputs(const char * s)100 dcputs(const char *s)
101 {
102 int len=strlen(s);
103 dcchkstr(len);
104 strcat(dcptr,s);
105 dcptr+=len;
106 strsize+=len;
107 }
108
109 void
dcputchar(char c)110 dcputchar(char c)
111 {
112 dcchkstr(1);
113
114 *dcptr++=c;
115 *dcptr='\000';
116 strsize++;
117 }
118
119 int
dcprintf(char * format,...)120 dcprintf(char *format, ...)
121 {
122 char *s;
123 size_t size;
124 int ret;
125
126 va_list args;
127 va_start(args,format);
128 ret = vasprintf(&s,format,args);
129 dcputs(s);
130 size=strlen(s);
131 free(s);
132 return size;
133 }
134
135 char *
dcgetstr()136 dcgetstr()
137 {
138 char *ret;
139 ret = dcstr;
140 dcstr=NULL;
141 strmaxsize=0;
142 return ret;
143 }
144
145 struct strbufinfo
146 {
147 int size;
148 int maxsize;
149 char *str;
150 char *ptr;
151 };
152
153
setTempString(void)154 static struct strbufinfo setTempString(void)
155 {
156 struct strbufinfo current;
157 current.size=strsize;
158 current.maxsize=strmaxsize;
159 current.str=dcstr;
160 current.ptr=dcptr;
161 dcinit();
162 return current;
163 }
164
setOrigString(struct strbufinfo old)165 static void setOrigString(struct strbufinfo old)
166 {
167 free(dcstr); /* not needed anymore */
168 strsize=old.size;
169 strmaxsize=old.maxsize;
170 dcstr=old.str;
171 dcptr=old.ptr;
172 }
173
174 // a variant of setOrigString()
175 // but for further usage of 2nd buffer
176 //
177 static char *
switchToOrigString(struct strbufinfo old)178 switchToOrigString(struct strbufinfo old)
179 {
180 char *tmp=dcstr;
181 strsize=old.size;
182 strmaxsize=old.maxsize;
183 dcstr=old.str;
184 dcptr=old.ptr;
185 return tmp;
186 }
187
188 #if USE_LIB
189 #define puts(s) dcputs(s)
190 #define putchar(c) dcputchar(c)
191 #define printf dcprintf
192 #endif
193
194 #define INDENT { int ii=gIndent; while(--ii>=0) { putchar(' '); putchar(' '); } }
195
196 /* String used for terminating lines (see println) */
197 static const char* newlinestring = "\\\n";
198
199 /* Set the newline character. By default it is an escaped NL. */
200 void
setNewLineString(const char * ch)201 setNewLineString(const char* ch)
202 {
203 newlinestring = ch;
204 }
205
206 /* Print a line with a terminating newline, which can be set by
207 * setNewLineString()
208 */
209 static void
println(const char * fmt,...)210 println(const char* fmt, ...)
211 {
212 char *tmp;
213 int written;
214
215 va_list ap;
216 va_start (ap, fmt);
217 written = vasprintf (&tmp, fmt, ap);
218
219 dcprintf("%s%s", tmp, newlinestring);
220
221 free(tmp);
222 }
223
224
225 /* End Package */
226
227 /*
228 * Start Package
229 *
230 * A package to maintain escaped characters strings
231 * [ BSC == BackSlashCounter ]
232 */
233 #define BSC 2
strlenext(char * str)234 static int strlenext(char *str)
235 {
236 int i=0;
237 while (*str)
238 {
239 i++;
240 if (*str=='\'') i+=BSC;
241 str++;
242 }
243 return i;
244 }
245
strcpyext(char * dest,char * src)246 static char* strcpyext(char *dest,char *src)
247 {
248 char *r=dest;
249 while (*src)
250 {
251 if (*src=='\'')
252 {
253 *dest++='\\';
254 #if BSC == 2
255 *dest++='\\';
256 #endif
257 }
258 *dest++=*src++;
259 }
260 *dest='\0';
261 return r;
262 }
263
strcatext(char * dest,char * src)264 static char* strcatext(char *dest,char *src)
265 {
266 char *r=dest;
267 while (*dest)
268 dest++;
269 strcpyext(dest,src);
270 return r;
271 }
272 /* End Package */
273
274 /*
275 * Start Package
276 *
277 * A package to maintain a representation of the Flash VM stack
278 */
279
280 struct _stack {
281 char type;
282 struct SWF_ACTIONPUSHPARAM *val;
283 struct _stack *next;
284 };
285
286 struct _stack *Stack;
287
288 enum
289 {
290 PUSH_STRING = 0,
291 PUSH_FLOAT = 1,
292 PUSH_NULL = 2,
293 PUSH_UNDEF = 3,
294 PUSH_REGISTER = 4,
295 PUSH_BOOLEAN = 5,
296 PUSH_DOUBLE = 6,
297 PUSH_INT = 7,
298 PUSH_CONSTANT = 8,
299 PUSH_CONSTANT16 = 9,
300 PUSH_VARIABLE = 10,
301 };
302
303 static char *
getString(struct SWF_ACTIONPUSHPARAM * act)304 getString(struct SWF_ACTIONPUSHPARAM *act)
305 {
306 char *t;
307 #ifdef DEBUG
308 printf("*getString* type=%d\n",act->Type);
309 #endif
310 switch( act->Type )
311 {
312 case PUSH_STRING:
313 t=malloc(strlen(act->p.String)+3); /* 2 "'"s and a NULL */
314 strcpy(t,"'");
315 strcat(t,act->p.String);
316 strcat(t,"'");
317 return t;
318 case PUSH_NULL: /* NULL */
319 return "null";
320 case PUSH_UNDEF: /* Undefined */
321 return "undefined";
322 case PUSH_REGISTER: /* REGISTER */
323 if( regs[act->p.RegisterNumber] &&
324 regs[act->p.RegisterNumber]->Type != 4 &&
325 regs[act->p.RegisterNumber]->Type != 7 )
326 {
327 return getName(regs[act->p.RegisterNumber]);
328 }
329 else
330 {
331 t=malloc(4); /* Rdd */
332 sprintf(t,"R%d", act->p.RegisterNumber );
333 return t;
334 }
335 case PUSH_BOOLEAN: /* BOOLEAN */
336 if( act->p.Boolean )
337 return "true";
338 else
339 return "false";
340 case PUSH_DOUBLE: /* DOUBLE */
341 t=malloc(10); /* big enough? */
342 sprintf(t,"%g", act->p.Double );
343 return t;
344 case PUSH_INT: /* INTEGER */
345 t=malloc(10); /* 32-bit decimal */
346 sprintf(t,"%ld", act->p.Integer );
347 return t;
348 case PUSH_CONSTANT: /* CONSTANT8 */
349 t=malloc(strlenext(pool[act->p.Constant8])+3); /* 2 "'"s and a NULL */
350 strcpy(t,"'");
351 strcatext(t,pool[act->p.Constant8]);
352 strcat(t,"'");
353 return t;
354 case PUSH_CONSTANT16: /* CONSTANT16 */
355 t=malloc(strlenext(pool[act->p.Constant16])+3); /* 2 '\"'s and a NULL */
356 strcpy(t,"'");
357 strcatext(t,pool[act->p.Constant16]);
358 strcat(t,"'");
359 return t;
360
361 case 12:
362 case 11: /* INCREMENTED or DECREMENTED VARIABLE */
363 case PUSH_VARIABLE: /* VARIABLE */
364 return act->p.String;
365 default:
366 fprintf (stderr," Can't get string for type: %d\n", act->Type);
367 break;
368 }
369 return "";
370 }
371
372 static char *
getName(struct SWF_ACTIONPUSHPARAM * act)373 getName(struct SWF_ACTIONPUSHPARAM *act)
374 {
375 char *t;
376
377 switch( act->Type )
378 {
379 case PUSH_STRING: /* STRING */
380 t=malloc(strlen(act->p.String)+3);
381 /*
382 strcpy(t,"\"");
383 strcat(t,act->p.String);
384 strcat(t,"\"");
385 */
386 strcpy(t,act->p.String);
387 if(strlen(t)) /* Not a zero length string */
388 return t;
389 else
390 return "this";
391 #if 0
392 case 4: /* REGISTER */
393 t=malloc(4); /* Rdd */
394 sprintf(t,"R%d", act->p.RegisterNumber );
395 return t;
396 #endif
397 case PUSH_CONSTANT: /* CONSTANT8 */
398 t=malloc(strlenext(pool[act->p.Constant8])+1);
399 strcpyext(t,pool[act->p.Constant8]);
400 if(strlen(t)) /* Not a zero length string */
401 return t;
402 else
403 {
404 t=realloc(t,6);
405 return strcpy(t,"this");
406 }
407 case PUSH_CONSTANT16: /* CONSTANT16 */
408 t=malloc(strlenext(pool[act->p.Constant16])+1);
409 strcpyext(t,pool[act->p.Constant16]);
410 if(strlen(t)) /* Not a zero length string */
411 return t;
412 else
413 {
414 t=realloc(t,6);
415 return strcpy(t,"this");
416 }
417 default:
418 return getString(act);
419 }
420 }
421
422 static int
getInt(struct SWF_ACTIONPUSHPARAM * act)423 getInt(struct SWF_ACTIONPUSHPARAM *act)
424 {
425 switch( act->Type )
426 {
427 case PUSH_FLOAT: /* FLOAT -- also used for PROPERTY storing */
428 return ((int)act->p.Float);
429 case PUSH_NULL: /* NULL */
430 return 0;
431 case PUSH_REGISTER: /* REGISTER */
432 return getInt(regs[act->p.RegisterNumber]);
433 case PUSH_DOUBLE: /* DOUBLE */
434 return (int)act->p.Double;
435 case PUSH_INT: /* INTEGER */
436 return act->p.Integer;
437 default:
438 fprintf (stderr," Can't get int for type: %d\n", act->Type);
439 }
440 return 0;
441 }
442
443 static char *
getProperty(Property prop)444 getProperty(Property prop)
445 {
446 switch(prop)
447 {
448 case SWF_SETPROPERTY_X: return("_x"); break;
449 case SWF_SETPROPERTY_Y:
450 case PROPERTY_Y: return("_y"); break;
451 case PROPERTY_XMOUSE: return("_xMouse"); break;
452 case PROPERTY_YMOUSE: return("_yMouse"); break;
453 case SWF_SETPROPERTY_XSCALE:
454 case PROPERTY_XSCALE: return("_xScale"); break;
455 case SWF_SETPROPERTY_YSCALE:
456 case PROPERTY_YSCALE: return("_yScale"); break;
457 case PROPERTY_CURRENTFRAME: return("_currentFrame"); break;
458 case PROPERTY_TOTALFRAMES: return("_totalFrames"); break;
459 case SWF_SETPROPERTY_ALPHA:
460 case PROPERTY_ALPHA: return("_alpha"); break;
461 case SWF_SETPROPERTY_VISIBILITY:
462 case PROPERTY_VISIBLE: return("_visible"); break;
463 case PROPERTY_WIDTH: return("_width"); break;
464 case PROPERTY_HEIGHT: return("_height"); break;
465 case SWF_SETPROPERTY_ROTATION:
466 case PROPERTY_ROTATION: return("_rotation"); break;
467 case PROPERTY_TARGET: return("_target"); break;
468 case PROPERTY_FRAMESLOADED: return("_framesLoaded"); break;
469 case SWF_SETPROPERTY_NAME:
470 case PROPERTY_NAME: return("_name"); break;
471 case PROPERTY_DROPTARGET: return("_dropTarget"); break;
472 case PROPERTY_URL: return("_url"); break;
473 case SWF_SETPROPERTY_HIGHQUALITY:
474 case PROPERTY_HIGHQUALITY: return("_quality"); break;
475 case SWF_SETPROPERTY_SHOWFOCUSRECT:
476 case PROPERTY_FOCUSRECT: return("_focusRect"); break;
477 case SWF_SETPROPERTY_SOUNDBUFFERTIME:
478 case PROPERTY_SOUNDBUFTIME: return("_soundBufTime"); break;
479 case SWF_SETPROPERTY_WTHIT:
480 case PROPERTY_WTHIT: return("_WTHIT!?"); break;
481 default: return("unknown property!"); break;
482 }
483 }
484
485 struct SWF_ACTIONPUSHPARAM *
newVar(char * var)486 newVar(char *var)
487 {
488 struct SWF_ACTIONPUSHPARAM *v;
489
490 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
491 v->Type = PUSH_VARIABLE;
492 v->p.String = var;
493 return v;
494 }
495
496 struct SWF_ACTIONPUSHPARAM *
newVar2(char * var,char * var2)497 newVar2(char *var,char *var2)
498 {
499 struct SWF_ACTIONPUSHPARAM *v;
500
501 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
502 v->Type = PUSH_VARIABLE;
503 v->p.String = malloc(strlen(var)+strlen(var2)+1);
504 strcpy(v->p.String,var);
505 strcat(v->p.String,var2);
506 return v;
507 }
508
509
510 struct SWF_ACTIONPUSHPARAM *
newVar3(char * var,char * var2,char * var3)511 newVar3(char *var,char *var2, char *var3)
512 {
513 struct SWF_ACTIONPUSHPARAM *v;
514
515 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
516 v->Type = PUSH_VARIABLE; /* VARIABLE */
517 v->p.String = malloc(strlen(var)+strlen(var2)+strlen(var3)+1);
518 strcpy(v->p.String,var);
519 strcat(v->p.String,var2);
520 strcat(v->p.String,var3);
521 return v;
522 }
523
524 struct SWF_ACTIONPUSHPARAM *
newVar5(char * var,char * var2,char * var3,char * var4,char * var5)525 newVar5(char *var,char *var2, char *var3,char *var4,char *var5)
526 {
527 struct SWF_ACTIONPUSHPARAM *v;
528
529 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
530 v->Type = PUSH_VARIABLE; /* VARIABLE */
531 v->p.String = malloc(strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(var5)+1);
532 strcpy(v->p.String,var);
533 strcat(v->p.String,var2);
534 strcat(v->p.String,var3);
535 strcat(v->p.String,var4);
536 strcat(v->p.String,var5);
537 return v;
538 }
539
540 void
push(struct SWF_ACTIONPUSHPARAM * val)541 push(struct SWF_ACTIONPUSHPARAM *val)
542 {
543 struct _stack *t;
544 #ifdef DEBUG
545 printf("*push* type=%d\n",val->Type);
546 #endif
547 t = calloc(1,sizeof(*Stack));
548 t->type = val->Type;
549 t->val = val;
550 t->next = Stack;
551 Stack = t;
552 }
553
554
555 void
pushdup()556 pushdup()
557 {
558 struct _stack *t;
559 #ifdef DEBUG
560 printf("*pushdup*\n");
561 #endif
562 if(Stack == NULL)
563 {
564 SWF_warn("WARNING: pushdup on empty stack. This might be wrong!\n");
565 return;
566 }
567 t = calloc(1,sizeof(*Stack));
568 t->type = Stack->type;
569 t->val = Stack->val;
570 t->next = Stack;
571 Stack = t;
572 }
573
574
575 void
pushvar(struct SWF_ACTIONPUSHPARAM * val)576 pushvar(struct SWF_ACTIONPUSHPARAM *val)
577 {
578 struct _stack *t;
579 #ifdef DEBUG
580 printf("*pushvar*\n");
581 #endif
582 t = calloc(1,sizeof(*Stack));
583 t->type = 'v'; // ???
584 t->val = val;
585 t->next = Stack;
586 Stack = t;
587 }
588
pop()589 struct SWF_ACTIONPUSHPARAM * pop()
590 {
591 struct _stack *t;
592 struct SWF_ACTIONPUSHPARAM * ret;
593
594 #ifdef DEBUG
595 printf("*pop*\n");
596 #endif
597 #ifdef DEBUGSTACK /* continue w stack dummy */
598 if( Stack == NULL ) push(newVar("// *** pop(): INTERNAL STACK ERROR FOUND ***"));
599 #else
600 if( Stack == NULL ) SWF_error("Stack blown!! - pop");
601 #endif
602 t=Stack;
603 Stack=t->next;
604 ret=t->val;
605 return ret;
606 }
607
peek()608 struct SWF_ACTIONPUSHPARAM * peek()
609 {
610 #ifdef DEBUG
611 printf("*peek*\n");
612 #endif
613 #ifdef DEBUGSTACK /* continue w stack dummy */
614 if( Stack == NULL ) push(newVar("// *** peek(): INTERNAL STACK ERROR FOUND ***"));
615 #else
616 if( Stack == NULL ) SWF_error("Stack blown!! - peek");
617 #endif
618 return Stack->val;
619 }
620
621 void
stackswap()622 stackswap()
623 {
624 #ifdef DEBUG
625 printf("*stackswap*\n");
626 #endif
627 struct SWF_ACTIONPUSHPARAM *p = peek(); /* peek() includes error handling */
628 char type = Stack->type;
629 Stack->type = Stack->next->type;
630 Stack->val = Stack->next->val;
631 Stack->next->type = type;
632 Stack->next->val = p;
633 }
634
635
636 static struct SWF_ACTIONPUSHPARAM *
newVar_N(char * var,char * var2,char * var3,char * var4,int pop_counter,char * final)637 newVar_N(char *var,char *var2, char *var3,char *var4,int pop_counter,char *final)
638 {
639 struct SWF_ACTIONPUSHPARAM *v;
640 int psize=PARAM_STRSIZE;
641 int i;
642 int slen=strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(final);
643
644 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
645 v->p.String = malloc(psize + slen);
646 v->Type = PUSH_VARIABLE;
647 strcpy(v->p.String,var);
648 strcat(v->p.String,var2);
649 strcat(v->p.String,var3);
650 strcat(v->p.String,var4);
651 for(i=0;i<pop_counter;i++)
652 {
653 char *pops=getString(pop());
654 while ( strlen(v->p.String)+ 2 + strlen(pops) +slen >= psize)
655 {
656 psize += PARAM_STRSIZE;
657 v->p.String = realloc( v->p.String, psize);
658 }
659 strcat(v->p.String,pops);
660 if( i < pop_counter-1 )
661 strcat(v->p.String,",");
662 }
663 strcat(v->p.String,final);
664 return v;
665 }
666
667 // similar to newVar_N(),
668 // but pops 2 items from stack per counter,
669 // and second of them we are interested in getName() instead of getString()
670 static struct SWF_ACTIONPUSHPARAM *
newVar_N2(char * var,char * var2,char * var3,char * var4,int pop_counter,char * final)671 newVar_N2(char *var,char *var2, char *var3,char *var4,int pop_counter,char *final)
672 {
673 struct SWF_ACTIONPUSHPARAM *v;
674 int psize=PARAM_STRSIZE;
675 int i;
676 int slen=strlen(var)+strlen(var2)+strlen(var3)+strlen(var4)+strlen(final);
677
678 v=malloc(sizeof(struct SWF_ACTIONPUSHPARAM));
679 v->p.String = malloc(psize + slen);
680 v->Type = PUSH_VARIABLE;
681 strcpy(v->p.String,var);
682 strcat(v->p.String,var2);
683 strcat(v->p.String,var3);
684 strcat(v->p.String,var4);
685 for(i=0;i<pop_counter;i++)
686 {
687 char *pops1=getString(pop());
688 char *pops2=getName (pop());
689
690 while ( strlen(v->p.String)+ 3 + strlen(pops1)+ strlen(pops2) +slen >= psize)
691 {
692 psize += PARAM_STRSIZE;
693 v->p.String = realloc( v->p.String, psize);
694 }
695 strcat(v->p.String,pops2);
696 strcat(v->p.String,":");
697 strcat(v->p.String,pops1);
698 if( i < pop_counter-1 )
699 strcat(v->p.String,",");
700 }
701 strcat(v->p.String,final);
702 return v;
703 }
704
705 /* End Package */
706
707 static int gIndent;
708 static void decompileActions(int n, SWF_ACTION *actions,int indent);
709 char * decompile5Action(int n, SWF_ACTION *actions,int indent);
710
711 /******************************************************************************/
712 /******************************************************************************/
713 /******************************************************************************/
714 /******************************************************************************/
715 /******************************************************************************/
716
717
718 #define SanityCheck(curact,test,msg ) \
719 if(!(test) ) SWF_error( "SanityCheck failed in %s\n %s\n", #curact, msg );
720
721 #define OUT_BEGIN(block) \
722 struct block *sact = (struct block *)act;
723 #define OUT_BEGIN2(block) \
724 struct block *sact = (struct block *)&(actions[n]);
725
726 static void
decompileCONSTANTPOOL(SWF_ACTION * act)727 decompileCONSTANTPOOL (SWF_ACTION *act)
728 {
729 OUT_BEGIN(SWF_ACTIONCONSTANTPOOL);
730 pool=sact->ConstantPool;
731 }
732
733 static void
decompileWAITFORFRAME(SWF_ACTION * act)734 decompileWAITFORFRAME (SWF_ACTION *act)
735 {
736 OUT_BEGIN(SWF_ACTIONWAITFORFRAME);
737
738 INDENT
739 println("WaitForFrame(%d,%d);", sact->Frame,sact->SkipCount);
740 }
741
742 static void
decompilePUSHPARAM(struct SWF_ACTIONPUSHPARAM * act,int wantstring)743 decompilePUSHPARAM (struct SWF_ACTIONPUSHPARAM *act, int wantstring)
744 {
745 char *t;
746 switch( act->Type )
747 {
748 case PUSH_STRING: /* STRING */
749 if( wantstring ) printf ("'%s'", act->p.String);
750 else printf ("%s", act->p.String);
751 break;
752 case PUSH_FLOAT: /* FLOAT */
753 printf ("%f", act->p.Float);
754 break;
755 case PUSH_NULL: /* NULL */
756 printf ("NULL" );
757 break;
758 case PUSH_UNDEF: /* Undefined */
759 printf ("undefined" );
760 break;
761 case PUSH_REGISTER: /* Register */
762 if( regs[act->p.RegisterNumber] ) {
763 printf ("%s", getName(act));
764 } else {
765 printf ("R%d", (int)act->p.RegisterNumber);
766 }
767 break;
768 case PUSH_BOOLEAN: /* BOOLEAN */
769 printf ("%s", act->p.Boolean?"true":"false");
770 break;
771 case PUSH_DOUBLE: /* DOUBLE */
772 printf ("%g", act->p.Double);
773 break;
774 case PUSH_INT: /* INTEGER */
775 printf ("%ld", act->p.Integer);
776 break;
777
778 case PUSH_CONSTANT: /* CONSTANT8 */
779 case PUSH_CONSTANT16: /* CONSTANT16 */
780 if( wantstring ) t=getString(act);
781 else t=getName(act);
782 puts(t);
783 free(t);
784 break;
785
786 #if 0
787 case 8: /* CONSTANT8 */
788 if( wantstring )
789 printf ("'%s'", pool[act->p.Constant8]);
790 else
791 printf ("%s", pool[act->p.Constant8]);
792 break;
793 case 9: /* CONSTANT16 */
794 if( wantstring )
795 printf ("'%s'", pool[act->p.Constant16]);
796 else
797 printf ("%s", pool[act->p.Constant16]);
798 break;
799 #endif
800 case 12:
801 case 11: /* INCREMENTED or DECREMENTED VARIABLE */
802 case PUSH_VARIABLE: /* VARIABLE */
803 printf ("%s", act->p.String);
804 break;
805 default:
806 printf (" Unknown type: %d\n", act->Type);
807 }
808 }
809
810 static void
decompileGETURL(SWF_ACTION * act)811 decompileGETURL (SWF_ACTION *act)
812 {
813 OUT_BEGIN(SWF_ACTIONGETURL);
814
815 INDENT
816 println("getUrl('%s',%s);", sact->UrlString, sact->TargetString);
817 }
818
819 static int
decompileGETURL2(SWF_ACTION * act)820 decompileGETURL2 (SWF_ACTION *act)
821 {
822 struct SWF_ACTIONPUSHPARAM *a,*b;
823 OUT_BEGIN(SWF_ACTIONGETURL2);
824 INDENT
825
826 a = pop();
827 b = pop();
828
829 if (sact->f.FlagBits.SendVarsMethod==3)
830 puts("loadVariables(");
831 else
832 {
833 if (sact->f.FlagBits.SendVarsMethod==2)
834 puts("loadVariablesNum(");
835 else
836 {
837 if (sact->f.FlagBits.SendVarsMethod==1)
838 puts("loadMovie(");
839 else
840 {
841 if (*getName(a)=='_') // found a _level
842 puts("loadMovieNum(");
843 else
844 puts("getURL(");
845 }
846 }
847 }
848 decompilePUSHPARAM (b, 1);
849 puts(",");
850 decompilePUSHPARAM (a, 1);
851 if (sact->f.FlagBits.LoadVariableFlag)
852 puts(",'GET'");
853 if (sact->f.FlagBits.LoadTargetFlag)
854 puts(",'POST'");
855 println(");");
856 return 0;
857 }
858
OpCode(SWF_ACTION * actions,int n,int maxn)859 static inline int OpCode(SWF_ACTION *actions, int n, int maxn)
860 {
861 if(!n || n >= maxn)
862 {
863 #if DEBUG
864 SWF_warn("OpCode: want %i, max %i\n", n, maxn);
865 #endif
866 return -999;
867 }
868 return actions[n].SWF_ACTIONRECORD.ActionCode;
869 }
870
871 static int
isStoreOp(int n,SWF_ACTION * actions,int maxn)872 isStoreOp(int n, SWF_ACTION *actions,int maxn)
873 {
874 switch(OpCode(actions, n, maxn))
875 {
876 case SWFACTION_STOREREGISTER:
877 case SWFACTION_SETVARIABLE:
878 case SWFACTION_SETMEMBER:
879 case SWFACTION_CASTOP:
880 return 1;
881 default:
882 return 0;
883 }
884 }
885
886 static int
decompileGOTOFRAME(int n,SWF_ACTION * actions,int maxn,int islabel)887 decompileGOTOFRAME(int n, SWF_ACTION *actions,int maxn,int islabel)
888 {
889 int i=0;
890 struct SWF_ACTIONGOTOLABEL *sactv2;
891 OUT_BEGIN2(SWF_ACTIONGOTOFRAME);
892 sactv2 = (struct SWF_ACTIONGOTOLABEL*)sact;
893 INDENT
894 if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY)
895 {
896 i=1;
897 puts("gotoAndPlay(");
898 }
899 else
900 {
901 if (OpCode(actions, n+1, maxn) == SWFACTION_STOP)
902 i=1;
903 puts("gotoAndStop(");
904 }
905
906 if (islabel)
907 println("'%s');", sactv2->FrameLabel);
908 else
909 println("%d);", sact->Frame+1); /* GOTOFRAME arg is 0-based */
910 return i;
911 }
912
913 static int
decompileGOTOFRAME2(int n,SWF_ACTION * actions,int maxn)914 decompileGOTOFRAME2(int n, SWF_ACTION *actions, int maxn)
915 {
916 int i=0;
917 OUT_BEGIN2(SWF_ACTIONGOTOFRAME2);
918 INDENT
919 if (n+1 < maxn)
920 {
921 if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY ||
922 OpCode(actions, n+1, maxn) == SWFACTION_STOP)
923 i=1;
924 if (OpCode(actions, n+1, maxn) == SWFACTION_PLAY)
925 puts("gotoAndPlay(");
926 else
927 {
928 if (OpCode(actions, n+1, maxn) == SWFACTION_STOP)
929 puts("gotoAndStop(");
930 else
931 {
932 if (sact->f.FlagBits.PlayFlag)
933 puts("gotoAndPlay(");
934 else
935 puts("gotoAndStop(");
936 }
937 }
938 }
939 else
940 {
941 if (sact->f.FlagBits.PlayFlag)
942 puts("gotoAndPlay(");
943 else
944 puts("gotoAndStop(");
945 }
946 decompilePUSHPARAM(pop(),0);
947 println(");");
948 return i;
949 }
950
951
precedence(int op1,int op2)952 static int precedence(int op1,int op2)
953 {
954 static unsigned char ops[]= { // array of opcodes w rising precedence
955 // SWFACTION_SETVARIABLE, // TAKE CARE: array is incomplete
956 // SWFACTION_TRACE,
957 // missing ops are considered with low precedence
958 SWFACTION_LOGICALOR,
959 SWFACTION_LOGICALAND,
960 SWFACTION_BITWISEOR,
961 SWFACTION_BITWISEXOR,
962 SWFACTION_BITWISEAND,
963 SWFACTION_STRICTEQUALS,
964 SWFACTION_EQUALS2,
965 SWFACTION_EQUAL,
966 SWFACTION_GREATER,
967 SWFACTION_LESSTHAN,
968 SWFACTION_LESS2,
969 SWFACTION_SHIFTRIGHT,
970 SWFACTION_SHIFTRIGHT2,
971 SWFACTION_SHIFTLEFT,
972 SWFACTION_ADD,
973 SWFACTION_ADD2,
974 SWFACTION_SUBTRACT,
975 SWFACTION_MODULO,
976 SWFACTION_MULTIPLY,
977 SWFACTION_DIVIDE,
978 SWFACTION_LOGICALNOT,
979 SWFACTION_PUSH // FIXME: need more analysis on code after PUSH
980 };
981 unsigned char* f=memchr(ops,op1,sizeof(ops));
982 unsigned char* s=memchr(ops,op2,sizeof(ops));
983 #ifdef DEBUG
984 printf("1op=%d 2op=%d result=%d\n",op1,op2,f>s);
985 if (!f) printf("opcode=%d NOT in precedence list\n",op1);
986 if (!s) printf("opcode=%d NOT in precedence list\n",op2);
987 #endif
988 return f>s;
989 }
990
991 #ifdef DECOMP_SWITCH
992 static int
check_switch(int firstcode)993 check_switch(int firstcode)
994 {
995 return (firstcode == SWFACTION_PUSH || firstcode == SWFACTION_JUMP);
996 }
997 #endif
998
999
1000 static int
decompileArithmeticOp(int n,SWF_ACTION * actions,int maxn)1001 decompileArithmeticOp(int n, SWF_ACTION *actions, int maxn)
1002 {
1003 struct SWF_ACTIONPUSHPARAM *left, *right;
1004 int op_l = OpCode(actions, n, maxn);
1005 int op_r = OpCode(actions, n+1, maxn);
1006 right=pop();
1007 left=pop();
1008 switch(OpCode(actions, n, maxn))
1009 {
1010 /*
1011 case SWFACTION_GETMEMBER:
1012 decompilePUSHPARAM(peek(),0);
1013 break;
1014 */
1015 case SWFACTION_INSTANCEOF:
1016 if (precedence(op_l, op_r))
1017 push(newVar3(getString(left)," instanceof ",getString(right)));
1018 else
1019 push(newVar_N("(",getString(left)," instanceof ",getString(right),0,")"));
1020 break;
1021 case SWFACTION_ADD:
1022 case SWFACTION_ADD2:
1023 if (precedence(op_l, op_r))
1024 push(newVar3(getString(left),"+",getString(right)));
1025 else
1026 push(newVar_N("(",getString(left),"+",getString(right),0,")"));
1027 break;
1028 case SWFACTION_SUBTRACT:
1029 if (precedence(op_l, op_r))
1030 push(newVar3(getString(left),"-",getString(right)));
1031 else
1032 push(newVar_N("(",getString(left),"-",getString(right),0,")"));
1033 break;
1034 case SWFACTION_MULTIPLY:
1035 if (precedence(op_l, op_r))
1036 push(newVar3(getString(left),"*",getString(right)));
1037 else
1038 push(newVar_N("(",getString(left),"*",getString(right),0,")"));
1039 break;
1040 case SWFACTION_DIVIDE:
1041 if (precedence(op_l, op_r))
1042 push(newVar3(getString(left),"/",getString(right)));
1043 else
1044 push(newVar_N("(",getString(left),"/",getString(right),0,")"));
1045 break;
1046 case SWFACTION_MODULO:
1047 if (precedence(op_l, op_r))
1048 push(newVar3(getString(left),"%",getString(right)));
1049 else
1050 push(newVar_N("(",getString(left),"%",getString(right),0,")"));
1051 break;
1052 case SWFACTION_SHIFTLEFT:
1053 if (precedence(op_l, op_r))
1054 push(newVar3(getString(left),"<<",getString(right)));
1055 else
1056 push(newVar_N("(",getString(left),"<<",getString(right),0,")"));
1057 break;
1058 case SWFACTION_SHIFTRIGHT:
1059 if (precedence(op_l, op_r))
1060 push(newVar3(getString(left),">>",getString(right)));
1061 else
1062 push(newVar_N("(",getString(left),">>",getString(right),0,")"));
1063 break;
1064 case SWFACTION_SHIFTRIGHT2:
1065 if (precedence(op_l, op_r))
1066 push(newVar3(getString(left),">>>",getString(right)));
1067 else
1068 push(newVar_N("(",getString(left),">>>",getString(right),0,")"));
1069 break;
1070 case SWFACTION_LOGICALAND:
1071 if (precedence(op_l, op_r))
1072 push(newVar3(getString(left),"&&",getString(right)));
1073 else
1074 push(newVar_N("(",getString(left),"&&",getString(right),0,")"));
1075 break;
1076 case SWFACTION_LOGICALOR:
1077 if (precedence(op_l, op_r))
1078 push(newVar3(getString(left),"||",getString(right)));
1079 else
1080 push(newVar_N("(",getString(left),"||",getString(right),0,")"));
1081 break;
1082 case SWFACTION_BITWISEAND:
1083 if (precedence(op_l, op_r))
1084 push(newVar3(getString(left),"&",getString(right)));
1085 else
1086 push(newVar_N("(",getString(left),"&",getString(right),0,")"));
1087 break;
1088 case SWFACTION_BITWISEOR:
1089 if (precedence(op_l, op_r))
1090 push(newVar3(getString(left),"|",getString(right)));
1091 else
1092 push(newVar_N("(",getString(left),"|",getString(right),0,")"));
1093 break;
1094 case SWFACTION_BITWISEXOR:
1095 if (precedence(op_l, op_r))
1096 push(newVar3(getString(left),"^",getString(right)));
1097 else
1098 push(newVar_N("(",getString(left),"^",getString(right),0,")"));
1099 break;
1100 case SWFACTION_EQUALS2: /* including negation */
1101 case SWFACTION_EQUAL:
1102 if( OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1103 OpCode(actions, n+2, maxn) != SWFACTION_IF)
1104 {
1105 op_r = OpCode(actions, n+1, maxn);
1106 if (precedence(op_l, op_r))
1107 push(newVar3(getString(left),"!=",getString(right)));
1108 else
1109 push(newVar_N("(",getString(left),"!=",getString(right),0,")"));
1110 return 1; /* due negation op */
1111 }
1112 if (precedence(op_l, op_r))
1113 push(newVar3(getString(left),"==",getString(right)));
1114 else
1115 push(newVar_N("(",getString(left),"==",getString(right),0,")"));
1116 break;
1117 case SWFACTION_LESS2:
1118 if( OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1119 OpCode(actions, n+2, maxn) != SWFACTION_IF )
1120 {
1121 op_r = OpCode(actions, n+2, maxn);
1122 if (precedence(op_l, op_r))
1123 push(newVar3(getString(left),">=",getString(right)));
1124 else
1125 push(newVar_N("(",getString(left),">=",getString(right),0,")"));
1126 return 1; /* due negation op */
1127 }
1128 if (precedence(op_l, op_r))
1129 push(newVar3(getString(left),"<",getString(right)));
1130 else
1131 push(newVar_N("(",getString(left),"<",getString(right),0,")"));
1132 break;
1133 case SWFACTION_GREATER:
1134 if (precedence(op_l, op_r))
1135 push(newVar3(getString(left),">",getString(right)));
1136 else
1137 push(newVar_N("(",getString(left),">",getString(right),0,")"));
1138 break;
1139 case SWFACTION_LESSTHAN:
1140 if (precedence(op_l, op_r))
1141 push(newVar3(getString(left),"<",getString(right)));
1142 else
1143 push(newVar_N("(",getString(left),"<",getString(right),0,")"));
1144 break;
1145 case SWFACTION_STRINGEQ:
1146 if (precedence(op_l, op_r))
1147 push(newVar3(getString(left),"==",getString(right)));
1148 else
1149 push(newVar_N("(",getString(left),"==",getString(right),0,")"));
1150 break;
1151 case SWFACTION_STRINGCOMPARE:
1152 puts("STRINGCOMPARE");
1153 break;
1154 case SWFACTION_STRICTEQUALS:
1155 #ifdef DECOMP_SWITCH
1156 if (OpCode(actions, n, maxn) == SWFACTION_IF)
1157 {
1158 int code = actions[n+1].SWF_ACTIONIF.Actions[0].SWF_ACTIONRECORD.ActionCode;
1159 if(check_switch(code))
1160 {
1161 push(right); // keep left and right side separated
1162 push(left); // because it seems we have found a switch(){} and
1163 break; // let decompileIF() once more do all the dirty work
1164 }
1165 }
1166 #endif
1167 if( OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1168 OpCode(actions, n+2, maxn) != SWFACTION_IF )
1169 {
1170 op_r = OpCode(actions, n+2, maxn);
1171 if (precedence(op_l, op_r))
1172 push(newVar3(getString(left),"!==",getString(right)));
1173 else
1174 push(newVar_N("(",getString(left),"!==",getString(right),0,")"));
1175 return 1; /* due negation op */
1176 } else {
1177 if (precedence(op_l, op_r))
1178 push(newVar3(getString(left),"===",getString(right)));
1179 else
1180 push(newVar_N("(",getString(left),"===",getString(right),0,")"));
1181 break;
1182 }
1183 default:
1184 printf("Unhandled Arithmetic/Logic OP %x\n",
1185 actions[n].SWF_ACTIONRECORD.ActionCode);
1186 }
1187 return 0;
1188 }
1189
1190 static int
isLogicalOp(int n,SWF_ACTION * actions,int maxn)1191 isLogicalOp(int n, SWF_ACTION *actions, int maxn)
1192 {
1193 switch(OpCode(actions, n, maxn))
1194 {
1195 case SWFACTION_LESSTHAN:
1196 case SWFACTION_LOGICALAND:
1197 case SWFACTION_LOGICALOR:
1198 case SWFACTION_LOGICALNOT:
1199 case SWFACTION_STRINGEQ:
1200 case SWFACTION_STRINGCOMPARE:
1201 case SWFACTION_LESS2:
1202 case SWFACTION_EQUALS2:
1203 case SWFACTION_EQUAL:
1204 case SWFACTION_BITWISEAND:
1205 case SWFACTION_BITWISEOR:
1206 case SWFACTION_BITWISEXOR:
1207 case SWFACTION_STRICTEQUALS:
1208 case SWFACTION_GREATER:
1209 /*
1210 case SWFACTION_GETMEMBER:
1211 */
1212 return 1;
1213 default:
1214 return 0;
1215 }
1216 }
1217
1218 static int
isLogicalOp2(int n,SWF_ACTION * actions,int maxn)1219 isLogicalOp2(int n, SWF_ACTION *actions,int maxn)
1220 {
1221 switch(actions[n].SWF_ACTIONRECORD.ActionCode)
1222 {
1223 case SWFACTION_LOGICALNOT:
1224 case SWFACTION_PUSHDUP:
1225 case SWFACTION_IF:
1226 return 1;
1227 default:
1228 return 0;
1229 }
1230 }
1231
1232 static int
stackVal(int n,SWF_ACTION * actions)1233 stackVal(int n, SWF_ACTION *actions)
1234 {
1235 if (!n)
1236 return 0;
1237
1238 switch((actions[n-1]).SWF_ACTIONRECORD.ActionCode)
1239 {
1240 case SWFACTION_LOGICALNOT:
1241 case SWFACTION_DECREMENT:
1242 case SWFACTION_INCREMENT:
1243 case SWFACTION_RANDOMNUMBER:
1244 case SWFACTION_TOSTRING:
1245 case SWFACTION_TONUMBER:
1246 case SWFACTION_ORD:
1247 case SWFACTION_CHR:
1248 case SWFACTION_MBORD:
1249 case SWFACTION_MBCHR:
1250 case SWFACTION_INT:
1251 case SWFACTION_GETVARIABLE:
1252 case SWFACTION_SUBSTRING:
1253 case SWFACTION_MBSUBSTRING:
1254 case SWFACTION_GETMEMBER:
1255 case SWFACTION_ADD:
1256 case SWFACTION_ADD2:
1257 case SWFACTION_SUBTRACT:
1258 case SWFACTION_MULTIPLY:
1259 case SWFACTION_DIVIDE:
1260 case SWFACTION_MODULO:
1261 case SWFACTION_BITWISEAND:
1262 case SWFACTION_BITWISEOR:
1263 case SWFACTION_BITWISEXOR:
1264 case SWFACTION_LESSTHAN:
1265 case SWFACTION_LOGICALAND:
1266 case SWFACTION_LOGICALOR:
1267 case SWFACTION_STRINGEQ:
1268 case SWFACTION_STRINGCOMPARE:
1269 case SWFACTION_LESS2:
1270 case SWFACTION_EQUALS2:
1271 case SWFACTION_EQUAL:
1272 case SWFACTION_STRICTEQUALS:
1273 case SWFACTION_GREATER:
1274 case SWFACTION_STRINGGREATER:
1275 case SWFACTION_STRINGCONCAT:
1276 case SWFACTION_SHIFTLEFT:
1277 case SWFACTION_SHIFTRIGHT:
1278 case SWFACTION_SHIFTRIGHT2:
1279 case SWFACTION_INSTANCEOF:
1280 case SWFACTION_CALLMETHOD:
1281 case SWFACTION_CALLFUNCTION:
1282 case SWFACTION_GETTIME:
1283 case SWFACTION_GETPROPERTY:
1284 case SWFACTION_PUSH:
1285 case SWFACTION_DELETE:
1286 case SWFACTION_DELETE2:
1287 case SWFACTION_MBLENGTH:
1288 case SWFACTION_STRINGLENGTH:
1289 case SWFACTION_CASTOP:
1290 case SWFACTION_TYPEOF:
1291 case SWFACTION_PUSHDUP:
1292 return 1;
1293 default:
1294 return 0;
1295 }
1296 }
1297
1298 static int
decompileLogicalNot(int n,SWF_ACTION * actions,int maxn)1299 decompileLogicalNot(int n, SWF_ACTION *actions, int maxn)
1300 {
1301 #ifdef STATEMENT_CLASS
1302 if(OpCode(actions, n-1, maxn) == SWFACTION_GETVARIABLE &&
1303 OpCode(actions, n+1, maxn) == SWFACTION_LOGICALNOT &&
1304 OpCode(actions, n+2, maxn) == SWFACTION_IF )
1305 {
1306 /* It's a class statement -- skip over both NOTs */
1307 return 1;
1308 }
1309 #endif
1310 if(OpCode(actions, n+1, maxn) != SWFACTION_IF )
1311 push(newVar2("!",getString(pop())));
1312 return 0;
1313 }
1314
1315 static void
decompilePUSH(SWF_ACTION * act)1316 decompilePUSH (SWF_ACTION *act)
1317 {
1318 int i;
1319 OUT_BEGIN(SWF_ACTIONPUSH);
1320
1321 SanityCheck(SWF_PUSH,
1322 act->SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH,
1323 "not a PUSH")
1324
1325 for(i=0;i<sact->NumParam;i++)
1326 push(&(sact->Params[i]));
1327 }
1328
1329 static void
decompilePUSHDUP(SWF_ACTION * act)1330 decompilePUSHDUP (SWF_ACTION *act)
1331 {
1332 SanityCheck(SWF_PUSHDUP,
1333 act->SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSHDUP,
1334 "not a PUSHDUP")
1335 pushdup();
1336 }
1337
1338 static void
decompileSTACKSWAP(SWF_ACTION * act)1339 decompileSTACKSWAP (SWF_ACTION *act)
1340 {
1341 SanityCheck(SWF_STACKSWAP,
1342 act->SWF_ACTIONRECORD.ActionCode == SWFACTION_STACKSWAP,
1343 "not a STACKSWAP")
1344 stackswap();
1345 }
1346
1347 static int
decompileSETPROPERTY(int n,SWF_ACTION * actions,int maxn)1348 decompileSETPROPERTY(int n, SWF_ACTION *actions,int maxn)
1349 {
1350 struct SWF_ACTIONPUSHPARAM *val, *idx, *obj;
1351
1352 INDENT
1353 val = pop();
1354 idx = pop();
1355 obj = pop();
1356 #ifdef DEBUG
1357 printf("*setProp* objName %s (type=%d) Prop (type=%d) =%x\n",
1358 getName(obj), obj->Type, idx->Type,getInt(idx));
1359 #endif
1360 if (obj->Type == PUSH_VARIABLE)
1361 puts("eval(");
1362
1363 decompilePUSHPARAM(obj,0);
1364 if (obj->Type == PUSH_VARIABLE)
1365 puts(")");
1366
1367 puts(".");
1368 puts(getProperty(getInt(idx)));
1369 printf(" = " );
1370 decompilePUSHPARAM(val,0);
1371 println(";");
1372 return 0;
1373 }
1374
1375 static int
decompileGETPROPERTY(int n,SWF_ACTION * actions,int maxn)1376 decompileGETPROPERTY(int n, SWF_ACTION *actions,int maxn)
1377 {
1378 struct SWF_ACTIONPUSHPARAM *idx, *obj;
1379
1380 INDENT
1381 idx = pop();
1382 obj = pop();
1383 #ifdef DEBUG
1384 printf("*GETProp* objName %s (type=%d) Prop (type=%d) =%x\n",
1385 getName(obj), obj->Type, idx->Type,getInt(idx));
1386 #endif
1387 if (obj->Type == PUSH_VARIABLE)
1388 push( newVar5("eval(",getName(obj),".",getProperty(getInt(idx)),")"));
1389 else
1390 push( newVar3( getName(obj),".",getProperty(getInt(idx))));
1391 return 0;
1392 }
1393
1394 static int
decompileTRACE(int n,SWF_ACTION * actions,int maxn)1395 decompileTRACE(int n, SWF_ACTION *actions, int maxn)
1396 {
1397 INDENT
1398 puts("trace(");
1399 decompilePUSHPARAM(pop(),1);
1400 println(");");
1401 return 0;
1402 }
1403
1404 static int
decompileCALLFRAME(int n,SWF_ACTION * actions,int maxn)1405 decompileCALLFRAME(int n, SWF_ACTION *actions, int maxn)
1406 {
1407 INDENT
1408 puts("callFrame(");
1409 decompilePUSHPARAM(pop(),1);
1410 println(");");
1411 return 0;
1412 }
1413
1414 static int
decompileGETTIME(int n,SWF_ACTION * actions,int maxn)1415 decompileGETTIME(int n, SWF_ACTION *actions, int maxn)
1416 {
1417 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
1418 {
1419 INDENT
1420 println("getTimer();");
1421 return 1;
1422 }
1423 else
1424 {
1425 push(newVar("getTimer()"));
1426 return 0;
1427 }
1428 }
1429
1430 static int
decompileINCR_DECR(int n,SWF_ACTION * actions,int maxn,int is_incr)1431 decompileINCR_DECR(int n, SWF_ACTION *actions, int maxn, int is_incr)
1432 {
1433 int is_postop;
1434 struct SWF_ACTIONPUSHPARAM *var=pop();
1435 char *dblop=is_incr ? "++":"--";
1436
1437 if((OpCode(actions, n, maxn) == SWFACTION_PUSHDUP
1438 || OpCode(actions, n+1, maxn) == SWFACTION_PUSHDUP
1439 || OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE)
1440 || ( OpCode(actions, n-1, maxn) == SWFACTION_GETVARIABLE
1441 && OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER
1442 && OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE))
1443 {
1444 is_postop=(OpCode(actions, n-1, maxn) == SWFACTION_PUSHDUP)?1:0;
1445 if (is_postop)
1446 var = newVar2(getString(var),dblop);
1447 else
1448 var = newVar2(dblop,getString(var));
1449 if (OpCode(actions, n+1, maxn) == SWFACTION_SETVARIABLE)
1450 {
1451 var->Type=11; /* later trigger printing variable inc/dec */
1452 }
1453 else
1454 {
1455 var->Type=12; /* later be quiet, see decompileSETVARIABLE() */
1456 if (is_postop)
1457 {
1458 pop();
1459 push(var); /* will duplicate stacktop */
1460 }
1461 }
1462 push(var);
1463 }
1464 else
1465 {
1466 if((OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER &&
1467 OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER &&
1468 OpCode(actions, n+2, maxn) == SWFACTION_SETMEMBER ) ||
1469 (OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER &&
1470 OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER &&
1471 OpCode(actions, n+2, maxn) == SWFACTION_PUSH ) ||
1472 (OpCode(actions, n-1, maxn) == SWFACTION_PUSH &&
1473 OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER) ||
1474 (OpCode(actions, n-3, maxn) == SWFACTION_GETMEMBER &&
1475 OpCode(actions, n-2, maxn) == SWFACTION_PUSH &&
1476 OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER &&
1477 OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER &&
1478 ((struct SWF_ACTIONPUSH *)&actions[n-2].SWF_ACTIONRECORD)->NumParam >= 4
1479 /* 4: a pair of get/set - FIXME: add more analysis about stack here */))
1480 { // incr/decr object variables with side effects
1481 is_postop= (OpCode(actions, n+1, maxn) == SWFACTION_SETMEMBER)?1:0;
1482 if (is_postop)
1483 var = newVar2(getString(var),dblop);
1484 else
1485 var = newVar2(dblop,getString(var));
1486 if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_PUSH)
1487 pop();
1488 if(OpCode(actions, n+1, maxn) == SWFACTION_GETMEMBER)
1489 pop();
1490
1491 pop();
1492 pop();
1493 var->Type=12; // to be quiet later in ...SETMEMBER()
1494 regs[0]=var; // FIXME: r0 perhaps a ming special
1495 push(var);
1496 push(var);
1497 push(var);
1498
1499 if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_PUSH )
1500 push(var);
1501 if (is_postop && OpCode(actions, n-1, maxn) == SWFACTION_GETMEMBER )
1502 push(var);
1503 }
1504 else
1505 {
1506 if(OpCode(actions, n-1, maxn) == SWFACTION_PUSH &&
1507 OpCode(actions, n+1, maxn) == SWFACTION_STOREREGISTER &&
1508 regs[actions[n+1].SWF_ACTIONSTOREREGISTER.Register]->Type == PUSH_VARIABLE)
1509 {
1510 var = newVar2(dblop,getString(var));
1511 if ((OpCode(actions, n+2, maxn) == SWFACTION_POP
1512 && actions[n-1].SWF_ACTIONPUSH.NumParam==1)
1513 || OpCode(actions, n+3, maxn) == SWFACTION_POP)
1514 {
1515 var->Type=11; // later print inc/dec
1516 }
1517 else
1518 {
1519 var->Type=12; // later be quiet in ..STOREREGISTER()
1520 if (actions[n-1].SWF_ACTIONPUSH.NumParam>1)
1521 {
1522 pop();
1523 push(var);
1524 }
1525 }
1526 push(var);
1527 }
1528 else // fallback to old incr/decr code
1529 { // FIXME: this is bad designed for handling side effect code
1530 INDENT // like post-incrementing a function argument etc.
1531 decompilePUSHPARAM(var,0);
1532 puts(dblop);
1533 println(";");
1534 push(var);
1535 }
1536 }
1537 }
1538 return 0;
1539 }
1540
1541 static int
decompileSTOREREGISTER(int n,SWF_ACTION * actions,int maxn)1542 decompileSTOREREGISTER(int n, SWF_ACTION *actions, int maxn)
1543 {
1544 struct SWF_ACTIONPUSHPARAM *data;
1545 OUT_BEGIN2(SWF_ACTIONSTOREREGISTER);
1546 data=peek();
1547
1548 if (!regs[sact->Register] || sact->Register==0 ) // ===internal===
1549 {
1550 regs[sact->Register] = data;
1551 }
1552 else // ===user visible level===
1553 {
1554 if ( regs[sact->Register]->Type == PUSH_VARIABLE) // V7: a named function parameter in register
1555 { // V7: a local var in register
1556 if (data->Type==12)
1557 data->Type = PUSH_VARIABLE; // do nothing, but only once
1558 else
1559 {
1560 char *l=getName(regs[sact->Register]);
1561 char *r=getName(data);
1562 if (strcmp(l,r))
1563 {
1564 INDENT
1565 if (data->Type==11)
1566 {
1567 println("%s;", r);
1568 }
1569 else
1570 {
1571 printf("%s = ",l);
1572 decompilePUSHPARAM(data,1);
1573 println(";");
1574 }
1575 }
1576 }
1577 }
1578 }
1579 return 0;
1580 }
1581
1582 static int
decompileNEWOBJECT(int n,SWF_ACTION * actions,int maxn)1583 decompileNEWOBJECT(int n, SWF_ACTION *actions, int maxn)
1584 {
1585 struct SWF_ACTIONPUSHPARAM *obj, *nparam;
1586 obj = pop();
1587 nparam=pop();
1588 push(newVar_N("new ","",getName(obj),"(", nparam->p.Integer,")"));
1589 return 0;
1590 }
1591
1592 static int
decompileNEWMETHOD(int n,SWF_ACTION * actions,int maxn)1593 decompileNEWMETHOD(int n, SWF_ACTION *actions, int maxn)
1594 {
1595 char *t;
1596 struct SWF_ACTIONPUSHPARAM *meth, *nparam, *obj;
1597 meth = pop();
1598 obj = pop();
1599 nparam=pop();
1600
1601 t=malloc(strlen( getName(obj) ) +2);
1602 strcpy(t,getName(obj));
1603 strcat(t,".");
1604
1605 push(newVar_N("new ",t,getName(meth),"(", nparam->p.Integer,")"));
1606 free (t);
1607 return 0;
1608 }
1609
1610
1611 static int
decompileGETMEMBER(int n,SWF_ACTION * actions,int maxn)1612 decompileGETMEMBER(int n, SWF_ACTION *actions, int maxn)
1613 {
1614 struct SWF_ACTIONPUSHPARAM *obj, *mem, *var;
1615 char *vname, *varname,*memname;
1616 int len;
1617
1618 mem=pop();
1619 var=pop();
1620 varname=getName(var);
1621 memname=getName(mem);
1622 #ifdef DEBUG
1623 printf("*getMember* varName %s (type=%d) memName=%s (type=%d)\n",
1624 varname,var->Type, memname,mem->Type);
1625 #endif
1626 len = strlen(varname)+strlen(memname);
1627 if (mem->Type == PUSH_INT || mem->Type == PUSH_DOUBLE || mem->Type == PUSH_VARIABLE
1628 || mem->Type == PUSH_REGISTER || mem->Type == 12 )
1629 {
1630 vname = malloc(len+3);
1631 strcpy(vname,varname);
1632 strcat(vname,"[");
1633 strcat(vname,memname);
1634 strcat(vname,"]");
1635 }
1636 else
1637 {
1638 vname = malloc(len+2);
1639 strcpy(vname,varname);
1640 strcat(vname,".");
1641 strcat(vname,memname);
1642 }
1643 obj = newVar(vname);
1644 pushvar(obj);
1645
1646 return 0;
1647 }
1648
1649
1650 static int
decompileSETMEMBER(int n,SWF_ACTION * actions,int maxn)1651 decompileSETMEMBER(int n, SWF_ACTION *actions, int maxn)
1652 {
1653 struct SWF_ACTIONPUSHPARAM *val, *var, *obj;
1654 val = pop();
1655 var = pop();
1656 obj = pop();
1657
1658 #ifdef DEBUG
1659 printf("*SETMember* varName %s (type=%d) objName=%s (type=%d)\n",getName(var),var->Type, getName(obj),obj->Type);
1660 #endif
1661 if (obj->Type == 12) /* do nothing: inline inc/dec using side effect */
1662 {
1663 obj->Type = PUSH_VARIABLE; /* ...but only once */
1664 return 0;
1665 }
1666 INDENT
1667 if (obj->Type == 11) /* simply output variable and inc/dec op */
1668 {
1669 decompilePUSHPARAM(obj,0);
1670 println(";");
1671 return 0;
1672 }
1673
1674 decompilePUSHPARAM(obj,0);
1675 if (var->Type == PUSH_INT || var->Type == PUSH_DOUBLE || var->Type == PUSH_VARIABLE
1676 || var->Type == PUSH_REGISTER || var->Type == 12 )
1677 {
1678 puts("[");
1679 }
1680 else
1681 {
1682 puts(".");
1683 if (OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER)
1684 {
1685 struct SWF_ACTIONSTOREREGISTER *sactv2 = (struct SWF_ACTIONSTOREREGISTER*)&actions[n-1];
1686 if (sactv2->Register==0)
1687 regs[0]=newVar3(getName(obj),".",getName(var)); // easter 07: some sugar for mtc et al.
1688 }
1689 }
1690 decompilePUSHPARAM(var,0);
1691 if (var->Type == PUSH_INT || var->Type == PUSH_DOUBLE || var->Type == PUSH_VARIABLE
1692 || var->Type == PUSH_REGISTER || var->Type == 12 )
1693 {
1694 puts("]");
1695 }
1696 printf(" = " );
1697
1698
1699 if ( OpCode(actions, n-1, maxn) == SWFACTION_STOREREGISTER ) {
1700 struct SWF_ACTIONSTOREREGISTER *sr =
1701 (struct SWF_ACTIONSTOREREGISTER*)&actions[n-1];
1702 printf("R%d", sr->Register);
1703 }
1704 else if (val->Type != PUSH_VARIABLE) {
1705 /* later it will be a switch{} */
1706 decompilePUSHPARAM(val,1);
1707 }
1708 else {
1709 decompilePUSHPARAM(val,0);
1710 }
1711 println(";");
1712 return 0;
1713 }
1714
1715 static int
decompileGETVARIABLE(int n,SWF_ACTION * actions,int maxn)1716 decompileGETVARIABLE(int n, SWF_ACTION *actions, int maxn)
1717 {
1718 struct SWF_ACTIONPUSHPARAM *var;
1719
1720 var = pop();
1721 #ifdef DEBUG
1722 printf("*GETVariable* varName %s (type=%d)\n",getName(var),var->Type);
1723 #endif
1724 if (var->Type == PUSH_VARIABLE)
1725 pushvar(newVar3("eval(",getName(var),")"));
1726 else
1727 pushvar(newVar(getName(var)));
1728
1729 return 0;
1730 }
1731
1732 static int
decompileSETVARIABLE(int n,SWF_ACTION * actions,int maxn,int islocalvar)1733 decompileSETVARIABLE(int n, SWF_ACTION *actions,int maxn,int islocalvar)
1734 {
1735 struct SWF_ACTIONPUSHPARAM *val, *var;
1736
1737 val = pop();
1738 var = pop();
1739 if (val->Type!=12)
1740 {
1741 INDENT
1742 }
1743 #ifdef DEBUG
1744 printf("*SETVariable* varName %s (type=%d) valName=%s (type=%d)\n",
1745 getName(var),var->Type, getName(val),val->Type);
1746 #endif
1747 if (val->Type!=12 && islocalvar)
1748 {
1749 puts("var ");
1750 }
1751 if (gIndent<0) /* the ENUM workaround: */
1752 { /* in "for (xx in yy) { }" we need xx, but nothing else */
1753 puts(getName(var));
1754 return 0;
1755 }
1756
1757
1758 switch (val->Type)
1759 {
1760 case 10:
1761 puts(getName(var)); // Variable (NEVER as string)
1762 printf(" = " );
1763 decompilePUSHPARAM(val,0);
1764 println(";");
1765 break;
1766 case 11: /* simply output variable and inc/dec op */
1767 puts(getName(val));
1768 println(";");
1769 break;
1770 case 12: /* do nothing: inline increment/decrement (using side effect only) */
1771 val->Type = PUSH_VARIABLE; // but print next time e.g. in y=++x;
1772 break;
1773 default:
1774 puts(getName(var));
1775 printf(" = " );
1776 decompilePUSHPARAM(val,1); // for certain types parameter 1 does not care
1777 println(";");
1778 }
1779 return 0;
1780 }
1781
1782 static int
decompileRETURN(int n,SWF_ACTION * actions,int maxn)1783 decompileRETURN(int n, SWF_ACTION *actions, int maxn)
1784 {
1785 struct SWF_ACTIONPUSHPARAM *var=pop();
1786 INDENT
1787 printf("return ");
1788 if (var->Type== PUSH_REGISTER && var->p.RegisterNumber==0) /* REGISTER 0 used as helper variable */
1789 puts(getName(regs[0]));
1790 else
1791 decompilePUSHPARAM(var,1);
1792 println(";");
1793 return 0;
1794 }
1795
1796 static int
decompileJUMP(int n,SWF_ACTION * actions,int maxn)1797 decompileJUMP(int n, SWF_ACTION *actions, int maxn)
1798 {
1799 int i=0,j=0;
1800 int offSave;
1801 struct SWF_ACTIONIF *sactif;
1802 OUT_BEGIN2(SWF_ACTIONJUMP);
1803 sactif=NULL;
1804
1805 if(isLogicalOp(n+1, actions, maxn) ||
1806 (OpCode(actions, n+1, maxn) == SWFACTION_PUSH && isLogicalOp(n+2, actions, maxn)))
1807 {
1808 /* Probably the start of a do {} while(), so skip it */
1809 return 0;
1810 }
1811
1812 /* Probably the end of a switch{}, so skip it */
1813 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
1814 return 1;
1815
1816 if (OpCode(actions, n+1, maxn) == SWFACTION_JUMP)
1817 {
1818 if (actions[n+1].SWF_ACTIONJUMP.BranchOffset==0)
1819 return 1;
1820 }
1821
1822 for(i=0; n + 1 + i < maxn && (actions[(n+1)+i].SWF_ACTIONRECORD.Offset < (actions[n+1].SWF_ACTIONRECORD.Offset+actions[n ].SWF_ACTIONJUMP.BranchOffset)); i++)
1823 {
1824 #if 0
1825 printf("/* for PART3 OP 0x%x */\n",actions[n+1+i].SWF_ACTIONRECORD.ActionCode);
1826 #endif
1827 ; // NOOP
1828 }
1829
1830 if (i)
1831 {
1832 for (j=0; n+j+i<maxn; j++)
1833 {
1834 #if 0
1835 printf("/* FOR part2 OP 0x%x */\n",actions[n+i+j].SWF_ACTIONRECORD.ActionCode)
1836 // at least one should push on stack
1837 #endif
1838
1839 if (OpCode(actions, n+i+j, maxn) == SWFACTION_IF)
1840 {
1841 sactif = (struct SWF_ACTIONIF *)&(actions[n+i+j]);
1842 /* chk whether last jump does lead us back to start of loop */
1843 if (sactif->Actions[sactif->numActions-1].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP
1844 && sactif->Actions[sactif->numActions-1].SWF_ACTIONJUMP.BranchOffset+
1845 sactif->Actions[sactif->numActions-1].SWF_ACTIONJUMP.Offset==
1846 actions[n].SWF_ACTIONRECORD.Offset )
1847 {
1848 break;
1849 }
1850 else
1851 sactif=NULL;
1852 }
1853 }
1854 }
1855
1856 if (sactif)
1857 {
1858 INDENT
1859 puts("while(");
1860 decompileActions(j-1, &actions[n+1+i], gIndent);
1861 puts(getName(pop()));
1862 println("){ /* original FOR loop rewritten to WHILE */");
1863 offSave=offseoloop;
1864 if (n+i+j+1<maxn) // see part2 above
1865 offseoloop=actions[n+i+j+1].SWF_ACTIONRECORD.Offset;
1866 else
1867 offseoloop=actions[n+i+j].SWF_ACTIONRECORD.Offset+5;
1868 decompileActions(sactif->numActions-1, sactif->Actions,gIndent+1);
1869 decompileActions(i, &actions[n+1], gIndent+1);
1870 offseoloop=offSave;
1871 INDENT
1872 println("};");
1873 return i+j;
1874 }
1875
1876 if (sact->BranchOffset>0)
1877 {
1878 if ( stackVal(n,actions) == 1 && n+1==maxn)
1879 { // leaving block @last op with value on stack: a return x;
1880 return decompileRETURN(n, actions,maxn);
1881 }
1882 if (n+2 < maxn && OpCode(actions, n+1, maxn) == SWFACTION_PUSH &&
1883 actions[n+2].SWF_ACTIONRECORD.Offset == actions[n+1].SWF_ACTIONRECORD.Offset+sact->BranchOffset)
1884 {
1885 return 1; // jump to short to be a 'break': but an internal jump over a push
1886 } // to do: add some control flow analysis
1887
1888 INDENT
1889
1890 if (offseoloop==actions[n].SWF_ACTIONRECORD.Offset+sact->BranchOffset+5)
1891 puts("break;" );
1892 else
1893 puts("return;" );
1894
1895 println("\t\t\t// offs_end_of_loop=%d offs_jmp_dest=%d",
1896 offseoloop, actions[n].SWF_ACTIONRECORD.Offset+sact->BranchOffset+5);
1897 }
1898 else
1899 {
1900 if (sact->BranchOffset<0)
1901 {
1902 INDENT
1903 println("continue; /*------*/");
1904 }
1905 }
1906 /* error("Unhandled JUMP"); */
1907 return 0;
1908 }
1909
1910 static int
decompileDEFINELOCAL2(int n,SWF_ACTION * actions,int maxn)1911 decompileDEFINELOCAL2(int n, SWF_ACTION *actions, int maxn)
1912 {
1913 struct SWF_ACTIONPUSHPARAM *var;
1914
1915 INDENT
1916 var = pop();
1917 puts("var ");
1918 puts(getName(var));
1919 println(";");
1920
1921 return 0;
1922 }
1923
1924 static int
decompileENUMERATE(int n,SWF_ACTION * actions,int maxn,int is_type2)1925 decompileENUMERATE(int n, SWF_ACTION *actions, int maxn, int is_type2)
1926 {
1927 int i=0;
1928 while (i < maxn && i < 5 && OpCode(actions, n+i, maxn))
1929 i++;
1930
1931 INDENT
1932 println("/* a for-var-in loop should follow below: */" );
1933 return i-1; // preserve some code for decompileIF()...
1934 } // ... and let decompileIF() do all the dirty work ;-)
1935
1936
1937 #ifdef DECOMP_SWITCH
1938
1939 // [recursive] estimate size of buffer needed for decompiling 'switch'
1940 // [ only call by decompileIF() ]
1941 //
1942 static int
countAllSwitchActions(union SWF_ACTION * actions,union SWF_ACTION * pre)1943 countAllSwitchActions (union SWF_ACTION *actions, union SWF_ACTION *pre)
1944 {
1945 int i,j=1;
1946 if (actions->SWF_ACTIONRECORD.ActionCode==SWFACTION_IF && pre->SWF_ACTIONRECORD.ActionCode==SWFACTION_STRICTEQUALS )
1947 {
1948 for(i=0; i < ((struct SWF_ACTIONIF*)actions)->numActions; i++)
1949 {
1950 j+=countAllSwitchActions(&((struct SWF_ACTIONIF*)actions)->Actions[i],pre);
1951 pre=&((struct SWF_ACTIONIF*)actions)->Actions[i];
1952 }
1953 }
1954 return j;
1955 }
1956
1957
1958 // [recursive] copy all actions in a 'flat' buffer by
1959 // unpackung all if-actions that are part of the switch operation
1960 // [ only call by decompileIF() ]
1961 //
1962 static union SWF_ACTION *
getAllSwitchActions(union SWF_ACTION * dest,union SWF_ACTION * actions,union SWF_ACTION * pre)1963 getAllSwitchActions(union SWF_ACTION *dest, union SWF_ACTION *actions, union SWF_ACTION *pre)
1964 {
1965 #ifdef DEBUGSWITCH
1966 println("SWCODE: %p %d %s %s",
1967 dest, actions->SWF_ACTIONRECORD.Offset,
1968 actionName(actions->SWF_ACTIONRECORD.ActionCode),
1969 actionName(pre->SWF_ACTIONRECORD.ActionCode));
1970 #endif
1971
1972 *dest++=*actions;
1973 if (actions->SWF_ACTIONRECORD.ActionCode==SWFACTION_IF
1974 && pre->SWF_ACTIONRECORD.ActionCode==SWFACTION_STRICTEQUALS )
1975 {
1976 int i;
1977 struct SWF_ACTIONIF *sactv2 = (struct SWF_ACTIONIF*)actions;
1978 for(i=0; i< sactv2->numActions; i++)
1979 {
1980 dest=getAllSwitchActions(dest,&sactv2->Actions[i],pre);
1981 pre=&((struct SWF_ACTIONIF*)actions)->Actions[i];
1982 }
1983 }
1984 return dest;
1985 }
1986
1987 // looks similar other decompileXXXX() but
1988 // can't called by decompileAction()
1989 // [ do only call by decompileIF() ]
1990 //
1991 static int
decompile_SWITCH(int n,SWF_ACTION * actions,int maxn,int off1end)1992 decompile_SWITCH(int n, SWF_ACTION *actions, int maxn, int off1end)
1993 {
1994 int i,j;
1995 int start; // base action index for case value and code
1996 int ccsize=0; // size of code for case value
1997 int cvsize=0; // size of case value
1998 int maxoff=0; // action offset AFTER switch
1999 int n_maxoff=0; // array index of maxoff
2000 int pend=0; // control pending output
2001 int xsize=0; // ret val
2002 int jmpsize=0; // debug helper
2003 int lastoff=0; // debug helper
2004 int n_firstactions=maxn;// array index of 1st case actions code
2005 int lastcasestart=0; // offs where last "case x:" begins
2006 char *defa="[last]"; // debug helper for early "default:"
2007 char *tmp=NULL; // helper for pending output
2008 struct strbufinfo origbuf; // pending output buffer
2009 struct _stack *StackSave;
2010 struct SWF_ACTIONPUSHPARAM *swcopy,*sw=pop();
2011 struct SWF_ACTIONPUSHPARAM *compare=pop();
2012 int offSave;
2013 for (i=0; i<n_firstactions; i++) // seek last op in 1st if
2014 {
2015 if (actions[i+1].SWF_ACTIONRECORD.Offset==off1end)
2016 {
2017 // println("found #off end first= %d",i+1);
2018 if (OpCode(actions, i, maxn) == SWFACTION_JUMP)
2019 {
2020 maxoff=actions[i].SWF_ACTIONJUMP.BranchOffset+actions[i].SWF_ACTIONJUMP.Offset+5;
2021 j=1;
2022 }
2023 else
2024 {
2025 // SanityCheck(decompile_SWITCH,0,"no jump found where expected");
2026 }
2027 break;
2028 }
2029 }
2030
2031 if (!maxoff)
2032 {
2033 for (i=maxn-1;i>=0;i--) // seek from end of block last op of switch{}
2034 {
2035 if (OpCode(actions, i, maxn) == SWFACTION_JUMP && !actions[i].SWF_ACTIONJUMP.BranchOffset)
2036 {
2037 maxoff=actions[i].SWF_ACTIONRECORD.Offset+5;
2038 j=2;
2039 break;
2040 }
2041 }
2042 }
2043
2044 for (i=0;i<maxn;i++)
2045 {
2046 if (actions[i].SWF_ACTIONRECORD.Offset>=maxoff)
2047 {
2048 n_maxoff=i; // part of block is switch
2049 break;
2050 }
2051 }
2052
2053 if (!n_maxoff)
2054 n_maxoff=maxn; // whole block is switch
2055
2056 INDENT
2057 println("switch( %s ) { // end switch at %d (index %d) / found via meth %d)",
2058 getString(sw), maxoff,n_maxoff,j);
2059
2060 push(sw);
2061 push(compare);
2062
2063 i=1;
2064 do // here we go into main loop
2065 {
2066 if((OpCode(actions, i, maxn) == SWFACTION_IF
2067 && OpCode(actions, i-1, maxn) == SWFACTION_STRICTEQUALS )
2068 ||(OpCode(actions, i, maxn) == SWFACTION_JUMP
2069 && OpCode(actions, i-1, maxn) == SWFACTION_IF) )
2070 {
2071 start=i;
2072 while (start<maxn
2073 && actions[start].SWF_ACTIONRECORD.Offset < actions[i].SWF_ACTIONRECORD.Offset+5+actions[i].SWF_ACTIONJUMP.BranchOffset
2074 ) {
2075 start++; // count actions until start of "case x:"
2076 }
2077 if (n_firstactions==maxn) // if not done store earliest "case x: "actions
2078 {
2079 n_firstactions=start; // same as array index
2080 }
2081
2082 for (ccsize=0; ccsize+start<n_maxoff; ccsize++) // count actions belonging to "case x:"
2083 {
2084 #ifdef DEBUGSWITCH
2085 println("in ccsize: ccsize=%d off=%d %s",
2086 ccsize,actions[ccsize+start].SWF_ACTIONRECORD.Offset,
2087 actionName(actions[ccsize+start].SWF_ACTIONRECORD.ActionCode));
2088 #endif
2089 if (OpCode(actions, ccsize+start, maxn) == SWFACTION_JUMP)
2090 {
2091 if (maxoff == actions[ccsize+start].SWF_ACTIONJUMP.Offset+5 + actions[ccsize+start].SWF_ACTIONJUMP.BranchOffset)
2092 {
2093 jmpsize= actions[ccsize+start].SWF_ACTIONJUMP.BranchOffset;
2094 lastoff= actions[ccsize+start].SWF_ACTIONJUMP.Offset;
2095 ccsize++; // the jmp itself
2096 break;
2097 }
2098 }
2099 }
2100
2101 #if USE_LIB
2102 if (tmp && (start!=pend)) // output pending buffer if neccessary
2103 {
2104 puts(tmp);
2105 }
2106
2107 if (tmp)
2108 {
2109 free(tmp);
2110 tmp=NULL;
2111 }
2112 pend=start;
2113 #endif
2114 if (actions[i].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP)
2115 {
2116 if (ccsize<=1)
2117 break; // ready
2118 else
2119 {
2120 INDENT
2121 if (actions[start].SWF_ACTIONRECORD.Offset>lastcasestart)
2122 xsize+=ccsize;
2123 else
2124 defa="[early]";
2125 println("default: // at %d %s start=%d ccsize=%d",
2126 actions[start].SWF_ACTIONRECORD.Offset,defa, start, ccsize);
2127 }
2128 }
2129 else
2130 {
2131 INDENT
2132 xsize=ccsize;
2133 lastcasestart=actions[start].SWF_ACTIONRECORD.Offset;
2134 println("case %s: // at %d start=%d ccsize=%d jmp=%d+%d+5",
2135 getString(pop()), lastcasestart, start, ccsize, lastoff,jmpsize);
2136 swcopy=pop();
2137 // SanityCheck(decompile_SWITCH,!strcmp(getName(swcopy),getName(sw)),"sw0 != sw");
2138 }
2139
2140 #if USE_LIB
2141 origbuf=setTempString(); // switch to temp buffer
2142 #endif
2143 StackSave=Stack;
2144 offSave=offseoloop;
2145 offseoloop=maxoff;
2146 decompileActions( ccsize, &actions[start],gIndent+1);
2147 offseoloop=offSave;
2148 Stack=StackSave;
2149 #if USE_LIB
2150 tmp=switchToOrigString(origbuf);
2151 #endif
2152
2153 if (actions[i].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP) // after "default:"
2154 {
2155 break; // ready
2156 }
2157 else
2158 {
2159 if (actions[i+1].SWF_ACTIONRECORD.ActionCode!=SWFACTION_JUMP) // not before "default:" or end
2160 {
2161 i++; // the 'if' itself
2162 cvsize=0;
2163 while (i+cvsize < n_firstactions
2164 && actions[i+cvsize].SWF_ACTIONRECORD.ActionCode!=SWFACTION_STRICTEQUALS)
2165 {
2166 #ifdef DEBUGSWITCH
2167 println("in cvsize=%d %d %s",
2168 cvsize, actions[i+cvsize].SWF_ACTIONRECORD.Offset,
2169 actionName(actions[i+cvsize].SWF_ACTIONRECORD.ActionCode));
2170 #endif
2171 cvsize++; // count "case X:" code size
2172 }
2173 decompileActions( cvsize, &actions[i],gIndent+1); // at least one push on stack expected
2174 i+=cvsize;
2175 }
2176 }
2177 }
2178 } while (++i < n_firstactions);
2179
2180 #if USE_LIB
2181 if (tmp)
2182 {
2183 puts(tmp); // print last pending output
2184 free(tmp);
2185 }
2186 #endif
2187 INDENT
2188 println("} // switch ret value =%d",xsize);
2189 return xsize;
2190 }
2191 #endif
2192
2193 static int
decompileIF(int n,SWF_ACTION * actions,int maxn)2194 decompileIF(int n, SWF_ACTION *actions, int maxn)
2195 {
2196 int offSave;
2197 int j,i=0;
2198 struct strbufinfo origbuf;
2199 OUT_BEGIN2(SWF_ACTIONIF);
2200 /*
2201 * IF is used in various way to implement different types
2202 * of loops. We try to detect these different types of loops
2203 * here.
2204 */
2205
2206 #ifdef STATEMENT_CLASS
2207 if((OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT) &&
2208 (OpCode(actions, n-2, maxn) == SWFACTION_LOGICALNOT) &&
2209 (OpCode(actions, n-3, maxn) == SWFACTION_GETVARIABLE) &&
2210 (OpCode(actions, n-4, maxn) == SWFACTION_PUSH) )
2211 {
2212 /* It's really a class definition */
2213 INDENT
2214 puts("class ");
2215 decompilePUSHPARAM(newVar(getName(pop())),0);
2216 println(" {" );
2217 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2218 INDENT
2219 println("}");
2220 return 0;
2221 }
2222
2223 if(
2224 (OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT) &&
2225 (OpCode(actions, n-2, maxn) == SWFACTION_LOGICALNOT) &&
2226 (OpCode(actions, n-3, maxn) == SWFACTION_GETMEMBER) &&
2227 (OpCode(actions, n-4, maxn) == SWFACTION_PUSH) )
2228 {
2229 /* It's really a class definition */
2230 INDENT
2231 println(" {");
2232 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2233 INDENT
2234 println("}");
2235 return 0;
2236 }
2237 #endif
2238 /*
2239 * do {} while() loops have a JUMP at the end of the if clause
2240 * that points to a JUMP above the IF statement.
2241 */
2242 if(n && isLogicalOp(n-1, actions, maxn) &&
2243 (sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2244 ( (sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.Offset +
2245 sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset) < actions[n].SWF_ACTIONRECORD.Offset) &&
2246 isLogicalOp(sact->numActions-2, sact->Actions, maxn) )
2247 {
2248 INDENT
2249 println("do {");
2250 offSave=offseoloop;
2251 offseoloop=actions[n].SWF_ACTIONRECORD.Offset+5;
2252 decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2253 offseoloop=offSave;
2254 INDENT
2255 puts("while( ");
2256 puts(getName(pop()));
2257 puts(");");
2258 return 0;
2259 }
2260
2261 /* ak,2006
2262 * lots of "do {} while()" have simply a CONDITIONED JUMP back at the end of the loop
2263 */
2264 if( actions[n].SWF_ACTIONJUMP.BranchOffset < 0 )
2265 {
2266 INDENT
2267 println("do { /* 2nd type */ ");
2268 offSave=offseoloop;
2269 offseoloop=actions[n ].SWF_ACTIONRECORD.Offset+5;
2270 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2271 offseoloop=offSave;
2272 INDENT
2273 puts("} while( ");
2274 puts(getName(pop()));
2275 println(");");
2276 return 0;
2277 }
2278
2279 j=0;
2280 while (OpCode(actions, n-j, maxn) != SWFACTION_ENUMERATE &&
2281 OpCode(actions, n-j, maxn) != SWFACTION_ENUMERATE2 && j<n && j<5)
2282 {
2283 j++; // check for a pending ENUMERATE
2284 }
2285
2286 if ((OpCode(actions, n-j, maxn) == SWFACTION_ENUMERATE ||
2287 OpCode(actions, n-j, maxn) == SWFACTION_ENUMERATE2 ) &&
2288 OpCode(actions, n-j+1, maxn) == SWFACTION_STOREREGISTER )
2289 {
2290 struct SWF_ACTIONPUSHPARAM *var;
2291 int x;
2292 var = pop();
2293 INDENT
2294 puts("for ( ");
2295 // check for an usual special case w register Rx
2296 if (sact->Actions[1].SWF_ACTIONRECORD.ActionCode == SWFACTION_STOREREGISTER)
2297 {
2298 struct SWF_ACTIONSTOREREGISTER *sactv2 = (struct SWF_ACTIONSTOREREGISTER*)&sact->Actions[1];
2299 puts("var ");
2300 puts(getName(regs[sactv2->Register]));
2301 x=3;
2302 }
2303 else
2304 {
2305 decompileActions( 2 , sact->Actions,-1); /* -1 == the ENUM workaround */
2306 x=2;
2307 }
2308 puts(" in ");
2309 puts(getName(var));
2310 println(" ) {");
2311 if(n+1 >= maxn)
2312 {
2313 SWF_warn("Warning: %s:%i: something is wrong here\n", __FILE__, __LINE__);
2314 }
2315 else
2316 {
2317 offSave=offseoloop;
2318 offseoloop=actions[n+1].SWF_ACTIONRECORD.Offset;
2319 decompileActions(sact->numActions-1-x, &sact->Actions[x],gIndent+1);
2320 offseoloop=offSave;
2321 }
2322 INDENT
2323 println("}");
2324 return 0;
2325 }
2326
2327 /*
2328 * while() loops have a JUMP at the end of the if clause that jumps backwards
2329 * But also "continue" statements could jump backwards.
2330 */
2331
2332 if( isLogicalOp(n-1, actions, maxn) &&
2333 ( (sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2334 sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset < 0) )
2335 {
2336 if(0) dumpRegs();
2337 INDENT
2338 /* if on a level >0 we can check for any outer loop
2339 To do: get the level on a better way than using gIndent */
2340 if (gIndent
2341 && actions[maxn-1].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP
2342 && actions[maxn-1].SWF_ACTIONJUMP.Offset+actions[maxn].SWF_ACTIONJUMP.BranchOffset==
2343 sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.Offset+sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset)
2344 {
2345 /* this jump leads from a block to start of a loop on outer block:
2346 it is an 'if' later followed by last action 'continue' */
2347 SWF_warn("WARNING: this might be wrong (%s:%i)\n", __FILE__, __LINE__);
2348 puts("if ( ");
2349 puts(getName(pop()));
2350 println(" ) {");
2351 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2352 }
2353 else /* while(){} as usual */
2354 {
2355 puts("while( ");
2356 puts(getName(pop()));
2357 println(" ) {");
2358 offSave=offseoloop;
2359 offseoloop=actions[n+1].SWF_ACTIONRECORD.Offset;
2360 decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2361 offseoloop=offSave;
2362 }
2363 INDENT
2364 println("}");
2365 return 0;
2366 }
2367 { // WTF ???
2368 #define SOME_IF_DEBUG 0 /* coders only */
2369 int has_else_or_break= ((sact->Actions[sact->numActions-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_JUMP) &&
2370 (sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset > 0 )) ? 1:0;
2371 int has_lognot=(actions[n-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_LOGICALNOT) ? 1:0;
2372 int else_action_cnt=0,is_logor=0,is_logand=0,sbi,sbe;
2373
2374 /* before emitting any "if"/"else" characters let's check
2375 for a ternary operation cond?a:b
2376 */
2377 if (has_else_or_break)
2378 {
2379 int limit=actions[n+1].SWF_ACTIONRECORD.Offset + sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset;
2380 /* Count the number of action records that are part of
2381 * the else clause, and then decompile only that many.
2382 */
2383 for(else_action_cnt=0;
2384 else_action_cnt+n+1<maxn && actions[n+1+else_action_cnt].SWF_ACTIONRECORD.Offset < limit;
2385 else_action_cnt++)
2386 {
2387 #if SOME_IF_DEBUG
2388 println("/* ELSE OP 0x%x at %d*/",actions[n+1+else_action_cnt].SWF_ACTIONRECORD.ActionCode,
2389 actions[n+1+else_action_cnt].SWF_ACTIONRECORD.Offset)
2390 #endif
2391 ;
2392 }
2393 }
2394 i=else_action_cnt; // =return value
2395 sbi=stackVal (sact->numActions-1,sact->Actions);
2396 sbe=stackVal (else_action_cnt,&actions[n+1]);
2397
2398 // check against opcodes we do not expect in a ternary operation
2399 if (sbi==1 && sbe==1)
2400 {
2401 for (j=0;j<sact->numActions-1;j++)
2402 {
2403 if (sact->Actions[j].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP) // perhaps more ops
2404 {
2405 sbi=i=has_else_or_break=0;
2406 break;
2407 }
2408 }
2409 for (j=0;j<else_action_cnt;j++)
2410 {
2411 if (actions[n+j].SWF_ACTIONRECORD.ActionCode==SWFACTION_JUMP) // perhaps more ops
2412 {
2413 sbe=i=has_else_or_break=0;
2414 break;
2415 }
2416 }
2417 }
2418 #if SOME_IF_DEBUG
2419 printf("sbi=%d sbe=%d\n", sbi,sbe);
2420 #endif
2421 if (sbi==1 && sbe==1)
2422 {
2423 #if SOME_IF_DEBUG
2424 println("/* ****Found ternary ternary operation \"cond ? a : b\" **** */");
2425 printf("If Actions=%d\n",sact->numActions-1);
2426 printf("Else Actions=%d\n",else_action_cnt);
2427 #endif
2428 struct strbufinfo origbuf;
2429 #if USE_LIB
2430 origbuf=setTempString(); /* switch to a temporary string buffer */
2431 #endif
2432 puts("(");
2433 puts(getName(pop()));
2434 puts(" ? ");
2435 decompileActions(else_action_cnt , &actions[n+1],0);
2436 puts(getName(pop()));
2437 puts(" : ");
2438 decompileActions(sact->numActions-1, sact->Actions,0);
2439 puts(getName(pop()));
2440 puts(")");
2441 #if USE_LIB
2442 push (newVar(dcgetstr())); /* push for later assignment */
2443 setOrigString(origbuf); /* switch back to orig buffer */
2444 #else
2445 push (newVar("/* ternary op: see code above */"));
2446 #endif
2447 }
2448 else
2449 {
2450 /* at this point let's check for conditioned jumps that are NOT 'if':
2451 currently that is code for the locical operations && and ||
2452 */
2453 if (OpCode(actions, n-1, maxn) == SWFACTION_PUSHDUP)
2454 is_logor=1;
2455
2456 if (OpCode(actions, n-2, maxn)== SWFACTION_PUSHDUP
2457 && OpCode(actions, n-1, maxn) == SWFACTION_LOGICALNOT)
2458 {
2459 is_logand=1;
2460 }
2461
2462 if (is_logor || is_logand)
2463 {
2464 #if SOME_IF_DEBUG
2465 println("");
2466 println("/* detected LOGICAL %s: %d actions*/", is_logor ? "OR":"AND",sact->numActions);
2467 #endif
2468 #if USE_LIB
2469 origbuf=setTempString(); /* switch to a temporary string buffer */
2470 #endif
2471
2472 puts(getName(pop())); /* get left side of logical or */
2473 puts(is_logor ? " || ":" && ");
2474 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2475 puts(getName(pop())); /* get right side of logical or */
2476 #if USE_LIB
2477 push(newVar(dcgetstr()));
2478 setOrigString(origbuf); /* switch back to orig buffer */
2479 #else
2480 push (newVar("/* see logical term lines above */"));
2481 #endif
2482 return 0;
2483 }
2484 #ifdef DECOMP_SWITCH
2485 if ( OpCode(actions, n-1, maxn) == SWFACTION_STRICTEQUALS
2486 && check_switch(sact->Actions[0].SWF_ACTIONRECORD.ActionCode) )
2487 {
2488 union SWF_ACTION *xact,*xact0;
2489 for(i=n-1,j=0; i< maxn ;i++) // n-1 due adding 1st SWFACTION_STRICTEQUALS in buffer
2490 {
2491 j+=countAllSwitchActions(&actions[i],&actions[i-1]); // FIRST count size of code
2492 }
2493 xact0=xact = (union SWF_ACTION *) calloc (j,sizeof (SWF_ACTION));
2494 INDENT
2495 println("// checking %d actions for switch(){}",j);
2496 for(i=n-1; i< maxn ;i++)
2497 {
2498 xact=getAllSwitchActions(xact,&actions[i],&actions[i-1]); // SECOND copy into xtra buffer
2499 }
2500 j=decompile_SWITCH(0,xact0,j,actions[n+1].SWF_ACTIONRECORD.Offset); // THIRD decompile xtra buffer
2501 free(xact0);
2502 return j;
2503 }
2504 #endif
2505 /* it seems we have a found the REAL 'if' statement,
2506 so it's right time to print the "if" just NOW!
2507 */
2508 INDENT
2509 puts("if( ");
2510 puts(getName(pop())); /* the condition itself */
2511 println(" ) {");
2512 if ( has_else_or_break )
2513 {
2514 int limit=actions[n+1].SWF_ACTIONRECORD.Offset + sact->Actions[sact->numActions-1].SWF_ACTIONJUMP.BranchOffset;
2515 // limit == dest of jmp == offset next op after 'if' + jumpdist at end of 'if'
2516 int lastopsize=actions[maxn-1].SWF_ACTIONRECORD.Length;
2517 if (actions[maxn-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_IF)
2518 lastopsize+=actions[maxn-1].SWF_ACTIONIF.BranchOffset + 3; /* +3 see parser.c: "Action + Length bytes not included in the length" */
2519
2520 if (offseoloop
2521 && ! (has_lognot
2522 && OpCode(actions, n-2, maxn) == SWFACTION_EQUALS2
2523 && OpCode(actions, n-3, maxn) == SWFACTION_PUSH
2524 && OpCode(actions, n-4, maxn) == SWFACTION_PUSHDUP)
2525 && limit > actions[maxn-1].SWF_ACTIONRECORD.Offset+lastopsize)
2526 {
2527 /* the jump leads outside this limit, so it is a simple 'if'
2528 with a 'break' or 'return' at the end, and there is NO else clause.
2529 */
2530 INDENT
2531 println("// offs_endjump_dest=%d offs_after_blk %d",
2532 limit, actions[maxn-1].SWF_ACTIONRECORD.Offset+lastopsize);
2533 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2534 i=0; /* found break/return but no else and thus return 0 */
2535 }
2536 else
2537 {
2538 /* There is an else clause also!
2539 (action counter is set above)
2540 */
2541 struct _stack *StackSave=Stack; /* decompile if and else blocks at same stack base */
2542 if (has_lognot)
2543 {
2544 decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2545 INDENT
2546 println("} else {");
2547 }
2548 Stack=StackSave;
2549 decompileActions(else_action_cnt , &actions[n+1],gIndent+1);
2550 if (!has_lognot) /* the missing if-part just NOW */
2551 {
2552 Stack=StackSave;
2553 INDENT
2554 println ("} else {" );
2555 decompileActions(sact->numActions-1, sact->Actions,gIndent+1);
2556 }
2557 }
2558 }
2559 else
2560 {
2561 /* It's a simple if() {} */
2562 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2563 }
2564 INDENT
2565 println("}");
2566 } // WTF ???
2567 return i;
2568 }
2569 return 0;
2570 }
2571
2572 static int
decompileINITOBJECT(int n,SWF_ACTION * actions,int maxn)2573 decompileINITOBJECT(int n, SWF_ACTION *actions, int maxn)
2574 {
2575 struct SWF_ACTIONPUSHPARAM *nparam;
2576 nparam=pop();
2577 push(newVar_N2("","","","{", nparam->p.Integer,"}"));
2578 return 0;
2579 }
2580
2581 static int
decompileWITH(int n,SWF_ACTION * actions,int maxn)2582 decompileWITH(int n, SWF_ACTION *actions, int maxn)
2583 {
2584 OUT_BEGIN2(SWF_ACTIONWITH);
2585
2586 INDENT
2587 puts("with(");
2588 decompilePUSHPARAM(pop(),0);
2589 puts(")");
2590 println(" {" );
2591 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2592 INDENT
2593 println("}" );
2594
2595 return 1;
2596 }
2597
2598 static int
decompileTRY(int n,SWF_ACTION * actions,int maxn)2599 decompileTRY(int n, SWF_ACTION *actions, int maxn)
2600 {
2601 #ifdef DEBUG
2602 struct _stack *StackSave=Stack;
2603 #endif
2604 OUT_BEGIN2(SWF_ACTIONTRY);
2605 INDENT
2606 println("try {");
2607 decompileActions(sact->numTryActs, sact->TryActs,gIndent+1);
2608 INDENT
2609 println("}");
2610 #ifdef DEBUG
2611 if (Stack!=StackSave)
2612 {
2613 println("/* Stack problem in try{} code above */");
2614 Stack=StackSave;
2615 }
2616 #endif
2617 if (sact->numCatchActs)
2618 {
2619 struct SWF_ACTIONPUSHPARAM *rsave=NULL;
2620 INDENT
2621 if( ! sact->CatchInRegisterFlag)
2622 println("catch (%s) {",sact->CatchName);
2623 else
2624 {
2625 char *t=malloc(5); /* Rddd */
2626 sprintf(t,"R%d", sact->CatchRegister );
2627 rsave=regs[sact->CatchRegister];
2628 regs[sact->CatchRegister] = newVar(t);
2629 println("catch (%s) {",t);
2630 }
2631 decompileActions(sact->numCatchActs, sact->CatchActs,gIndent+1);
2632 INDENT
2633 println("}");
2634 if (rsave)
2635 regs[sact->CatchRegister]=rsave;
2636 #ifdef DEBUG
2637 if (Stack!=StackSave)
2638 {
2639 println("/* Stack problem in catch{} code above */");
2640 Stack=StackSave;
2641 }
2642 #endif
2643 }
2644 if (sact->numFinallyActs)
2645 {
2646 INDENT
2647 println("finally () {");
2648 decompileActions(sact->numFinallyActs, sact->FinallyActs,gIndent+1);
2649 INDENT
2650 println("}");
2651 #ifdef DEBUG
2652 if (Stack!=StackSave)
2653 {
2654 println("/* Stack problem in finally{} code above */");
2655 Stack=StackSave;
2656 }
2657 #endif
2658 }
2659 return 0;
2660 }
2661
2662
2663 static int
decompileDEFINEFUNCTION(int n,SWF_ACTION * actions,int maxn,int is_type2)2664 decompileDEFINEFUNCTION(int n, SWF_ACTION *actions, int maxn, int is_type2)
2665 {
2666 int i,j,k,m,r;
2667 struct SWF_ACTIONPUSHPARAM *myregs[ 256 ];
2668 struct _stack *StackSave;
2669 struct SWF_ACTIONDEFINEFUNCTION2 *sactv2;
2670 struct strbufinfo origbuf;
2671 OUT_BEGIN2(SWF_ACTIONDEFINEFUNCTION);
2672 sactv2 = (struct SWF_ACTIONDEFINEFUNCTION2*)sact;
2673
2674 #ifdef DEBUG
2675 if(n+1 < maxn)
2676 {
2677 println("/* function followed by OP %x */",
2678 OpCode(actions, n+1, maxn));
2679 }
2680 #endif
2681 #if USE_LIB
2682 if (isStoreOp(n+1, actions,maxn)
2683 || ( *sact->FunctionName==0 && !is_type2 )
2684 || (*sactv2->FunctionName==0 && is_type2 ))
2685 {
2686 origbuf=setTempString(); /* switch to a temporary string buffer */
2687 }
2688 #endif
2689 puts("function ");
2690 if (is_type2)
2691 {
2692 for(j=1;j<sactv2->RegisterCount;j++)
2693 {
2694 myregs[j]=regs[j];
2695 regs[j]=NULL;
2696 }
2697 r=1;
2698 if (sactv2->PreloadThisFlag) regs[r++]=newVar("this");
2699 if (sactv2->PreloadArgumentsFlag) regs[r++]=newVar("arguments");
2700 if (sactv2->PreloadSuperFlag) regs[r++]=newVar("super");
2701 if (sactv2->PreloadRootFlag) regs[r++]=newVar("root");
2702 if (sactv2->PreloadParentFlag) regs[r++]=newVar("parent");
2703 if (sactv2->PreloadGlobalFlag) regs[r++]=newVar("global");
2704
2705 puts(sactv2->FunctionName);
2706 puts("(");
2707
2708 for(i=0,m=0;i<sactv2->NumParams;i++)
2709 {
2710 puts(sactv2->Params[i].ParamName);
2711 if ( sactv2->Params[i].Register)
2712 {
2713 printf(" /*=R%d*/ ",sactv2->Params[i].Register);
2714 regs[sactv2->Params[i].Register] = newVar(sactv2->Params[i].ParamName);
2715 m++; // do not count 'void' etc
2716 }
2717 if( sactv2->NumParams > i+1 ) puts(",");
2718 }
2719 println(") {" );
2720 if (r+m < sactv2->RegisterCount)
2721 {
2722 INDENT
2723 puts(" var ");
2724 }
2725 for(k=r;r<sactv2->RegisterCount;r++)
2726 {
2727 if (!regs[r])
2728 {
2729 char *t=malloc(5); /* Rddd */
2730 sprintf(t,"R%d", r );
2731 puts (t);
2732 if (k++ < sactv2->RegisterCount- m -1)
2733 puts(", ");
2734 else
2735 println(";" );
2736 regs[r]=newVar(t);
2737 }
2738 }
2739 StackSave=Stack;
2740 decompileActions(sactv2->numActions, sactv2->Actions,gIndent+1);
2741 #ifdef DEBUG
2742 if (Stack!=StackSave)
2743 {
2744 println("/* Stack problem in function code above */");
2745 }
2746 #endif
2747 Stack=StackSave;
2748 for(j=1;j<sactv2->RegisterCount;j++)
2749 regs[j]=myregs[j];
2750 }
2751 else
2752 {
2753 puts(sact->FunctionName);
2754 puts("(");
2755 for(i=0;i<sact->NumParams;i++) {
2756 puts(sact->Params[i]);
2757 if( sact->NumParams > i+1 ) puts(",");
2758 }
2759 println(") {" );
2760 k=0;
2761 if (sact->Actions[0].SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH)
2762 {
2763 struct SWF_ACTIONPUSH *sactPush=(struct SWF_ACTIONPUSH *)sact->Actions;
2764 for(i=0;i<sactPush->NumParam;i++)
2765 {
2766 if ((&(sactPush->Params[i]))->Type == PUSH_REGISTER)
2767 k++; /* REGISTER */
2768 }
2769 if (k)
2770 {
2771 INDENT
2772 puts(" var ");
2773 for(i=1;i<=k;i++)
2774 {
2775 char *t=malloc(5); /* Rddd */
2776 sprintf(t,"R%d", i );
2777 puts (t);
2778 if (i < k)
2779 puts(", ");
2780 else
2781 println(";" );
2782 regs[i]=newVar(t);
2783 }
2784 }
2785 }
2786 for(j=1;j<=k;j++)
2787 myregs[j]=regs[j];
2788 StackSave=Stack;
2789 decompileActions(sact->numActions, sact->Actions,gIndent+1);
2790 #ifdef DEBUG
2791 if (Stack!=StackSave)
2792 {
2793 println("/* Stack problem in function code above */");
2794 }
2795 #endif
2796 Stack=StackSave;
2797 for(j=1;j<=k;j++)
2798 regs[j]=myregs[j];
2799 }
2800 INDENT
2801 if (isStoreOp(n+1, actions,maxn)
2802 || ( *sact->FunctionName==0 && !is_type2 )
2803 || (*sactv2->FunctionName==0 && is_type2 ))
2804 {
2805 puts("}");
2806 #if USE_LIB
2807 push (newVar(dcgetstr())); /* push func body for later assignment */
2808 setOrigString(origbuf); /* switch back to orig buffer */
2809 #else
2810 push (newVar("/* see function code above */")); /* workaround only if LIB is not in use */
2811 #endif
2812 }
2813 else
2814 println("}" );
2815 return 0;
2816 }
2817
2818 static int
decompileCALLMETHOD(int n,SWF_ACTION * actions,int maxn)2819 decompileCALLMETHOD(int n, SWF_ACTION *actions, int maxn)
2820 {
2821 struct SWF_ACTIONPUSHPARAM *meth, *obj, *nparam;
2822 meth=pop();
2823 obj=pop();
2824 nparam=pop();
2825 if (nparam->p.Integer>25)
2826 {
2827 INDENT
2828 println("// Problem getting method arguments (%d ignored) below:",
2829 nparam->p.Integer);
2830 nparam->p.Integer=0;
2831 }
2832 #ifdef DEBUG
2833 printf("*CALLMethod* objName=%s (type=%d) methName=%s (type=%d)\n",
2834 getName(obj), obj->Type, getName(meth), meth->Type);
2835 #endif
2836 if (meth->Type == PUSH_UNDEF) /* just undefined, like in "super();" */
2837 push(newVar_N(getName(obj),"","","(", nparam->p.Integer,")"));
2838 else
2839 {
2840 if (meth->Type == PUSH_INT || meth->Type == PUSH_DOUBLE || meth->Type == PUSH_VARIABLE
2841 || meth->Type == PUSH_REGISTER || meth->Type == 12 )
2842 {
2843 push(newVar_N(getName(obj),"[",getName(meth),"](", nparam->p.Integer,")"));
2844 }
2845 else
2846 push(newVar_N(getName(obj),".",getName(meth),"(", nparam->p.Integer,")"));
2847 }
2848 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2849 {
2850 /* call method and throw away any result */
2851 INDENT
2852 puts(getName(pop()));
2853 println(";" );
2854 return 1;
2855 }
2856 return 0;
2857 }
2858
2859 static int
decompileCALLFUNCTION(int n,SWF_ACTION * actions,int maxn)2860 decompileCALLFUNCTION(int n, SWF_ACTION *actions, int maxn)
2861 {
2862 struct SWF_ACTIONPUSHPARAM *meth, *nparam;
2863
2864 SanityCheck(SWF_CALLMETHOD,
2865 actions[n-1].SWF_ACTIONRECORD.ActionCode == SWFACTION_PUSH,
2866 "CALLMETHOD not preceeded by PUSH")
2867
2868 meth=pop();
2869 nparam=pop();
2870 if (nparam->p.Integer>25)
2871 {
2872 INDENT
2873 println("// Problem getting function arguments (%d ignored) below:",
2874 nparam->p.Integer);
2875 nparam->p.Integer=0;
2876 }
2877 push(newVar_N("","",getName(meth),"(", nparam->p.Integer,")"));
2878 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2879 {
2880 /* call function and throw away any result */
2881 INDENT
2882 puts(getName(pop()));
2883 println(";" );
2884 return 1;
2885 }
2886 return 0;
2887 }
2888
2889 static int
decompile_Null_ArgBuiltInFunctionCall(int n,SWF_ACTION * actions,int maxn,char * functionname)2890 decompile_Null_ArgBuiltInFunctionCall(int n, SWF_ACTION *actions, int maxn, char *functionname)
2891 {
2892 INDENT
2893 puts(functionname); // only used for cases w/o return value
2894 println("();" );
2895 return 0;
2896 }
2897
2898 static int
decompileSingleArgBuiltInFunctionCall(int n,SWF_ACTION * actions,int maxn,char * functionname)2899 decompileSingleArgBuiltInFunctionCall(int n, SWF_ACTION *actions, int maxn, char *functionname)
2900 {
2901 push(newVar_N("","",functionname,"(", 1,")"));
2902 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2903 {
2904 /* call function and throw away any result */
2905 INDENT
2906 puts(getName(pop()));
2907 println(";" );
2908 return 1;
2909 }
2910 return 0;
2911 }
2912
2913 static int
decompileSTARTDRAG(int n,SWF_ACTION * actions,int maxn)2914 decompileSTARTDRAG(int n, SWF_ACTION *actions, int maxn)
2915 {
2916 INDENT
2917 puts("startDrag(");
2918 decompilePUSHPARAM(pop(),1);
2919 puts(",");
2920 decompilePUSHPARAM(pop(),0);
2921 puts(",");
2922 decompilePUSHPARAM(pop(),0); //
2923 println(");" );
2924 return 0;
2925 }
2926
2927 static int
decompileSUBSTRING(int n,SWF_ACTION * actions,int maxn)2928 decompileSUBSTRING(int n, SWF_ACTION *actions,int maxn)
2929 {
2930 push(newVar_N("","","substr","(", 3,")"));
2931 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2932 {
2933 /* call function and throw away any result */
2934 INDENT
2935 puts(getName(pop()));
2936 println(";" );
2937 return 1;
2938 }
2939 return 0;
2940 }
2941
2942 static int
decompileSTRINGCONCAT(int n,SWF_ACTION * actions,int maxn)2943 decompileSTRINGCONCAT(int n, SWF_ACTION *actions, int maxn)
2944 {
2945 push(newVar_N("","","concat","(", 2,")"));
2946 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
2947 {
2948 /* call function and throw away any result */
2949 INDENT
2950 puts(getName(pop()));
2951 println(";" );
2952 return 1;
2953 }
2954 return 0;
2955 }
2956
2957 static int
decompileTHROW(int n,SWF_ACTION * actions,int maxn)2958 decompileTHROW(int n, SWF_ACTION *actions, int maxn)
2959 {
2960 INDENT
2961 puts("throw ");
2962 puts(getName(pop()));
2963 println(";");
2964 return 0;
2965 }
2966
2967 static int
decompileREMOVECLIP(int n,SWF_ACTION * actions,int maxn)2968 decompileREMOVECLIP(int n, SWF_ACTION *actions, int maxn)
2969 {
2970 INDENT
2971 puts("removeMovieClip(");
2972 puts(getName(pop()));
2973 println(");" );
2974 return 0;
2975 }
2976
2977 static int
decompileDUPLICATECLIP(int n,SWF_ACTION * actions,int maxn)2978 decompileDUPLICATECLIP(int n, SWF_ACTION *actions, int maxn)
2979 {
2980 struct SWF_ACTIONPUSHPARAM *a, *b;
2981
2982 INDENT
2983 a = pop();
2984 b = pop();
2985
2986 puts("duplicateMovieClip(");
2987 puts(getString(pop()));
2988 puts(",");
2989 puts(getString(b));
2990 puts(",");
2991 puts(getString(a));
2992 println(");" );
2993 return 0;
2994 }
2995
2996 static int
decompileINITARRAY(int n,SWF_ACTION * actions,int maxn)2997 decompileINITARRAY(int n, SWF_ACTION *actions, int maxn)
2998 {
2999 struct SWF_ACTIONPUSHPARAM *nparam;
3000 nparam=pop();
3001 push(newVar_N("","","","[", nparam->p.Integer,"]"));
3002 return 0;
3003 }
3004
3005 static int
decompileEXTENDS(int n,SWF_ACTION * actions,int maxn)3006 decompileEXTENDS(int n, SWF_ACTION *actions, int maxn)
3007 {
3008 struct SWF_ACTIONPUSHPARAM *baseclass;
3009
3010 baseclass=pop();
3011 #if 0
3012 /* It's useless to open a class body when there's no
3013 * other code supporting it. */
3014 printf("class ");
3015 puts(getName(pop()));
3016 printf(" extends ");
3017 puts(getName(baseclass));
3018 println(" {" );
3019 #else
3020 /* We'll do it with asm{} */
3021 println("asm {");
3022 println(" push '%s'", getName(pop()));
3023 println(" getvariable");
3024 println(" push '%s'", getName(baseclass));
3025 println(" getvariable");
3026 println(" extends");
3027 println("};");
3028 #endif
3029
3030 return 0;
3031 }
3032
3033 static int
decompileDELETE(int n,SWF_ACTION * actions,int maxn,int is_type2)3034 decompileDELETE(int n, SWF_ACTION *actions, int maxn, int is_type2)
3035 {
3036 if (is_type2)
3037 push(newVar3("delete(",getName(pop()),")"));
3038 else
3039 push(newVar_N("delete(",getName(pop()),".",getName(pop()), 0,")"));
3040
3041
3042 if (OpCode(actions, n+1, maxn) == SWFACTION_POP)
3043 {
3044 /* call delete() with its args and throw away any result */
3045 INDENT
3046 puts(getName(pop()));
3047 println(";" );
3048 return 1;
3049 }
3050 return 0;
3051 }
3052
3053 static int
decompileSETTARGET(int n,SWF_ACTION * actions,int maxn,int is_type2)3054 decompileSETTARGET(int n, SWF_ACTION *actions, int maxn, int is_type2)
3055 {
3056 int action_cnt=0;
3057 char *name;
3058 OUT_BEGIN2(SWF_ACTIONSETTARGET);
3059 name = is_type2 ? getString(pop()) : sact->TargetName;
3060 if (*name)
3061 {
3062 INDENT
3063 println("tellTarget('%s') {" ,name);
3064 while(action_cnt+n<maxn)
3065 {
3066 if (OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_SETTARGET
3067 || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_SETTARGET2
3068 || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_DEFINEFUNCTION
3069 || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_DEFINEFUNCTION2
3070 || OpCode(actions, n+1+action_cnt, maxn)==SWFACTION_END)
3071 {
3072 break;
3073 }
3074 action_cnt++;
3075 }
3076 decompileActions(action_cnt,&actions[n+1],gIndent+1);
3077 INDENT
3078 println("}" );
3079 }
3080 return action_cnt;
3081 }
3082
3083 static int
decompileIMPLEMENTS(int n,SWF_ACTION * actions,int maxn)3084 decompileIMPLEMENTS(int n, SWF_ACTION *actions, int maxn)
3085 {
3086 struct SWF_ACTIONPUSHPARAM *nparam;
3087 int i;
3088 INDENT;
3089 puts(getName(pop()));
3090 printf(" implements ");
3091 nparam=pop();
3092 for(i=0;i<nparam->p.Integer;i++)
3093 {
3094 puts(getName(pop()));
3095 }
3096 println(" ;");
3097 return 0;
3098 }
3099
3100 static int
decompileCAST(int n,SWF_ACTION * actions,int maxn)3101 decompileCAST(int n, SWF_ACTION *actions, int maxn)
3102 {
3103 struct SWF_ACTIONPUSHPARAM *iparam=pop();
3104 struct SWF_ACTIONPUSHPARAM *tparam=pop();
3105 push(newVar_N( getName(tparam),"(",getName(iparam),"", 0,")"));
3106 return 0;
3107 }
3108
3109 int
decompileAction(int n,SWF_ACTION * actions,int maxn)3110 decompileAction(int n, SWF_ACTION *actions, int maxn)
3111 {
3112 if( n > maxn ) SWF_error("Action overflow!!");
3113
3114 #ifdef DEBUG
3115 fprintf(stderr,"%d:\tACTION[%3.3d]: %s\n",
3116 actions[n].SWF_ACTIONRECORD.Offset, n,
3117 actionName(actions[n].SWF_ACTIONRECORD.ActionCode));
3118 #endif
3119
3120 switch(actions[n].SWF_ACTIONRECORD.ActionCode)
3121 {
3122 case SWFACTION_END:
3123 return 0;
3124
3125 case SWFACTION_CONSTANTPOOL:
3126 decompileCONSTANTPOOL(&actions[n]);
3127 return 0;
3128
3129 case SWFACTION_GOTOLABEL:
3130 return decompileGOTOFRAME(n, actions, maxn,1);
3131
3132 case SWFACTION_GOTOFRAME:
3133 return decompileGOTOFRAME(n, actions, maxn,0);
3134
3135 case SWFACTION_GOTOFRAME2:
3136 return decompileGOTOFRAME2(n, actions, maxn);
3137
3138 case SWFACTION_WAITFORFRAME:
3139 decompileWAITFORFRAME(&actions[n]);
3140 return 0;
3141
3142 case SWFACTION_GETURL2:
3143 decompileGETURL2(&actions[n]);
3144 return 0;
3145
3146 case SWFACTION_GETURL:
3147 decompileGETURL(&actions[n]);
3148 return 0;
3149
3150 case SWFACTION_PUSH:
3151 decompilePUSH(&actions[n]);
3152 return 0;
3153
3154 case SWFACTION_PUSHDUP:
3155 decompilePUSHDUP(&actions[n]);
3156 return 0;
3157
3158 case SWFACTION_STACKSWAP:
3159 decompileSTACKSWAP(&actions[n]);
3160 return 0;
3161
3162 case SWFACTION_SETPROPERTY:
3163 decompileSETPROPERTY(n, actions, maxn);
3164 return 0;
3165
3166 case SWFACTION_GETPROPERTY:
3167 decompileGETPROPERTY(n, actions, maxn);
3168 return 0;
3169
3170 case SWFACTION_GETTIME:
3171 return decompileGETTIME(n, actions, maxn);
3172
3173 case SWFACTION_TRACE:
3174 decompileTRACE(n, actions, maxn);
3175 return 0;
3176
3177 case SWFACTION_CALLFRAME:
3178 decompileCALLFRAME(n, actions, maxn);
3179 return 0;
3180
3181 case SWFACTION_EXTENDS:
3182 decompileEXTENDS(n, actions, maxn);
3183 return 0;
3184
3185 case SWFACTION_INITOBJECT:
3186 decompileINITOBJECT(n, actions, maxn);
3187 return 0;
3188
3189 case SWFACTION_NEWOBJECT:
3190 decompileNEWOBJECT(n, actions, maxn);
3191 return 0;
3192
3193 case SWFACTION_NEWMETHOD:
3194 decompileNEWMETHOD(n, actions, maxn);
3195 return 0;
3196
3197 case SWFACTION_GETMEMBER:
3198 decompileGETMEMBER(n, actions, maxn);
3199 return 0;
3200
3201 case SWFACTION_SETMEMBER:
3202 decompileSETMEMBER(n, actions, maxn);
3203 return 0;
3204
3205 case SWFACTION_GETVARIABLE:
3206 decompileGETVARIABLE(n, actions, maxn);
3207 return 0;
3208
3209 case SWFACTION_SETVARIABLE:
3210 decompileSETVARIABLE(n, actions, maxn, 0);
3211 return 0;
3212
3213 case SWFACTION_DEFINELOCAL:
3214 decompileSETVARIABLE(n, actions, maxn, 1);
3215 return 0;
3216
3217 case SWFACTION_DEFINELOCAL2:
3218 decompileDEFINELOCAL2(n, actions, maxn);
3219 return 0;
3220
3221 case SWFACTION_DECREMENT:
3222 return decompileINCR_DECR(n, actions, maxn, 0);
3223
3224 case SWFACTION_INCREMENT:
3225 return decompileINCR_DECR(n, actions, maxn,1);
3226
3227 case SWFACTION_STOREREGISTER:
3228 decompileSTOREREGISTER(n, actions, maxn);
3229 return 0;
3230
3231 case SWFACTION_JUMP:
3232 return decompileJUMP(n, actions, maxn);
3233
3234 case SWFACTION_RETURN:
3235 decompileRETURN(n, actions, maxn);
3236 return 0;
3237
3238 case SWFACTION_LOGICALNOT:
3239 return decompileLogicalNot(n, actions, maxn);
3240
3241 case SWFACTION_IF:
3242 return decompileIF(n, actions, maxn);
3243
3244 case SWFACTION_WITH:
3245 decompileWITH(n, actions, maxn);
3246 return 0;
3247
3248 case SWFACTION_ENUMERATE:
3249 return decompileENUMERATE(n, actions, maxn, 0);
3250
3251 case SWFACTION_ENUMERATE2 :
3252 return decompileENUMERATE(n, actions, maxn,1);
3253
3254 case SWFACTION_INITARRAY:
3255 return decompileINITARRAY(n, actions, maxn);
3256
3257 case SWFACTION_DEFINEFUNCTION:
3258 return decompileDEFINEFUNCTION(n, actions, maxn,0);
3259
3260 case SWFACTION_DEFINEFUNCTION2:
3261 return decompileDEFINEFUNCTION(n, actions, maxn,1);
3262
3263 case SWFACTION_CALLFUNCTION:
3264 return decompileCALLFUNCTION(n, actions, maxn);
3265
3266 case SWFACTION_CALLMETHOD:
3267 return decompileCALLMETHOD(n, actions, maxn);
3268
3269 case SWFACTION_INSTANCEOF:
3270 case SWFACTION_SHIFTLEFT:
3271 case SWFACTION_SHIFTRIGHT:
3272 case SWFACTION_SHIFTRIGHT2:
3273 case SWFACTION_ADD:
3274 case SWFACTION_ADD2:
3275 case SWFACTION_SUBTRACT:
3276 case SWFACTION_MULTIPLY:
3277 case SWFACTION_DIVIDE:
3278 case SWFACTION_MODULO:
3279 case SWFACTION_BITWISEAND:
3280 case SWFACTION_BITWISEOR:
3281 case SWFACTION_BITWISEXOR:
3282 case SWFACTION_EQUAL:
3283 case SWFACTION_EQUALS2:
3284 case SWFACTION_LESS2:
3285 case SWFACTION_LOGICALAND:
3286 case SWFACTION_LOGICALOR:
3287 case SWFACTION_GREATER:
3288 case SWFACTION_LESSTHAN:
3289 case SWFACTION_STRINGEQ:
3290 case SWFACTION_STRINGCOMPARE:
3291 case SWFACTION_STRICTEQUALS:
3292 return decompileArithmeticOp(n, actions, maxn);
3293
3294 case SWFACTION_POP:
3295 pop();
3296 return 0;
3297
3298 case SWFACTION_STARTDRAG:
3299 return decompileSTARTDRAG(n, actions, maxn);
3300
3301 case SWFACTION_DELETE:
3302 return decompileDELETE(n, actions, maxn,0);
3303
3304 case SWFACTION_DELETE2:
3305 return decompileDELETE(n, actions, maxn,1);
3306
3307 case SWFACTION_TARGETPATH:
3308 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"targetPath");
3309
3310 case SWFACTION_TYPEOF:
3311 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"typeof");
3312
3313 case SWFACTION_ORD:
3314 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"ord");
3315
3316 case SWFACTION_CHR:
3317 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"chr");
3318
3319 case SWFACTION_INT:
3320 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"int");
3321
3322 case SWFACTION_TOSTRING:
3323 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"String");
3324
3325 case SWFACTION_TONUMBER:
3326 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"Number");
3327
3328 case SWFACTION_RANDOMNUMBER:
3329 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"random");
3330
3331 case SWFACTION_STRINGLENGTH:
3332 return decompileSingleArgBuiltInFunctionCall(n, actions, maxn,"length");
3333
3334 case SWFACTION_PLAY:
3335 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"play");
3336
3337 case SWFACTION_STOP:
3338 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stop");
3339
3340 case SWFACTION_NEXTFRAME:
3341 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"nextFrame");
3342
3343 case SWFACTION_PREVFRAME:
3344 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"prevFrame");
3345
3346 case SWFACTION_ENDDRAG:
3347 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stopDrag");
3348
3349 case SWFACTION_STOPSOUNDS:
3350 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"stopAllSounds");
3351
3352 case SWFACTION_TOGGLEQUALITY:
3353 return decompile_Null_ArgBuiltInFunctionCall(n, actions, maxn,"toggleHighQuality");
3354
3355 case SWFACTION_MBSUBSTRING:
3356 case SWFACTION_SUBSTRING:
3357 return decompileSUBSTRING(n, actions, maxn);
3358
3359 case SWFACTION_STRINGCONCAT:
3360 return decompileSTRINGCONCAT(n, actions, maxn);
3361
3362 case SWFACTION_REMOVECLIP:
3363 return decompileREMOVECLIP(n, actions, maxn);
3364
3365 case SWFACTION_DUPLICATECLIP:
3366 return decompileDUPLICATECLIP(n, actions, maxn);
3367
3368 case SWFACTION_SETTARGET:
3369 return decompileSETTARGET(n, actions, maxn,0);
3370
3371 case SWFACTION_SETTARGET2:
3372 return decompileSETTARGET(n, actions, maxn,1);
3373
3374 case SWFACTION_IMPLEMENTSOP:
3375 return decompileIMPLEMENTS(n, actions, maxn);
3376
3377 case SWFACTION_CASTOP:
3378 return decompileCAST(n, actions, maxn);
3379
3380 case SWFACTION_THROW:
3381 return decompileTHROW(n, actions, maxn);
3382
3383 case SWFACTION_TRY:
3384 return decompileTRY(n, actions, maxn);
3385
3386 default:
3387 outputSWF_ACTION(n,&actions[n]);
3388 return 0;
3389 }
3390 }
3391
3392 static void
decompileActions(int n,SWF_ACTION * actions,int indent)3393 decompileActions(int n, SWF_ACTION *actions, int indent)
3394 {
3395 int i, svindent;
3396
3397 svindent = gIndent;
3398 gIndent = indent;
3399
3400 for(i=0;i<n;i++) {
3401 i+=decompileAction(i, actions, n);
3402 }
3403 gIndent = svindent;
3404 }
3405
3406 char *
decompile5Action(int n,SWF_ACTION * actions,int indent)3407 decompile5Action(int n, SWF_ACTION *actions,int indent)
3408 {
3409 int j;
3410 if( !n )
3411 return NULL;
3412
3413 pool = NULL;
3414
3415 dcinit();
3416
3417 for(j=0;j<256;j++) regs[j]=0;
3418 regs[1] = newVar("R1");
3419 regs[2] = newVar("R2");
3420 regs[3] = newVar("R3");
3421 regs[4] = newVar("R4");
3422
3423 decompileActions(n, actions, indent);
3424 #ifdef DEBUGSTACK
3425 if( Stack != NULL && *dcstr)
3426 {
3427 int i=0;
3428 println("/* -----------------------------------------------------------------");
3429 println("NOTE: some stuff left on the stack at the end of a block of actions:");
3430 while (Stack)
3431 {
3432 i++;
3433 printf("%d.:\t%s",i, getString(pop()));
3434 println("");
3435 }
3436 println("*/");
3437 }
3438 #else
3439 if( Stack != NULL )
3440 fprintf(stderr,
3441 "Stuff left on the stack at the end of a block of actions!?!?!?\n");
3442 while (Stack)
3443 {
3444 pop();
3445 }
3446 #endif
3447 return dcgetstr();
3448 }
3449
3450