Skip to content

Commit edf0291

Browse files
committed
Add first ideas for addme.script virtual machine
1 parent 46be82f commit edf0291

File tree

5 files changed

+447
-0
lines changed

5 files changed

+447
-0
lines changed

SWBF2Admin/Maps/AddmeReader.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
using SWBF2Admin.Maps.Lua;
5+
6+
namespace SWBF2Admin.Maps
7+
{
8+
class AddmeReader
9+
{
10+
private const string UCFB_HEADER = "ucfb";
11+
12+
private BinaryReader reader;
13+
14+
private uint size;
15+
private string name;
16+
private string info;
17+
private uint bodySize;
18+
19+
public AddmeReader(Stream fs)
20+
{
21+
reader = new BinaryReader(fs);
22+
if (ReadChunkIdentifier() != UCFB_HEADER)
23+
{
24+
throw new Exception("File header mismatch");
25+
}
26+
size = reader.ReadUInt32();
27+
28+
while (NextChunk()) ;
29+
}
30+
31+
private bool NextChunk()
32+
{
33+
string ci = ReadChunkIdentifier();
34+
switch (ci)
35+
{
36+
case "scr_":
37+
uint scr_ = reader.ReadUInt32(); //todo
38+
break;
39+
case "NAME":
40+
name = ReadString();
41+
break;
42+
case "INFO":
43+
info = ReadString();
44+
break;
45+
case "BODY":
46+
ReadBody();
47+
break;
48+
}
49+
50+
return true;
51+
}
52+
53+
private void Align()
54+
{
55+
while (reader.BaseStream.Position % 4 != 0)
56+
{
57+
long toPad = reader.BaseStream.Position % 4;
58+
reader.BaseStream.Seek(toPad, SeekOrigin.Current);
59+
}
60+
}
61+
62+
private string ReadString()
63+
{
64+
int len = (int)reader.ReadUInt32();
65+
string r = DecodeString(reader.ReadBytes(len));
66+
Align();
67+
return r;
68+
}
69+
70+
private string ReadChunkIdentifier()
71+
{
72+
return DecodeString(reader.ReadBytes(4));
73+
}
74+
75+
private string DecodeString(byte[] b)
76+
{
77+
return Encoding.ASCII.GetString(b);
78+
}
79+
80+
private void ReadBody()
81+
{
82+
bodySize = reader.ReadUInt32();
83+
var l = new LuaVM(reader.BaseStream);
84+
}
85+
86+
~AddmeReader()
87+
{
88+
reader.Close();
89+
}
90+
}
91+
}

SWBF2Admin/Maps/Lua/LuaFunction.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace SWBF2Admin.Maps.Lua
8+
{
9+
class LuaFunction
10+
{
11+
private List<LuaInstruction> luaAssembly = new List<LuaInstruction>();
12+
13+
public LuaFunction(string name, int lineDefined, byte nups, byte numParams, byte variadic, byte maxStackSz)
14+
{
15+
Console.WriteLine("function: n:{0} l:{1} u:{2} p:{3} v:{4} s:{5}", name, lineDefined, nups, numParams, variadic, maxStackSz);
16+
}
17+
18+
public void PushLine(int line)
19+
{
20+
Console.WriteLine("line: l:{0}", line);
21+
}
22+
23+
public void PushLocale(string name, int startpc, int endpc)
24+
{
25+
Console.WriteLine("locale: n:{0} s:{1} e:{2} p:{3} v:{4} s:{5}", name, startpc, endpc);
26+
}
27+
28+
public void PushNup(string name)
29+
{
30+
Console.WriteLine("nup: n:{0}", name);
31+
}
32+
33+
public void PushConst()
34+
{
35+
Console.WriteLine("const: nil");
36+
}
37+
38+
public void PushConst(string str)
39+
{
40+
Console.WriteLine("const: s:{0}", str);
41+
}
42+
43+
public void PushConst(float f)
44+
{
45+
Console.WriteLine("const: f:{0}", f);
46+
}
47+
48+
public void PushNested(LuaFunction f)
49+
{
50+
51+
}
52+
53+
public void PushCode(byte[] code)
54+
{
55+
luaAssembly.Add(new LuaInstruction(code));
56+
}
57+
}
58+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
using System;
2+
3+
namespace SWBF2Admin.Maps.Lua
4+
{
5+
enum LuaOpcode : byte
6+
{
7+
MOVE,
8+
LOADK,
9+
LOADBOOL,
10+
LOADNIL,
11+
GETUPVAL,
12+
GETGLOBAL,
13+
GETTABLE,
14+
SETGLOBAL,
15+
SETTABLE,
16+
NEWTABLE,
17+
SELF,
18+
ADD,
19+
SUB,
20+
MUL,
21+
DIV,
22+
POW,
23+
UNM,
24+
NOT,
25+
CONCAT,
26+
JMP,
27+
EQ,
28+
LT,
29+
LE,
30+
TEST,
31+
CALL,
32+
TAILCALL,
33+
RETURN,
34+
FORLOOP,
35+
TFORLOOP,
36+
TFORPREP,
37+
SETLIST,
38+
SETLISTO,
39+
CLOSE,
40+
CLOSURE
41+
}
42+
class LuaInstruction
43+
{
44+
public LuaOpcode OpCode { get; set; }
45+
public int A { get; set; }
46+
public int B { get; set; }
47+
public int C { get; set; }
48+
49+
public LuaInstruction(byte[] instr)
50+
{
51+
OpCode = (LuaOpcode)extract(instr, 0, 6);
52+
A = extract(instr, 6, 8);
53+
C = 0;
54+
55+
switch (OpCode)
56+
{
57+
//iABx
58+
case LuaOpcode.LOADK:
59+
case LuaOpcode.GETGLOBAL:
60+
case LuaOpcode.SETGLOBAL:
61+
case LuaOpcode.SETLIST:
62+
case LuaOpcode.SETLISTO:
63+
case LuaOpcode.CLOSURE:
64+
B = extract(instr, 14, 18);
65+
break;
66+
67+
//iAsBx
68+
case LuaOpcode.JMP:
69+
case LuaOpcode.FORLOOP:
70+
case LuaOpcode.TFORPREP:
71+
B = EvaluateLuaSignBit(extract(instr, 14, 18));
72+
break;
73+
74+
//iABC
75+
default:
76+
C = EvaluateLuaSignBit(extract(instr, 14, 9));
77+
B = EvaluateLuaSignBit(extract(instr, 23, 9));
78+
79+
break;
80+
}
81+
Console.WriteLine("{0}\tA:{1} B:{2} C:{3}", OpCode, A, B, C);
82+
}
83+
84+
private static int EvaluateLuaSignBit(int i)
85+
{
86+
if ((i & (1 << 9)) != 0)
87+
{
88+
i ^= (1 << 9);
89+
i *= -1;
90+
}
91+
return i;
92+
}
93+
94+
private int extract(byte[] instr, int pos, int sz)
95+
{
96+
int res = 0;
97+
int i = pos;
98+
int ctx = 0;
99+
100+
while (i < pos + sz)
101+
{
102+
bool bit = (instr[i / 8] & (1 << (i % 8))) > 0;
103+
res |= ((int)(bit ? 1 : 0) << ctx);
104+
ctx++;
105+
i++;
106+
}
107+
return res;
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)