seems that demo compression causes desync
[awish.git] / tools / disasm.bob
bloba712ff272dcef0ea2e1fc7dbc2e7ed5f1efdf25b
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2  * Understanding is not required. Only obedience.
3  *
4  * This program is free software. It comes without any warranty, to
5  * the extent permitted by applicable law. You can redistribute it
6  * and/or modify it under the terms of the Do What The Fuck You Want
7  * To Public License, Version 2, as published by Sam Hocevar. See
8  * http://sam.zoy.org/wtfpl/COPYING for more details. */
9 require("fileex");
12 define abort (msg) {
13   writeln("ERROR: ", msg);
14   quit(1);
18 opnames = \[
19   "add",
20   "sub",
21   "mul",
22   "div",
23   "mod",
24   "bor",
25   "xor",
26   "and",
28   "jeq",
29   "jne",
30   "jlt",
31   "jle",
32   "jgt",
33   "jge",
35   "jmp",
37   "bsr",
39   "brk",
40   "end",
41   "new",
43   "set",
44   "get",
46   "psh",
47   "pop",
48   "swp",
49   "pck",
50   "rol",
51   "dpt",
53   "tid",
54   "kil",
55   "sus",
56   "res",
57   "sta",
59   "rxc",
60   "wxc",
62   "ret",
64   "rst",
66   "mgf",
67   "mgb",
68   "msf",
69   "msb",
73 define isBranch (mnemo) {
74   switch (mnemo) {
75     case "jmp":
76     case "bsr":
77     case "jeq":
78     case "jne":
79     case "jlt":
80     case "jle":
81     case "jgt":
82     case "jge":
83       return true;
84   }
85   return false;
89 LB_GVAR = 0;
90 LB_TVAR = 1;
91 LB_SVAR = 2;
92 LB_CODE = 3;
93 LB_CONST = 4;
96 list = \[];
99 fl = new File("awish.vmd", "rb");
100 if (!fl) abort("no code file");
101 sign = fl.readBuf(4);
102 if (sign != "AVM0") abort("invalid code file");
103 csz = fl.readWord();
104 code = fl.readBuf(csz);
105 lcnt = fl.readWord();
107 for (local f = 0; f < lcnt; ++f) {
108   local type = fl.getc(), value, name, nlen, vname, v;
109   //
110   if (type == LB_GVAR || type == LB_TVAR) {
111     value = fl.getc();
112   } else if (type == LB_CODE) {
113     value = fl.readWord();
114   } else if (type == LB_CONST) {
115     value = fl.readWord();
116     if (value >= 32768) value -= 65536;
117   } else {
118     abort("invalid code file");
119   }
120   nlen = fl.getc();
121   name = fl.readBuf(nlen);
122   for (local f = 0; f < name.length; ++f) name[f] ^= 0xa5;
123   v = \{type:type, name:name, value:value};
124   list.push(v);
127 fl.close();
130 define findLabel (val, type) {
131   foreach (local l with list.items()) {
132     if (l.type == type && l.value == val) return l.name;
133   }
134   return nil;
138 for (local f = 0; f < code.length; ++f) code[f] ^= 42;
141 pc = 0;
142 while (pc < code.length) {
143   local opcode = code[pc++], argc, brn, name;
144   //
145   argc = (opcode>>6)&0x03;
146   opcode &= 0x3f;
147   if (opcode >= opnames.length) {
148     write("%04x: BAD".format(pc-1));
149     name = "BAD";
150   } else if (opnames[opcode] == "jmp" && argc == 0) {
151     write("%04x: %s".format(pc-1, "ret"));
152     name = opnames[opcode];
153   } else {
154     write("%04x: %s".format(pc-1, opnames[opcode]));
155     name = opnames[opcode];
156   }
157   brn = isBranch(name);
158   // read operands
159   for (local f = 0; f < argc; ++f) {
160     local vn = code[pc++], val, var = 0, name;
161     //
162     if (f != 0) write(", "); else write(" ");
163     if (vn == 255) {
164       // immediate
165       val = code[pc++];
166       val |= (code[pc++]<<8);
167       if ((f != 00 || !brn) && val >= 32768) val -= 65536;
168       if (brn && f == 0) {
169         name = findLabel(val, LB_CODE);
170         if (name) write(name); else write("0x%04x".format(val));
171       } else {
172         //name = findLabel(val, LB_CONST);
173         name = nil;
174         if (name) write(name); else write(val);
175       }
176     } else if (vn == 127) {
177       // stack
178       val = code[pc++];
179       val |= (code[pc++]<<8);
180       if (val >= 32768) val -= 65536;
181       write("[.", val, "]");
182     } else {
183       // variable
184       if (vn >= 0x80) {
185         // global
186         var = 1;
187         val = vn&0x7f;
188         name = findLabel(val, LB_GVAR);
189         if (name) write("[", name, "]"); else write("[@", val, "]");
190       } else {
191         // thread
192         var = 2;
193         val = vn&0x7f;
194         name = findLabel(val, LB_TVAR);
195         if (name) write("[", name, "]"); else write("[", val, "]");
196       }
197     }
198   }
199   writeln();