amxmodx/plugins/BinLogReader/BinLog.cs

290 lines
6.8 KiB
C#

using System;
using System.IO;
using System.Text;
using System.Collections;
namespace BinLogReader
{
/// <summary>
/// binary log stuff yah
/// </summary>
public class BinLog
{
private static uint BINLOG_MAGIC = 0x414D424C;
private static short BINLOG_VERSION = 0x0300;
private static short BINLOG_MIN_VERSION = 0x0300;
private ArrayList oplist;
private PluginDb plugdb;
public ArrayList OpList
{
get
{
return oplist;
}
}
BinLog(int init_size)
{
oplist = new ArrayList(init_size);
}
public PluginDb GetPluginDB()
{
return plugdb;
}
public static BinLog FromFile(string filename)
{
if (!File.Exists(filename))
return null;
System.IO.FileStream stream = File.Open(filename, System.IO.FileMode.Open);
if (stream == null)
return null;
BinaryReader br = new BinaryReader(stream);
if (br == null)
return null;
BinLog bl = null;
BinLogOp opcode = BinLogOp.BinLog_Invalid;
long realtime = 0;
float gametime = 0.0f;
int plug_id = -1;
Plugin pl = null;
try
{
uint magic = br.ReadUInt32();
if (magic != BINLOG_MAGIC)
throw new Exception("Invalid magic log number");
ushort version = br.ReadUInt16();
if (version > BINLOG_VERSION || version < BINLOG_MIN_VERSION)
throw new Exception("Unknown log version number");
byte timesize = br.ReadByte();
bool bits64 = (timesize == 8) ? true : false;
FileInfo fi = new FileInfo(filename);
//guestimate required size
if (fi.Length > 500)
bl = new BinLog( (int)((fi.Length - 500) / 6) );
else
bl = new BinLog( (int)(fi.Length / 6) );
bl.plugdb = PluginDb.FromFile(br);
PluginDb db = bl.plugdb;
if (db == null)
throw new Exception("Plugin database read failure");
do
{
opcode = (BinLogOp)br.ReadByte();
gametime = br.ReadSingle();
if (bits64)
realtime = br.ReadInt64();
else
realtime = (long)br.ReadInt32();
plug_id = br.ReadInt32();
pl = db.GetPluginById(plug_id);
switch (opcode)
{
case BinLogOp.BinLog_SetString:
{
long addr;
if (bits64)
addr = br.ReadInt64();
else
addr = (long)br.ReadInt32();
int maxlen = br.ReadInt32();
ushort len = br.ReadUInt16();
byte [] str = br.ReadBytes(len+1);
string text = Encoding.ASCII.GetString(str, 0, len);
BinLogSetString bgs =
new BinLogSetString(addr, maxlen, text, gametime, realtime, pl);
bl.OpList.Add(bgs);
break;
}
case BinLogOp.BinLog_GetString:
{
long addr;
if (bits64)
addr = br.ReadInt64();
else
addr = (long)br.ReadInt32();
ushort len = br.ReadUInt16();
byte [] str = br.ReadBytes(len+1);
string text = Encoding.ASCII.GetString(str, 0, len);
BinLogGetString bgs =
new BinLogGetString(addr, text, gametime, realtime, pl);
bl.OpList.Add(bgs);
break;
}
case BinLogOp.BinLog_NativeParams:
{
ArrayList parms;
if (bits64)
{
long num = br.ReadInt64();
long p;
Int64 i64;
parms = new ArrayList((int)num);
for (int i=0; i<(int)num; i++)
{
p = br.ReadInt64();
i64 = new Int64();
i64 = p;
parms.Add(i64);
}
}
else
{
int num = br.ReadInt32();
int p;
Int32 i32;
parms = new ArrayList(num);
for (int i=0; i<num; i++)
{
p = br.ReadInt32();
i32 = new Int32();
i32 = p;
parms.Add(i32);
}
}
BinLogNativeParams bnp =
new BinLogNativeParams(gametime, realtime, pl);
bnp.ParamList = parms;
bl.OpList.Add(bnp);
break;
}
case BinLogOp.BinLog_FormatString:
{
int parm = br.ReadInt32();
int max = br.ReadInt32();
ushort len = br.ReadUInt16();
byte [] str = br.ReadBytes(len + 1);
string text = Encoding.ASCII.GetString(str, 0, len);
BinLogFmtString bfs =
new BinLogFmtString(parm, max, text, gametime, realtime, pl);
bl.OpList.Add(bfs);
break;
}
case BinLogOp.BinLog_End:
{
BinLogSimple bs =
new BinLogSimple(BinLogOp.BinLog_End, gametime, realtime, pl);
bl.OpList.Add(bs);
break;
}
case BinLogOp.BinLog_SetLine:
{
int line = br.ReadInt32();
int file = br.ReadInt32();
BinLogSetLine bsl =
new BinLogSetLine(line, gametime, realtime, pl, file);
bl.OpList.Add(bsl);
break;
}
case BinLogOp.BinLog_CallPubFunc:
{
int pubidx = br.ReadInt32();
int fileid = br.ReadInt32();
BinLogPublic bp =
new BinLogPublic(pubidx,
gametime,
realtime,
pl,
fileid);
bl.OpList.Add(bp);
break;
}
case BinLogOp.BinLog_NativeRet:
{
long ret;
if (bits64)
ret = br.ReadInt64();
else
ret = (long)br.ReadUInt32();
BinLogNativeRet bnr =
new BinLogNativeRet(ret, gametime, realtime, pl);
bl.OpList.Add(bnr);
break;
}
case BinLogOp.BinLog_NativeCall:
{
int native = br.ReadInt32();
int parms = br.ReadInt32();
int file = br.ReadInt32();
BinLogNativeCall bn =
new BinLogNativeCall(native,
parms,
gametime,
realtime,
pl,
file);
bl.OpList.Add(bn);
break;
}
case BinLogOp.BinLog_Start:
{
BinLogSimple bs =
new BinLogSimple(opcode, gametime, realtime, null);
bl.oplist.Add(bs);
break;
}
case BinLogOp.BinLog_Registered:
{
byte length1 = br.ReadByte();
byte [] title = br.ReadBytes(length1 + 1);
byte length2 = br.ReadByte();
byte [] vers = br.ReadBytes(length2 + 1);
BinLogRegister be =
new BinLogRegister(gametime, realtime, pl);
be.title = Encoding.ASCII.GetString(title, 0, length1);
be.version = Encoding.ASCII.GetString(vers, 0, length2);
bl.oplist.Add(be);
pl.Title = be.title;
pl.Version = be.version;
break;
}
default:
{
BinLogSimple bs = new BinLogSimple(BinLogOp.BinLog_Invalid, gametime, realtime, pl);
bl.oplist.Add(bs);
opcode = BinLogOp.BinLog_End;
break;
}
}
} while (opcode != BinLogOp.BinLog_End);
opcode =BinLogOp.BinLog_End;
}
catch (Exception e)
{
if (bl != null && bl.plugdb != null)
{
BinLogSimple bs = new BinLogSimple(BinLogOp.BinLog_Invalid, gametime, realtime, pl);
bl.oplist.Add(bs);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
br.Close();
stream.Close();
GC.Collect();
}
return bl;
}
}
}