Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- namespace ReaDat
- {
- class GothicDat
- {
- #region DatReader
- /// <summary>
- /// Abgeleitet von BinaryReader mit ein paar modifizierten Funktionen
- /// </summary>
- internal class DatReader : BinaryReader
- {
- public DatReader(Stream s) : base(s) { }
- public override char ReadChar()
- {
- return Convert.ToChar(ReadByte());
- }
- public override string ReadString()
- {
- char c = ReadChar();
- StringBuilder sb = new StringBuilder();
- while (c != '\n')
- {
- sb.Append(c);
- c = ReadChar();
- }
- return sb.ToString();
- }
- }
- #endregion
- /// <summary>
- /// Sucht nach Symbol.name in der Symboltable
- /// </summary>
- /// <param name="name">Name des zu suchenden Symbols</param>
- /// <returns>Das passende Symbol. Wird keine Übereinstimmung gefunden wird null zurückgegeben</returns>
- public Symbol GetSymbol(string name)
- {
- foreach (Symbol s in Symbols)
- if (s.name == name)
- return s;
- return null;
- }
- /// <summary>
- /// Version der .dat
- /// </summary>
- public byte Version;
- public Symbol[] Symbols;
- public readonly byte[] Stack;
- private int GetStackInt(int offs)
- {
- return Stack[offs] + (Stack[offs + 1] << 8) + (Stack[offs + 2] << 16) + (Stack[offs + 3] << 24);
- }
- private readonly byte[] content;
- public GothicDat(string Path)
- {
- content = File.ReadAllBytes(Path);
- MemoryStream m = new MemoryStream(content);
- DatReader br = new DatReader(m);
- // === Header ===
- Version = br.ReadByte();
- // === Symboltable ===
- int nr = br.ReadInt32();
- // sortedTable
- int[] sortedTable = new int[nr]; // Nur temporär.. Was soll ich damit?
- for (int i = 0; i < nr; ++i)
- sortedTable[i] = br.ReadInt32();
- // symbols
- Symbols = new Symbol[nr];
- for (int i = 0; i < nr; ++i)
- Symbols[i] = new Symbol(ref br, this, i);
- // === Stack ===
- UInt32 size = br.ReadUInt32();
- Stack = br.ReadBytes((int)size);
- br.Close();
- m.Close();
- content = null;
- }
- public class Symbol
- {
- internal Symbol(ref DatReader br, GothicDat s, int ID)
- {
- id = ID;
- Parent = s;
- b_hasName = br.ReadInt32();
- name = br.ReadString();
- offset = br.ReadInt32();
- bitfield = br.ReadInt32();
- filenr = br.ReadInt32();
- line = br.ReadInt32();
- line_anz = br.ReadInt32();
- pos_beg = br.ReadInt32();
- pos_anz = br.ReadInt32();
- if ((flags & zPAR_FLAG_CLASSVAR) == 0)
- {
- if (type == zPAR_TYPE_FUNC || type == zPAR_TYPE_CLASS || type == zPAR_TYPE_PROTOTYPE)
- content = new object[1];
- else
- content = new object[ele];
- if (content.Length == 0 && type == zPAR_TYPE_INSTANCE)
- content = new object[1];
- for (int i = 0; i < content.Length; ++i)
- {
- switch (type)
- {
- case zPAR_TYPE_STRING:
- content[i] = br.ReadString();
- break;
- case zPAR_TYPE_FLOAT:
- content[i] = br.ReadSingle();
- break;
- default:
- content[i] = br.ReadInt32();
- break;
- }
- }
- }
- parent = br.ReadInt32();
- }
- private readonly GothicDat Parent;
- public int b_hasName;
- public int id;
- public string name;
- public int offset;
- public int bitfield;
- public int filenr;
- public int line;
- public int line_anz;
- public int pos_beg;
- public int pos_anz;
- public int parent;
- public object[] content;
- public int type { get { return bitfield & zCPar_Symbol_bitfield_type; } }
- public int ele { get { return bitfield & zCPar_Symbol_bitfield_ele; } }
- public int flags { get { return bitfield & zCPar_Symbol_bitfield_flags; } }
- public string TypeToString()
- {
- StringBuilder sb = new StringBuilder();
- switch (type)
- {
- case zPAR_TYPE_VOID: return("void");
- case zPAR_TYPE_FLOAT: sb.Append("float");
- break;
- case zPAR_TYPE_INT: sb.Append("int");
- break;
- case zPAR_TYPE_STRING: sb.Append("string");
- break;
- case zPAR_TYPE_CLASS: return("class");
- case zPAR_TYPE_FUNC: return("func");
- case zPAR_TYPE_PROTOTYPE: return("prototype");
- case zPAR_TYPE_INSTANCE: return("instance");
- default:
- return string.Empty;
- }
- if(ele > 1)
- {
- sb.Append('[');
- sb.Append(ele);
- sb.Append(']');
- }
- return sb.ToString();
- }
- public string GetReturnValue()
- {
- switch(offset)
- {
- case 0:
- return "void";
- case 1:
- return "float";
- case 2:
- return "int";
- case 3:
- return "string";
- case 7:
- return "inst";
- default:
- return offset.ToString();
- }
- }
- public string GetLocalName()
- {
- return name.Split('.')[1];
- }
- public string ParamsToString()
- {
- if (ele == 0) return "()";
- StringBuilder s = new StringBuilder("(");
- s.Append(Parent.Symbols[id + 1].TypeToString());
- s.Append(' ');
- s.Append(Parent.Symbols[id + 1].GetLocalName());
- for (int i = 1; i < ele; ++i)
- {
- s.Append(", ");
- s.Append(Parent.Symbols[id + i + 1].TypeToString());
- s.Append(' ');
- s.Append(Parent.Symbols[id + i + 1].GetLocalName());
- }
- s.Append(")");
- return s.ToString();
- }
- public string FlagsToString()
- {
- StringBuilder s = new StringBuilder();
- if ((flags & zPAR_FLAG_CONST) > 0) s.Append("CONST, ");
- if ((flags & zPAR_FLAG_RETURN) > 0) s.Append("RETURN, ");
- if ((flags & zPAR_FLAG_CLASSVAR) > 0) s.Append("CLASSVAR, ");
- if ((flags & zPAR_FLAG_EXTERNAL) > 0) s.Append("EXTERNAL, ");
- if ((flags & zPAR_FLAG_MERGED) > 0) s.Append("MERGED, ");
- try
- {
- return s.Remove(s.Length - 2, 2).ToString();
- }
- catch
- {
- return String.Empty;
- }
- }
- private string OnecontentToString(int o)
- {
- switch(type)
- {
- case zPAR_TYPE_STRING:
- return "\"" + (string)content[o] + '"';
- case zPAR_TYPE_INT:
- return ((int) content[o]).ToString();
- case zPAR_TYPE_FLOAT:
- return ((float) content[o]).ToString();
- }
- return "";
- }
- public string ContentToString()
- {
- if ((type != zPAR_TYPE_STRING && type != zPAR_TYPE_INT && type != zPAR_TYPE_FLOAT) || (flags & zPAR_FLAG_CONST) == 0)
- return string.Empty;
- if (ele <= 1)
- return OnecontentToString(0);
- StringBuilder b = new StringBuilder();
- b.Append("{ ");
- b.Append(OnecontentToString(0));
- for(int i = 1; i < ele; ++i)
- {
- b.Append(", ");
- b.Append(OnecontentToString(i));
- }
- b.Append(" }");
- return b.ToString();
- }
- public override string ToString()
- {
- if (IsFunction() || IsInstance())
- return Parent.FuncToString(this);
- if (content == null || content.Length == 0 || !IsConst()) return base.ToString();
- return ContentToString();
- }
- public bool IsFunction()
- {
- return (((flags & zPAR_FLAG_CONST) > 0) && (type == zPAR_TYPE_FUNC));
- }
- public bool IsInstance()
- {
- return (type == zPAR_TYPE_INSTANCE);
- }
- public bool IsPrototype()
- {
- return (type == zPAR_TYPE_PROTOTYPE);
- }
- public bool IsConst()
- {
- return ((flags & zPAR_FLAG_CONST) > 0);
- }
- public string ParentToString()
- {
- return (parent == -1)? "" : Parent.Symbols[parent%Parent.Symbols.Length].name;
- }
- }
- public string TokToString(int tok)
- {
- switch (tok)
- {
- case zPAR_OP_PLUS: return "add";
- case zPAR_OP_MINUS: return "sub";
- case zPAR_OP_MUL: return "mul";
- case zPAR_OP_DIV: return "div";
- case zPAR_OP_MOD: return "mod";
- case zPAR_OP_OR: return "or";
- case zPAR_OP_AND: return "and";
- case zPAR_OP_LOWER: return "lwr";
- case zPAR_OP_HIGHER: return "hgh";
- case zPAR_OP_IS: return "is";
- case zPAR_OP_LOG_OR: return "lor";
- case zPAR_OP_LOG_AND: return "land";
- case zPAR_OP_SHIFTL: return "shl";
- case zPAR_OP_SHIFTR: return "shr";
- case zPAR_OP_LOWER_EQ: return "leq";
- case zPAR_OP_EQUAL: return "eq";
- case zPAR_OP_NOTEQUAL: return "neq";
- case zPAR_OP_HIGHER_EQ: return "heq";
- case zPAR_OP_ISPLUS: return "iadd";
- case zPAR_OP_ISMINUS: return "isub";
- case zPAR_OP_ISMUL: return "imul";
- case zPAR_OP_ISDIV: return "idiv";
- case zPAR_OP_UN_PLUS: return "uplus";
- case zPAR_OP_UN_MINUS: return "uminus";
- case zPAR_OP_UN_NOT: return "not";
- case zPAR_OP_UN_NEG: return "neg";
- case zPAR_TOK_RET: return "retn";
- case zPAR_TOK_CALL: return "call ";
- case zPAR_TOK_CALLEXTERN: return "callx ";
- case zPAR_TOK_POPINT: return "popi";
- case zPAR_TOK_PUSHINT: return "pushi ";
- case zPAR_TOK_PUSHVAR: return "pushv ";
- case zPAR_TOK_PUSHSTR: return "pushs ";
- case zPAR_TOK_PUSHINST: return "pushin ";
- case zPAR_TOK_PUSHINDEX: return "pushid ";
- case zPAR_TOK_POPVAR: return "popv";
- case zPAR_TOK_ASSIGNSTR: return "astr";
- case zPAR_TOK_ASSIGNSTRP: return "astrp";
- case zPAR_TOK_ASSIGNFUNC: return "afnc";
- case zPAR_TOK_ASSIGNFLOAT: return "aflt";
- case zPAR_TOK_ASSIGNINST: return "ains";
- case zPAR_TOK_JUMP: return "jmp ";
- case zPAR_TOK_JUMPF: return "jmpf ";
- case zPAR_TOK_SETINSTANCE: return "sinst ";
- case zPAR_TOK_ARRAYACCESS: return "pusha ";
- default:
- return string.Empty;
- }
- }
- public string FuncToString(Symbol fnc)
- {
- int c = (int)fnc.content[0] - 1;
- StringBuilder s = new StringBuilder();
- List<int> jmpStck = new List<int>();
- loopStart:
- do
- {
- c++;
- byte b = Stack[c];
- string h = c.ToString("X");
- int len = h.Length;
- while (++len < 8) s.Append('0');
- s.Append(h);
- s.Append(' ');
- s.Append(' ');
- h = TokToString(Stack[c]);
- s.Append(h);
- if (((b >= zPAR_TOK_CALL) && (b <= zPAR_TOK_POPVAR))
- || ((b >= zPAR_TOK_JUMP) && (b <= zPAR_TOK_SETINSTANCE))
- || (b == zPAR_TOK_ARRAYACCESS))
- {
- int r = 0;
- for (int i = 0; i < 4; ++i)
- r += Stack[c + i + 1] << (i << 3);
- string res = string.Empty;
- switch (b)
- {
- case zPAR_TOK_CALL:
- foreach (Symbol sym in Symbols)
- {
- if (!sym.IsFunction()&&!sym.IsPrototype()&&!sym.IsInstance()) continue;
- if ((int)sym.content[0] != r) continue;
- res = sym.name;
- break;
- }
- if(res == string.Empty)
- res = r.ToString();
- break;
- case zPAR_TOK_JUMPF:
- case zPAR_TOK_JUMP:
- jmpStck.Add(+r);
- res = "0x" + r.ToString("X").ToUpper();
- break;
- default:
- if (b != zPAR_TOK_PUSHINT)
- {
- res = Symbols[r].name;
- if (b == zPAR_TOK_ARRAYACCESS)
- {
- res += "[" + Stack[c + 5] + "]";
- ++c;
- }
- if(Symbols[r].IsConst() && !Symbols[r].IsFunction() && !Symbols[r].IsInstance() && !Symbols[r].IsPrototype())
- {
- res += ", " + Symbols[r];
- }
- }
- else
- {
- res = r.ToString();
- }
- break;
- }
- s.Append(res);
- c += 4;
- }
- s.Append('\n');
- }
- while (Stack[c] != zPAR_TOK_RET);
- if (c + 1 != Stack.Length)
- {
- bool found = false;
- foreach (Symbol S in Symbols)
- {
- if (!S.IsFunction()&&!S.IsInstance()&&!S.IsPrototype()) continue;
- if ((int)S.content[0] != (c + 1)) continue;
- found = true;
- break;
- }
- if(!found)
- goto loopStart;
- }
- return s.ToString();
- }
- #region Parsertokens
- //Gewöhnliche Operatoren
- public const byte zPAR_OP_PLUS = 0; //"+" 0x00
- public const byte zPAR_OP_MINUS = 1; //"-" 0x01
- public const byte zPAR_OP_MUL = 2; //"*" 0x02
- public const byte zPAR_OP_DIV = 3; //"/" 0x03
- public const byte zPAR_OP_MOD = 4; //"%" 0x04
- public const byte zPAR_OP_OR = 5; //"|" 0x05
- public const byte zPAR_OP_AND = 6; //"&" 0x06
- public const byte zPAR_OP_LOWER = 7; //"<" 0x07
- public const byte zPAR_OP_HIGHER = 8; //">" 0x08
- //Ausnahme:
- public const byte zPAR_OP_IS = 9; //"=" 0x09 //hole i1, i2 vom Datenstack und setze i1 = i2. i1 muss hier eine Referenz sein.
- //Operatoren aus zwei Zeichen
- public const byte zPAR_OP_LOG_OR = 11; //"||"0x0B
- public const byte zPAR_OP_LOG_AND = 12; //"&&"0x0C
- public const byte zPAR_OP_SHIFTL = 13; //"<<"0x0D
- public const byte zPAR_OP_SHIFTR = 14; //">>"0x0E
- public const byte zPAR_OP_LOWER_EQ = 15; //"<="0x0F
- public const byte zPAR_OP_EQUAL = 16; //"=="0x10
- public const byte zPAR_OP_NOTEQUAL = 17; //"!="0x11
- public const byte zPAR_OP_HIGHER_EQ = 18; //">="0x12
- public const byte zPAR_OP_ISPLUS = 19; //"+="0x13
- public const byte zPAR_OP_ISMINUS = 20; //"-="0x14
- public const byte zPAR_OP_ISMUL = 21; //"*="0x15
- public const byte zPAR_OP_ISDIV = 22; //"/="0x16
- /* Unäre Operatoren nehmen natürlich nur einen Wert vom Datenstack.
- Sie schieben ebenfalls das Ergebnis auf den Datenstack. */
- public const byte zPAR_OP_UNARY = 30;
- public const byte zPAR_OP_UN_PLUS = 30; //"+" 0x1E
- public const byte zPAR_OP_UN_MINUS = 31; //"-" 0x1F
- public const byte zPAR_OP_UN_NOT = 32; //"!" 0x20
- public const byte zPAR_OP_UN_NEG = 33; //"~" 0x21
- public const byte zPAR_OP_MAX = 33;
- //Jetzt: Andere Tokens (zum Parsen)
- public const byte zPAR_TOK_BRACKETON = 40;
- public const byte zPAR_TOK_BRACKETOFF = 41;
- public const byte zPAR_TOK_SEMIKOLON = 42;
- public const byte zPAR_TOK_KOMMA = 43;
- public const byte zPAR_TOK_SCHWEIF = 44;
- public const byte zPAR_TOK_NONE = 45;
- public const byte zPAR_TOK_FLOAT = 51;
- public const byte zPAR_TOK_VAR = 52;
- public const byte zPAR_TOK_OPERATOR = 53;
- /* Weitere Befehle (Nicht vergessen: Operatoren sind auch Befehle!)
- * Manchen Befehlen folgt immer ein Parameter nach.
- * Anderen Befehle bestehen nur aus dem Befehlstoken */
- public const byte zPAR_TOK_RET = 60; //0x3C //return
- public const byte zPAR_TOK_CALL = 61; //0x3D //rufe Funktion auf. Es folgen 4 byte Callziel (Stackadresse)
- public const byte zPAR_TOK_CALLEXTERN = 62; //0x3E //rufe External auf. Es folgen 4 byte Symbol der External
- public const byte zPAR_TOK_POPINT = 63; //0x3F //ungenutzt
- public const byte zPAR_TOK_PUSHINT = 64; //0x40 //schiebe integer Konstante auf den Datenstack. Es folgt die byteegerkonstante (4 byte)
- public const byte zPAR_TOK_PUSHVAR = 65; //0x41 //schiebe Variable auf den Datenstack. Es folt der Symbolindex der Variable (4 byte)
- public const byte zPAR_TOK_PUSHSTR = 66; //0x42 //ungenutzt
- public const byte zPAR_TOK_PUSHINST = 67; //0x43 //schiebe Instanz auf den Datenstack. Es folgen die 4 byte Symbolindex der Instanz
- public const byte zPAR_TOK_PUSHINDEX = 68; //0x44 //ungenutzt
- public const byte zPAR_TOK_POPVAR = 69; //0x45 //ungenutzt
- public const byte zPAR_TOK_ASSIGNSTR = 70; //0x46 //Zuweisung. Hole v1, v2 vom Stack und setze v1 = v2
- public const byte zPAR_TOK_ASSIGNSTRP = 71; //0x47 //Zuweisung. Hole v1, v2 vom Stack und setze v1 = v2
- public const byte zPAR_TOK_ASSIGNFUNC = 72; //0x48 //Zuweisung. Hole v1, v2 vom Stack und setze v1 = v2
- public const byte zPAR_TOK_ASSIGNFLOAT = 73; //0x49 //Zuweisung. Hole v1, v2 vom Stack und setze v1 = v2
- public const byte zPAR_TOK_ASSIGNINST = 74; //0x4A //Zuweisung. Hole v1, v2 vom Stack und setze v1 = v2
- public const byte zPAR_TOK_JUMP = 75; //0x4B //Springe im Parserstack. Es folgen 4 byte Sprungziel
- public const byte zPAR_TOK_JUMPF = 76; //0x4C //Hole b vom Datenstack und springe, falls b == 0 ist. Es folgen 4 byte Sprungziel (lies: "jump if false". Für "if"-Bedingungen)
- public const byte zPAR_TOK_SETINSTANCE = 80; //0x50 //Es folgen 4 byte Symbolindex. Umständlich zu erklären. So grob: "Setze aktuelle Instanz."
- //Irgendwelche byteernas. Wahrscheinlich nur bedingt relevant.
- public const byte zPAR_TOK_SKIP = 90;
- public const byte zPAR_TOK_LABEL = 91;
- public const byte zPAR_TOK_FUNC = 92;
- public const byte zPAR_TOK_FUNCEND = 93;
- public const byte zPAR_TOK_CLASS = 94;
- public const byte zPAR_TOK_CLASSEND = 95;
- public const byte zPAR_TOK_INSTANCE = 96;
- public const byte zPAR_TOK_INSTANCEEND = 97;
- public const byte zPAR_TOK_NEWSTRING = 98;
- //Kann verodert mit zPAR_TOK_PUSHVAR benutzt werden. In dem Fall wird noch ein weiteres Byte als Index erwartet. Für Pushen von Arraywerten.
- public const byte zPAR_TOK_FLAGARRAY = zPAR_TOK_VAR + 128;
- public const byte zPAR_TOK_ARRAYACCESS = 245;
- public const int zCPar_Symbol_bitfield_ele = ((1 << 12) - 1) << 0;
- public const int zCPar_Symbol_bitfield_type = ((1 << 4) - 1) << 12;
- public const int zCPar_Symbol_bitfield_flags = ((1 << 6) - 1) << 16;
- public const int zCPar_Symbol_bitfield_space = ((1 << 1) - 1) << 22;
- public const int zPAR_TYPE_VOID = 0 << 12;
- public const int zPAR_TYPE_FLOAT = 1 << 12;
- public const int zPAR_TYPE_INT = 2 << 12;
- public const int zPAR_TYPE_STRING = 3 << 12;
- public const int zPAR_TYPE_CLASS = 4 << 12;
- public const int zPAR_TYPE_FUNC = 5 << 12;
- public const int zPAR_TYPE_PROTOTYPE = 6 << 12;
- public const int zPAR_TYPE_INSTANCE = 7 << 12;
- public const int zPAR_FLAG_CONST = 1 << 16;
- public const int zPAR_FLAG_RETURN = 2 << 16;
- public const int zPAR_FLAG_CLASSVAR = 4 << 16;
- public const int zPAR_FLAG_EXTERNAL = 8 << 16;
- public const int zPAR_FLAG_MERGED = 16 << 16;
- #endregion
- }
- }
Add Comment
Please, Sign In to add comment