--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "action.h"
+#include "compile.h"
+
+
+#define print(x) {fputs(x,stdout);}
+
+int gIndent;
+#define INDENT_LEVEL 2
+
+void println(const char *s, ...)
+{
+ va_list ap;
+ int n = gIndent*INDENT_LEVEL;
+
+ while(n-- > 0)
+ putchar(' ');
+
+ va_start(ap, s);
+ vprintf(s, ap);
+ va_end(ap);
+
+ putchar('\n');
+}
+
+int fileOffset = 0;
+
+int readUInt8(Buffer f)
+{
+ return f->buffer[fileOffset++];
+}
+
+int readSInt8(Buffer f)
+{
+ return (signed char)readUInt8(f);
+}
+
+int readSInt16(Buffer f)
+{
+ return readUInt8(f) + readSInt8(f)*256;
+}
+
+int readUInt16(Buffer f)
+{
+ return readUInt8(f) + (readUInt8(f)<<8);
+}
+
+long readSInt32(Buffer f)
+{
+ return (long)readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24);
+}
+
+unsigned long readUInt32(Buffer f)
+{
+ return (unsigned long)(readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24));
+}
+
+double readDouble(Buffer f)
+{
+ double d;
+ unsigned char *p = (unsigned char *)&d;
+
+ p[4] = readUInt8(f);
+ p[5] = readUInt8(f);
+ p[6] = readUInt8(f);
+ p[7] = readUInt8(f);
+ p[0] = readUInt8(f);
+ p[1] = readUInt8(f);
+ p[2] = readUInt8(f);
+ p[3] = readUInt8(f);
+
+ return d;
+}
+
+char *readString(Buffer f)
+{
+ int len = 0, buflen = 256;
+ char c, *buf, *p;
+
+ buf = (char *)malloc(sizeof(char)*256);
+ p = buf;
+
+ while((c=(char)readUInt8(f)) != '\0')
+ {
+ if(len==buflen)
+ {
+ buf = (char *)realloc(buf, sizeof(char)*(buflen+256));
+ buflen += 256;
+ p = buf+len;
+ }
+
+ *(p++) = c;
+ ++len;
+ }
+
+ *p = 0;
+
+ return buf;
+}
+
+void dumpBytes(Buffer f, int length)
+{
+ int j=0, i, k;
+ unsigned char buf[16];
+
+ if(length==0)
+ return;
+
+ for(;;)
+ {
+ for(i=0; i<16; ++i)
+ {
+ printf("%02x ", buf[i] = readUInt8(f));
+ ++j;
+
+ if(j==length)
+ break;
+ }
+
+ if(j==length)
+ {
+ for(k=i+1; k<16; ++k)
+ print(" ");
+
+ ++i;
+ }
+
+ print(" ");
+
+ for(k=0; k<i; ++k)
+ if((buf[k] > 31) && (buf[k] < 128))
+ putchar(buf[k]);
+ else
+ putchar('.');
+
+ putchar('\n');
+
+ if(j==length)
+ break;
+ }
+ putchar('\n');
+ putchar('\n');
+}
+
+void printDoAction(Buffer f, int length);
+
+char *dictionary[256];
+
+int printActionRecord(Buffer f)
+{
+ int length = 0, type;
+
+ printf("(%i)\t", fileOffset);
+
+ type = readUInt8(f);
+
+ if((type&0x80) == 0x80)
+ length = readUInt16(f);
+
+ switch(type)
+ {
+ case SWFACTION_ADD:
+ println("Add");
+ break;
+ case SWFACTION_SUBTRACT:
+ println("Subtract");
+ break;
+ case SWFACTION_MULTIPLY:
+ println("Multiply");
+ break;
+ case SWFACTION_DIVIDE:
+ println("Divide");
+ break;
+ case SWFACTION_EQUAL:
+ println("Equals");
+ break;
+ case SWFACTION_LESSTHAN:
+ println("Less Than");
+ break;
+ case SWFACTION_LOGICALAND:
+ println("And");
+ break;
+ case SWFACTION_LOGICALOR:
+ println("Or");
+ break;
+ case SWFACTION_LOGICALNOT:
+ println("Not");
+ break;
+ case SWFACTION_STRINGEQ:
+ println("String eq");
+ break;
+ case SWFACTION_STRINGLENGTH:
+ println("String Length");
+ break;
+ case SWFACTION_SUBSTRING:
+ println("Substring");
+ break;
+ case SWFACTION_POP:
+ println("Pop");
+ break;
+ case SWFACTION_INT:
+ println("Int");
+ break;
+ case SWFACTION_GETVARIABLE:
+ println("Get Variable");
+ break;
+ case SWFACTION_SETVARIABLE:
+ println("Set Variable");
+ break;
+ case SWFACTION_SETTARGETEXPRESSION:
+ println("Set Target Expression");
+ break;
+ case SWFACTION_STRINGCONCAT:
+ println("String Concat");
+ break;
+ case SWFACTION_GETPROPERTY:
+ println("Get Property");
+ break;
+ case SWFACTION_SETPROPERTY:
+ println("Set Property");
+ break;
+ case SWFACTION_DUPLICATECLIP:
+ println("Duplicate Clip");
+ break;
+ case SWFACTION_REMOVECLIP:
+ println("Remove Clip");
+ break;
+ case SWFACTION_TRACE:
+ println("Trace");
+ break;
+ case SWFACTION_STARTDRAGMOVIE:
+ println("Start Drag Movie");
+ break;
+ case SWFACTION_STOPDRAGMOVIE:
+ println("Stop Drag Movie");
+ break;
+ case SWFACTION_STRINGCOMPARE:
+ println("String Compare");
+ break;
+ case SWFACTION_RANDOM:
+ println("Random");
+ break;
+ case SWFACTION_MBLENGTH:
+ println("String MB Length");
+ break;
+ case SWFACTION_ORD:
+ println("Ord");
+ break;
+ case SWFACTION_CHR:
+ println("Chr");
+ break;
+ case SWFACTION_GETTIMER:
+ println("Get Timer");
+ break;
+ case SWFACTION_MBSUBSTRING:
+ println("MB Substring");
+ break;
+ case SWFACTION_MBORD:
+ println("MB Ord");
+ break;
+ case SWFACTION_MBCHR:
+ println("MB Chr");
+ break;
+ case SWFACTION_NEXTFRAME:
+ println("Next Frame");
+ break;
+ case SWFACTION_PREVFRAME:
+ println("Previous Frame");
+ break;
+ case SWFACTION_PLAY:
+ println("Play");
+ break;
+ case SWFACTION_STOP:
+ println("Stop");
+ break;
+ case SWFACTION_TOGGLEQUALITY:
+ println("Toggle Quality");
+ break;
+ case SWFACTION_STOPSOUNDS:
+ println("Stop Sounds");
+ break;
+
+ /* ops with args */
+ case SWFACTION_PUSHDATA:
+ {
+ int type;
+ int start = fileOffset;
+
+ while(fileOffset < start+length)
+ {
+ switch(type = readUInt8(f))
+ {
+ case 0: /* string */
+ println("Push String: %s", readString(f));
+ break;
+ case 1: /* property */
+ readUInt16(f); /* always 0? */
+ println("Push Property: %04x", readUInt16(f));
+ break;
+ case 2: /* null */
+ println("Push NULL");
+ break;
+ case 3: /* ??? */
+ println("Push type 3- ??");
+ break;
+ case 4:
+ println("Push register %i", readUInt8(f));
+ break;
+ case 5:
+ if(readUInt8(f))
+ println("Push true");
+ else
+ println("Push false");
+ break;
+ case 6: /* double */
+ println("Push %f", readDouble(f));
+ break;
+ case 7: /* int */
+ println("Push %i", readSInt32(f));
+ break;
+ case 8: /* dictionary */
+ println("Push \"%s\"", dictionary[readUInt8(f)]);
+ break;
+ case 9: /* dictionary */
+ println("Push \"%s\"", dictionary[readSInt16(f)]);
+ default:
+ println("unknown push type: %i", type);
+ }
+ }
+ break;
+ }
+ case SWFACTION_GOTOFRAME:
+ println("Goto Frame %i", readUInt16(f));
+ break;
+ case SWFACTION_GETURL:
+ {
+ char *url = readString(f);
+ println("Get URL \"%s\" target \"%s\"", url, readString(f));
+ break;
+ }
+ case SWFACTION_WAITFORFRAMEEXPRESSION:
+ println("Wait For Frame Expression, skip %i\n", readUInt8(f));
+ break;
+ case SWFACTION_BRANCHALWAYS:
+ println("Branch Always %i", readSInt16(f));
+ break;
+ case SWFACTION_GETURL2:
+ {
+ int flags = readUInt8(f);
+
+ const char *op = (flags & 0x80) ? "Get URL2 (loadvariables)" : "Get URL2";
+ const char *tgt = (flags & 0x40) ? " into target" : "";
+
+ switch(flags & 0x03)
+ {
+ case 0: println("%s%s (Don't send)", op, tgt); break;
+ case 1: println("%s%s (GET)", op, tgt); break;
+ case 2: println("%s%s (POST)", op, tgt); break;
+ }
+ }
+ break;
+ case SWFACTION_BRANCHIFTRUE:
+ println("Branch If True %i", readSInt16(f));
+ break;
+ case SWFACTION_CALLFRAME:
+ println("Call Frame");
+ dumpBytes(f, length);
+ break;
+ case SWFACTION_GOTOEXPRESSION:
+ print("Goto Expression");
+ if(readUInt8(f) == 1)
+ printf(" and Play\n");
+ else
+ printf(" and Stop\n");
+ break;
+ case SWFACTION_WAITFORFRAME:
+ {
+ int frame = readUInt16(f);
+ println("Wait for frame %i else skip %i", frame, readUInt8(f));
+ break;
+ }
+ case SWFACTION_SETTARGET:
+ println("Set Target %s", readString(f));
+ break;
+ case SWFACTION_GOTOLABEL:
+ println("Goto Label %s", readString(f));
+ break;
+ case SWFACTION_END:
+ return 0;
+ break;
+
+ /* f5 ops */
+ case SWFACTION_DELETE:
+ println("Delete");
+ break;
+ case SWFACTION_VAR:
+ println("Var");
+ break;
+ case SWFACTION_VAREQUALS:
+ println("Var assign");
+ break;
+ case SWFACTION_INITARRAY:
+ println("Init array");
+ break;
+ case SWFACTION_INITOBJECT:
+ println("Init object");
+ break;
+ case SWFACTION_CALLFUNCTION:
+ println("call function");
+ break;
+ case SWFACTION_RETURN:
+ println("return");
+ break;
+ case SWFACTION_MODULO:
+ println("modulo");
+ break;
+ case SWFACTION_NEW:
+ println("new");
+ break;
+ case SWFACTION_TYPEOF:
+ println("typeof");
+ break;
+ case SWFACTION_NEWADD:
+ println("new add");
+ break;
+ case SWFACTION_NEWLESSTHAN:
+ println("new less than");
+ break;
+ case SWFACTION_NEWEQUALS:
+ println("new equals");
+ break;
+ case SWFACTION_DUP:
+ println("dup");
+ break;
+ case SWFACTION_SWAP:
+ println("swap");
+ break;
+ case SWFACTION_GETMEMBER:
+ println("get member");
+ break;
+ case SWFACTION_SETMEMBER:
+ println("set member");
+ break;
+ case SWFACTION_INCREMENT:
+ println("increment");
+ break;
+ case SWFACTION_CALLMETHOD:
+ println("call method");
+ break;
+ case SWFACTION_BITWISEAND:
+ println("bitwise and");
+ break;
+ case SWFACTION_BITWISEOR:
+ println("bitwise or");
+ break;
+ case SWFACTION_BITWISEXOR:
+ println("bitwise xor");
+ break;
+ case SWFACTION_SHIFTLEFT:
+ println("shift left");
+ break;
+ case SWFACTION_SHIFTRIGHT:
+ println("shift right");
+ break;
+ case SWFACTION_SHIFTRIGHT2:
+ println("shift right 2");
+ break;
+
+ case SWFACTION_CONSTANTPOOL:
+ {
+ int i, n = readUInt16(f);
+ print("declare dictionary:");
+
+ for(i=0; i<n; ++i)
+ printf(" %s%c", dictionary[i]=readString(f), (i<n-1)?',':'\n');
+
+ break;
+ }
+ case SWFACTION_WITH:
+ {
+ println("with");
+
+ ++gIndent;
+ printDoAction(f, readUInt16(f));
+ --gIndent;
+
+ break;
+ }
+ case SWFACTION_DEFINEFUNCTION:
+ {
+ char *name = readString(f);
+ int n = readUInt16(f);
+
+ print("function ");
+ print(name);
+ putchar('(');
+
+ if(n > 0)
+ {
+ printf("%s", readString(f));
+ --n;
+ }
+
+ for(; n>0; --n)
+ printf(", %s", readString(f));
+
+ putchar(')');
+ putchar('\n');
+
+ ++gIndent;
+ printDoAction(f, readUInt16(f));
+ --gIndent;
+
+ break;
+ }
+
+ case SWFACTION_ENUMERATE:
+ println("enumerate");
+ break;
+
+ case SWFACTION_SETREGISTER:
+ println("set register %i", readUInt8(f));
+ break;
+
+/* f6 actions */
+ case SWFACTION_INSTANCEOF:
+ println("instanceof");
+ break;
+ case SWFACTION_STRICTEQ:
+ println("strict_equals");
+ break;
+ case SWFACTION_ENUM2:
+ println("enum2");
+ break;
+
+ default:
+ println("Unknown Action: %02X", type);
+ dumpBytes(f, length);
+ }
+
+ return 1;
+}
+
+void printDoAction(Buffer f, int length)
+{
+ int end;
+
+ if(!f)
+ return;
+
+ end = fileOffset + length;
+
+ while(fileOffset < end && printActionRecord(f))
+ ;
+}