ref: bc96874813d62c86c475df2c6b311848169a30e6
dir: /acs.c/
#include <u.h> #include <libc.h> uvlong unpack(uchar *from, int n) { uvlong x; int i; for(i = x = 0; i < n; i++) x |= (from[i] << (i*8)); return x; } struct { char *name; int argc; } functab[] = { "NOP", 0, "Terminate", 0, "Suspend", 0, "PushNumber", 1, "LSpec1", 1, "LSpec2", 1, "LSpec3", 1, "LSpec4", 1, "LSpec5", 1, "LSpec1Direct", 2, "LSpec2Direct", 3, "LSpec3Direct", 4, "LSpec4Direct", 5, "LSpec5Direct", 6, "Add", 0, "Subtract", 0, "Multiply", 0, "Divide", 0, "Modulus", 0, "EQ", 0, "NE", 0, "LT", 0, "GT", 0, "LE", 0, "GE", 0, "AssignScriptVar", 1, "AssignMapVar", 1, "AssignWorldVar", 1, "PushScriptVar", 1, "PushMapVar", 1, "PushWorldVar", 1, "AddScriptVar", 1, "AddMapVar", 1, "AddWorldVar", 1, "SubScriptVar", 1, "SubMapVar", 1, "SubWorldVar", 1, "MulScriptVar", 1, "MulMapVar", 1, "MulWorldVar", 1, "DivScriptVar", 1, "DivMapVar", 1, "DivWorldVar", 1, "ModScriptVar", 1, "ModMapVar", 1, "ModWorldVar", 1, "IncScriptVar", 1, "IncMapVar", 1, "IncWorldVar", 1, "DecScriptVar", 1, "DecMapVar", 1, "DecWorldVar", 1, "Goto", 1, "IfGoto", 1, "Drop", 0, "Delay", 0, "DelayDirect", 1, "Random", 0, "RandomDirect", 2, "ThingCount", 0, "ThingCountDirect", 2, "TagWait", 0, "TagWaitDirect", 1, "PolyWait", 0, "PolyWaitDirect", 1, "ChangeFloor", 0, "ChangeFloorDirect", 1, "ChangeCeiling", 0, "ChangeCeilingDirect", 1, "Restart", 0, "AndLogical", 0, "OrLogical", 0, "AndBitwise", 0, "OrBitwise", 0, "EorBitwise", 0, "NegateLogical", 0, "LShift", 0, "RShift", 0, "UnaryMinus", 0, "IfNotGoto", 1, "LineSide", 0, "ScriptWait", 0, "ScriptWaitDirect", 1, "ClearLineSpecial", 0, "CaseGoto", 1, "BeginPrint", 0, "EndPrint", 0, "PrintString", 0, "PrintNumber", 0, "PrintCharacter", 0, "PlayerCount", 0, "GameType", 0, "GameSkill", 0, "Timer", 0, "SectorSound", 0, "AmbientSound", 0, "SoundSequence", 0, "SetLineTexture", 0, "SetLineBlocking", 0, "SetLineSpecial", 0, "ThingSound", 0, "EndPrintBold", 0, }; typedef struct { int index; uchar *address; int argc; int state; int wait; } Script; typedef struct { int marker; int off; int code; int count; int nstring; uchar *base; char **strings; Script scripts[]; } Lump; Lump* parsescript(uchar *b, int) { uchar *base; Lump *s; Script *info; Lump s2; int i; s2.base = base = b; s2.marker = unpack(b, 4); s2.off = unpack(b + 4, 4); s2.code = unpack(b + 8, 4); b += s2.off; s2.count = (int)unpack(b, 4); b += 4; s = mallocz(sizeof(Lump) * sizeof(Script)*s2.count, 1); *s = s2; for(i = 0; i < s->count; i++){ info = s->scripts + i; info->index = unpack(b, 4); info->address = base + unpack(b + 4, 4); info->argc = unpack(b + 8, 4); b += 12; } s->nstring = unpack(b, 4); b += 4; s->strings = mallocz(sizeof(char*) * s->nstring, 1); for(i = 0; i < s->nstring; i++, b += 4) s->strings[i] = (char*)base + unpack(b, 4); return s; } void dump(Lump *s) { int i, j, k; int *ip, *ap; int cmd; static uchar *labels[8192]; int nlabel; int ctx; ctx = 0; for(i = 0; i < s->count; i++){ ip = (int*)(s->scripts[i].address); print("script %d {\n", i); nlabel = 0; for(;;){ cmd = *ip; if(cmd >= nelem(functab)){ break; } print("%.2d\t\t%s(", nlabel, functab[cmd].name); labels[nlabel++] = (uchar*)ip; assert(nlabel != 1024); ap = ip + 1; for(j = 0; j < functab[cmd].argc; j++){ ctx = *ap; if(j == functab[cmd].argc-1) print("%d", *ap); else print("%d, ", *ap); ap++; ip++; } ip++; if(cmd == 52){ for(k = 0; k < nlabel; k++) if(labels[k] == s->base + ctx){ print(") //%d\n", k); break; } } print(")\n"); if(cmd == 1) break; } print("}\n"); } } uchar file[1024*64]; int nfile; void usage(void) { fprint(2, "usage: %s <script>\n", argv0); exits("usage"); } void main(int argc, char **argv) { int fd; int w; Lump *s; ARGBEGIN{ default: usage(); return; }ARGEND if(argc) fd = open(argv[0], OREAD); else fd = 0; if(fd < 0) sysfatal("open: %r"); for(nfile = 0; nfile < sizeof file;){ w = read(fd, file + nfile, sizeof file - nfile); if(w <= 0) break; nfile += w; } if(nfile == 0) return; if(nfile == sizeof file) fprint(2, "file truncated\n"); s = parsescript(file, nfile); dump(s); }