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);
}