decompile.c
来自「flash swf file player」· C语言 代码 · 共 1,406 行 · 第 1/3 页
C
1,406 行
/* take a stack, turn it into a tree. e.g.: cmd stack push 'a' 'a' push 'a' 'a' 'a' getvar 'a' a push '1' 'a' a 1 add 'a' a+1 setvar a = a+1*/#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include "decompile.h"#include "read.h"#include "action.h"typedef enum{ BRANCH_NONE = 0, BRANCH_WHILE, BRANCH_DO, BRANCH_IF, BRANCH_ELSE} Branchtype;static void listItem(Stack s, Action parent);static void resolveOffsets(Stack *statements, int nStatements);static void untangleBranches(Stack *statements, int start, int stop, Branchtype type, int indent);static int isNum(char *s){ float f = atof(s); if(f != 0 || s[0] == '0') return true; else return false;}static Stack stack = NULL;static Stack newStack(){ Stack s = (Stack)malloc(sizeof(struct _stack)); memset(s, 0, sizeof(struct _stack)); s->target = -1; return s;}static void destroy(Stack s){ if(!s) return; if(s->type == 't') { destroy(s->data.tree->left); destroy(s->data.tree->right); free(s->data.tree); } else if(s->type == 's') free(s->data.string); free(s);}static Stack newTree(Stack left, Action action, Stack right){ Tree t = (Tree)malloc(sizeof(struct _tree)); Stack s = newStack(); t->left = left; t->right = right; t->action = action; s->type = 't'; s->data.tree = t; return s;}static Stack newString(char *string){ Stack s = newStack(); s->type = 's'; s->data.string = string; return s;}static Stack newProperty(Property prop){ Stack s = newStack(); s->type = 'p'; s->data.prop = prop; return s;}static Stack pop(){ Stack s = stack; if(!stack) error("blown stack!"); stack = stack->next; return s;}static void push(Stack s){ s->next = stack; stack = s;}static char *negateString(char *s){ int i, l = strlen(s)+1; char *New = realloc(s, l+1); for(i=l; i>0; --i) New[i] = New[i-1]; New[0] = '-'; return New;}static Property getSetProperty(int prop){ switch(prop) { case SWF_SETPROPERTY_X: return PROPERTY_X; case SWF_SETPROPERTY_Y: return PROPERTY_Y; case SWF_SETPROPERTY_XSCALE: return PROPERTY_XSCALE; case SWF_SETPROPERTY_YSCALE: return PROPERTY_YSCALE; case SWF_SETPROPERTY_ALPHA: return PROPERTY_ALPHA; case SWF_SETPROPERTY_VISIBILITY: return PROPERTY_VISIBLE; case SWF_SETPROPERTY_ROTATION: return PROPERTY_ROTATION; case SWF_SETPROPERTY_NAME: return PROPERTY_NAME; case SWF_SETPROPERTY_HIGHQUALITY: return PROPERTY_HIGHQUALITY; case SWF_SETPROPERTY_SHOWFOCUSRECT: return PROPERTY_FOCUSRECT; case SWF_SETPROPERTY_SOUNDBUFFERTIME: return PROPERTY_SOUNDBUFTIME; case SWF_SETPROPERTY_WTHIT: return PROPERTY_WTHIT; default: error("unknown property: 0x%04x!", prop); return SWF_SETPROPERTY_WTHIT; }}static Stack readActionRecord(FILE *f){ int length = 0, type = readUInt8(f); if((type&0x80) == 0x80) length = readUInt16(f); switch(type) { /* no-arg */ case SWFACTION_GETTIMER: case SWFACTION_STOPDRAGMOVIE: case SWFACTION_NEXTFRAME: case SWFACTION_PREVFRAME: case SWFACTION_PLAY: case SWFACTION_STOP: case SWFACTION_TOGGLEQUALITY: case SWFACTION_STOPSOUNDS: return newTree(NULL, type, NULL); case SWFACTION_POP: /* pop(); */ return newTree(NULL, type, NULL); /* one-arg */ case SWFACTION_STRINGLENGTH: case SWFACTION_INT: case SWFACTION_RANDOM: case SWFACTION_MBLENGTH: case SWFACTION_ORD: case SWFACTION_CHR: case SWFACTION_MBORD: case SWFACTION_MBCHR: case SWFACTION_LOGICALNOT: case SWFACTION_GETVARIABLE: case SWFACTION_REMOVECLIP: case SWFACTION_TRACE: case SWFACTION_SETTARGETEXPRESSION: case SWFACTION_CALLFRAME: return newTree(pop(), type, NULL); /* two-arg */ case SWFACTION_ADD: case SWFACTION_MULTIPLY: case SWFACTION_DIVIDE: case SWFACTION_EQUAL: case SWFACTION_LESSTHAN: case SWFACTION_LOGICALAND: case SWFACTION_LOGICALOR: case SWFACTION_STRINGEQ: case SWFACTION_SETVARIABLE: case SWFACTION_STRINGCONCAT: case SWFACTION_STRINGCOMPARE: { Stack right = pop(); Stack left = pop(); return newTree(left, type, right); } case SWFACTION_GETPROPERTY: { Stack right = pop(); Stack left = pop(); if(right->type == 's') { Stack New = newProperty(atoi(right->data.string)); destroy(right); right = New; } return newTree(left, type, right); } case SWFACTION_SUBTRACT: { Stack right = pop(); Stack left = pop(); if(left->type == 's' && strcmp(left->data.string, "0") == 0) { destroy(left); right->data.string = negateString(right->data.string); return right; } return newTree(left, type, right); } /* three-arg */ case SWFACTION_SETPROPERTY: { Stack value = pop(); Stack property = pop(); Stack target = pop(); if(property->type == 's') { Stack New = newProperty(atoi(property->data.string)); destroy(property); property = New; } return newTree(newTree(target, type, property), SWFACTION_SETVARIABLE, value); } case SWFACTION_MBSUBSTRING: case SWFACTION_SUBSTRING: { Stack s3 = pop(); Stack s2 = pop(); Stack s1 = pop(); return newTree(s1, type, newTree(s2, type, s3)); } case SWFACTION_DUPLICATECLIP: { Stack level = pop(); Stack target = pop(); Stack source = pop(); Stack arg; if(level->type != 't' || level->data.tree->action != SWFACTION_ADD) error("WTHIT property not found in duplicateClip target level!"); if(level->data.tree->left->type == 'p' && level->data.tree->left->data.prop == PROPERTY_WTHIT) { arg = level->data.tree->right; level->data.tree->right = NULL; } else if(level->data.tree->right->type == 'p' && level->data.tree->right->data.prop == PROPERTY_WTHIT) { arg = level->data.tree->left; level->data.tree->left = NULL; } else error("WTHIT property not found in duplicateClip target level!"); destroy(level); return newTree(source, type, newTree(target, type, arg)); } /* weird ops */ case SWFACTION_STARTDRAGMOVIE: { Stack target = pop(); Stack lockmouse = pop(); Stack constraint = pop(); if(constraint->type != 's') error("Sorry, decompiler can't deal with conditional constraint!"); if(strcmp(constraint->data.string, "0") == 0) return newTree(constraint, type, newTree(lockmouse, type, target)); else { Stack s4 = pop(); Stack s3 = pop(); Stack s2 = pop(); Stack s1 = pop(); return newTree(newTree(newTree(s1, type, s2), type, newTree(s3, type, s4)), type, newTree(lockmouse, type, target)); } } case SWFACTION_PUSHDATA: { int local_type = readUInt8(f); if(local_type==0) return newString(readString(f)); else { readUInt16(f); /* 0x0000 */ return newProperty(getSetProperty(readUInt16(f))); } } case SWFACTION_GOTOFRAME: return newTree((Stack)readUInt16(f), type, NULL); case SWFACTION_GETURL: { char *url = readString(f); char *target = readString(f); return newTree((Stack)url, type, (Stack)target); } case SWFACTION_GETURL2: { Stack target = pop(); Stack url = pop(); return newTree((Stack)readUInt8(f), type, newTree(url, type, target)); } case SWFACTION_WAITFORFRAMEEXPRESSION: return newTree((Stack)readUInt8(f), type, NULL); case SWFACTION_GOTOEXPRESSION: return newTree(pop(), type, (Stack)readUInt8(f)); case SWFACTION_SETTARGET: case SWFACTION_GOTOLABEL: return newTree((Stack)readString(f), type, NULL); /* branches */ case SWFACTION_BRANCHIFTRUE: return newTree(pop(), type, (Stack)readSInt16(f)); case SWFACTION_BRANCHALWAYS: return newTree(NULL, type, (Stack)readSInt16(f)); case SWFACTION_WAITFORFRAME: { Stack left = (Stack)readUInt16(f); Stack right = (Stack)readUInt8(f); return newTree(left, type, right); } case SWFACTION_END: return NULL; default: printf("Unknown Action: %02X\n", type); dumpBytes(f, length); return NULL; }}static void listProperty(Property prop){ switch(prop) { case PROPERTY_X: printf("x"); break; case PROPERTY_Y: printf("y"); break; case PROPERTY_XSCALE: printf("xScale"); break; case PROPERTY_YSCALE: printf("yScale"); break; case PROPERTY_CURRENTFRAME: printf("currentFrame"); break; case PROPERTY_TOTALFRAMES: printf("totalFrames"); break; case PROPERTY_ALPHA: printf("alpha"); break; case PROPERTY_VISIBLE: printf("visible"); break; case PROPERTY_WIDTH: printf("width"); break; case PROPERTY_HEIGHT: printf("height"); break; case PROPERTY_ROTATION: printf("rotation"); break; case PROPERTY_TARGET: printf("target"); break; case PROPERTY_FRAMESLOADED: printf("framesLoaded"); break; case PROPERTY_NAME: printf("name"); break; case PROPERTY_DROPTARGET: printf("dropTarget"); break; case PROPERTY_URL: printf("url"); break; case PROPERTY_HIGHQUALITY: printf("quality"); break; case PROPERTY_FOCUSRECT: printf("focusRect"); break; case PROPERTY_SOUNDBUFTIME: printf("soundBufTime"); break; case PROPERTY_WTHIT: printf("WTHIT!?"); break; default: printf("unknown property!"); break; }}static int precedence(Action type){ switch(type) { case SWFACTION_SETVARIABLE: return 0; case SWFACTION_LOGICALAND: return 1; case SWFACTION_LOGICALOR: return 1; case SWFACTION_LOGICALNOT: return 2; case SWFACTION_LESSTHAN: return 3; case SWFACTION_EQUAL: return 3; case SWFACTION_ADD: return 4; case SWFACTION_SUBTRACT: return 4; case SWFACTION_MULTIPLY: return 5; case SWFACTION_DIVIDE: return 5; case SWFACTION_GETVARIABLE: return 6; case SWFACTION_GETPROPERTY: return 6; case SWFACTION_STRINGEQ: return 7; case SWFACTION_STRINGCONCAT: return 7; case SWFACTION_PUSHDATA: return 7; case SWFACTION_SETPROPERTY: return 8; default: return 0; }}typedef enum{ NONEGATE = 0, NEGATE = 1} negateFlag;static void listLessThan(Stack s, negateFlag negate){ Stack left = s->data.tree->left, right = s->data.tree->right;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?