Skip to content

Commit

Permalink
Add first ideas for addme.script virtual machine
Browse files Browse the repository at this point in the history
  • Loading branch information
jweigelt committed Oct 17, 2019
1 parent 46be82f commit edf0291
Show file tree
Hide file tree
Showing 5 changed files with 447 additions and 0 deletions.
91 changes: 91 additions & 0 deletions SWBF2Admin/Maps/AddmeReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.IO;
using System.Text;
using SWBF2Admin.Maps.Lua;

namespace SWBF2Admin.Maps
{
class AddmeReader
{
private const string UCFB_HEADER = "ucfb";

private BinaryReader reader;

private uint size;
private string name;
private string info;
private uint bodySize;

public AddmeReader(Stream fs)
{
reader = new BinaryReader(fs);
if (ReadChunkIdentifier() != UCFB_HEADER)
{
throw new Exception("File header mismatch");
}
size = reader.ReadUInt32();

while (NextChunk()) ;
}

private bool NextChunk()
{
string ci = ReadChunkIdentifier();
switch (ci)
{
case "scr_":
uint scr_ = reader.ReadUInt32(); //todo
break;
case "NAME":
name = ReadString();
break;
case "INFO":
info = ReadString();
break;
case "BODY":
ReadBody();
break;
}

return true;
}

private void Align()
{
while (reader.BaseStream.Position % 4 != 0)
{
long toPad = reader.BaseStream.Position % 4;
reader.BaseStream.Seek(toPad, SeekOrigin.Current);
}
}

private string ReadString()
{
int len = (int)reader.ReadUInt32();
string r = DecodeString(reader.ReadBytes(len));
Align();
return r;
}

private string ReadChunkIdentifier()
{
return DecodeString(reader.ReadBytes(4));
}

private string DecodeString(byte[] b)
{
return Encoding.ASCII.GetString(b);
}

private void ReadBody()
{
bodySize = reader.ReadUInt32();
var l = new LuaVM(reader.BaseStream);
}

~AddmeReader()
{
reader.Close();
}
}
}
58 changes: 58 additions & 0 deletions SWBF2Admin/Maps/Lua/LuaFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWBF2Admin.Maps.Lua
{
class LuaFunction
{
private List<LuaInstruction> luaAssembly = new List<LuaInstruction>();

public LuaFunction(string name, int lineDefined, byte nups, byte numParams, byte variadic, byte maxStackSz)
{
Console.WriteLine("function: n:{0} l:{1} u:{2} p:{3} v:{4} s:{5}", name, lineDefined, nups, numParams, variadic, maxStackSz);
}

public void PushLine(int line)
{
Console.WriteLine("line: l:{0}", line);
}

public void PushLocale(string name, int startpc, int endpc)
{
Console.WriteLine("locale: n:{0} s:{1} e:{2} p:{3} v:{4} s:{5}", name, startpc, endpc);
}

public void PushNup(string name)
{
Console.WriteLine("nup: n:{0}", name);
}

public void PushConst()
{
Console.WriteLine("const: nil");
}

public void PushConst(string str)
{
Console.WriteLine("const: s:{0}", str);
}

public void PushConst(float f)
{
Console.WriteLine("const: f:{0}", f);
}

public void PushNested(LuaFunction f)
{

}

public void PushCode(byte[] code)
{
luaAssembly.Add(new LuaInstruction(code));
}
}
}
110 changes: 110 additions & 0 deletions SWBF2Admin/Maps/Lua/LuaInstruction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;

namespace SWBF2Admin.Maps.Lua
{
enum LuaOpcode : byte
{
MOVE,
LOADK,
LOADBOOL,
LOADNIL,
GETUPVAL,
GETGLOBAL,
GETTABLE,
SETGLOBAL,
SETTABLE,
NEWTABLE,
SELF,
ADD,
SUB,
MUL,
DIV,
POW,
UNM,
NOT,
CONCAT,
JMP,
EQ,
LT,
LE,
TEST,
CALL,
TAILCALL,
RETURN,
FORLOOP,
TFORLOOP,
TFORPREP,
SETLIST,
SETLISTO,
CLOSE,
CLOSURE
}
class LuaInstruction
{
public LuaOpcode OpCode { get; set; }
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }

public LuaInstruction(byte[] instr)
{
OpCode = (LuaOpcode)extract(instr, 0, 6);
A = extract(instr, 6, 8);
C = 0;

switch (OpCode)
{
//iABx
case LuaOpcode.LOADK:
case LuaOpcode.GETGLOBAL:
case LuaOpcode.SETGLOBAL:
case LuaOpcode.SETLIST:
case LuaOpcode.SETLISTO:
case LuaOpcode.CLOSURE:
B = extract(instr, 14, 18);
break;

//iAsBx
case LuaOpcode.JMP:
case LuaOpcode.FORLOOP:
case LuaOpcode.TFORPREP:
B = EvaluateLuaSignBit(extract(instr, 14, 18));
break;

//iABC
default:
C = EvaluateLuaSignBit(extract(instr, 14, 9));
B = EvaluateLuaSignBit(extract(instr, 23, 9));

break;
}
Console.WriteLine("{0}\tA:{1} B:{2} C:{3}", OpCode, A, B, C);
}

private static int EvaluateLuaSignBit(int i)
{
if ((i & (1 << 9)) != 0)
{
i ^= (1 << 9);
i *= -1;
}
return i;
}

private int extract(byte[] instr, int pos, int sz)
{
int res = 0;
int i = pos;
int ctx = 0;

while (i < pos + sz)
{
bool bit = (instr[i / 8] & (1 << (i % 8))) > 0;
res |= ((int)(bit ? 1 : 0) << ctx);
ctx++;
i++;
}
return res;
}
}
}
Loading

0 comments on commit edf0291

Please sign in to comment.