private void ReadSPTR(int size, ref BinaryReader reader) { if (HexenFaked) { int numScripts = size / 8; for (int i = 0; i < numScripts; i++) { short number = reader.ReadInt16(); ScriptType type = (ScriptType)reader.ReadByte(); int argc = reader.ReadByte(); int address = reader.ReadInt32(); AcsScript script = new AcsScript(number, type, argc, address); Scripts[number] = script; } } else { int numScripts = size / 12; for (int i = 0; i < numScripts; i++) { short number = reader.ReadInt16(); ScriptType type = (ScriptType)reader.ReadInt16(); int address = reader.ReadInt32(); int argc = reader.ReadInt32(); AcsScript script = new AcsScript(number, type, argc, address); Scripts[number] = script; } } }
private void ReadSNAM(int size, ref BinaryReader reader) { string[] names = ReadStringTable(ref reader, false, false); for (int i = 0; i < names.Length; i++) { AcsScript s = Scripts[-(i + 1)]; s.Name = names[i]; } }
private void ReadAcs95(ref BinaryReader reader) { int numPointers = reader.ReadInt32(); for (int i = 0; i < numPointers; i++) { int number = reader.ReadInt32(); int pointer = reader.ReadInt32(); int argc = reader.ReadInt32(); int id = number % 1000; int typeNum = number / 1000; ScriptType type = (ScriptType)typeNum; Console.WriteLine("Script " + id + " is of type " + type); long pos = InputStream.Position; AcsScript script = new AcsScript(number, type, argc, pointer); InputStream.Seek(pointer, SeekOrigin.Begin); int len = 0; while (reader.ReadInt32() != (int)OpcodeEnum.Terminate) { len++; } InputStream.Seek(pointer, SeekOrigin.Begin); script.Code = AcsInstruction.ReadCode(this, ref reader, len); InputStream.Seek(pos, SeekOrigin.Begin); Scripts[number] = script; } int stringCount = reader.ReadInt32(); for (int i = 0; i < stringCount; i++) { int pointer = reader.ReadInt32(); long pos = InputStream.Position; InputStream.Seek(pointer, SeekOrigin.Begin); StringTable.Add(ReadString()); InputStream.Seek(pos, SeekOrigin.Begin); } }
private int FindClosestPointer(int p) { const int def = Int32.MaxValue; int r = def; foreach (var pair in Scripts) { AcsScript script = pair.Value; int ptr = script.Pointer; if (p > ptr || p == ptr) { continue; } r = Math.Min(ptr, r); } for (int i = 0; i < FunctionList.Count; i++) { int ptr = FunctionList[i].Pointer; if (p > ptr || p == ptr) { continue; } r = Math.Min(ptr, r); } if (r == def && DirOffset > p) { r = DirOffset; } if (r == def) { r = (int)InputStream.Length - 1; } Console.WriteLine($"Closest to {p} is {r}"); return(r); }
private void ReadCode(ref BinaryReader reader) { foreach (var script in Scripts) { int num = script.Key; AcsScript s = script.Value; s.CodeSize = FindClosestPointer(s.Pointer) - s.Pointer; InputStream.Seek(s.Pointer, SeekOrigin.Begin); s.Code = AcsInstruction.ReadCode(this, ref reader, s.CodeSize); } foreach (var func in FunctionList) { func.CodeSize = FindClosestPointer(func.Pointer) - func.Pointer; InputStream.Seek(func.Pointer, SeekOrigin.Begin); func.Code = AcsInstruction.ReadCode(this, ref reader, func.CodeSize); } }
public void Disassemble(Stream outputStream) { OutputStream = outputStream; AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName(); WriteLine("// Disassembled by " + assemblyName.Name + " version " + assemblyName.Version); WriteLine("//"); WriteLine("// String Table:"); for (int i = 0; i < StringTable.Count; i++) { WriteLine($"// {i,4} " + StringTable[i]); } WriteLine(); if (Format == AcsFormat.Acs95) { WriteLine("#include \"common.acs\""); } else { WriteLine("#include \"zcommon.acs\""); } WriteLine(); foreach (var library in Libraries) { WriteLine($"#import \"{library}\""); } WriteLine(); WriteLine("// ================================================== MAP ARRAYS"); WriteLine(); if (ImportedMapArrays.Count > 0) { WriteLine($"/* Imported map arrays ({ImportedMapArrays.Count}:"); foreach (KeyValuePair <int, ImportedArray> pair in ImportedMapArrays) { int index = pair.Key; ImportedArray array = pair.Value; WriteLine($"/* imported - index {index:x4} */ int {array.Name}[{array.Size}];"); } WriteLine("//*/"); } foreach (var pair in MapArrays) { int index = pair.Key; MapArray mapArray = pair.Value; int[] array = mapArray.Values; string name = (!String.IsNullOrEmpty(mapArray.Name) ? mapArray.Name : $"_a_{index:x4}_"); string type = (mapArray.IsString ? "str" : "int"); Write($"{type} {name}[{array.Length}] = " + "{"); for (int i = 0; i < array.Length; i++) { if (mapArray.IsString) { string s; int sI = array[i]; if (sI < StringTable.Count) { s = StringTable[array[i]]; } else { s = "(DeACC: Invalid string index " + sI + ")"; } Write($"\"{s}\""); } else { Write(array[i].ToString()); } if (i < array.Length - 1) { Write(", "); } } WriteLine("};"); } WriteLine(); WriteLine("// ================================================== MAP VARIABLES"); WriteLine(); if (ImportedMapVariables.Count > 0) { WriteLine($"/* Imported map variables ({ImportedMapVariables.Count}:"); foreach (KeyValuePair <int, string> pair in ImportedMapVariables) { int index = pair.Key; string name = pair.Value; WriteLine($"int {name}; // imported - index {index:x4}"); } WriteLine("//*/"); } foreach (var pair in MapVariables) { int index = pair.Key; MapVariable var = pair.Value; string type = (var.IsString ? "str" : "int"); WriteLine($"{type} {var.Name} = {var.Value};"); } WriteLine(); WriteLine("// ================================================== FUNCTIONS"); WriteLine(); foreach (KeyValuePair <string, AcsFunction> pair in FunctionMap) { string name = pair.Key; AcsFunction function = pair.Value; string returnType = (function.Returns ? "int" : "void"); string args; if (function.NumberOfArguments > 0) { args = ""; for (int i = 0; i < function.NumberOfArguments; i++) { args += $"int _p_{ParameterCounter:x4}_"; ParameterCounter++; if (i < function.NumberOfArguments - 1) { args += ", "; } } } else { args = "void"; } WriteLine($"// Pointer: {function.Pointer}; Size = {function.CodeSize}"); WriteLine($"function {returnType} {name} ({args})"); WriteLine("{"); WriteCode(function.Code); WriteLine("}"); WriteLine(); } WriteLine(); WriteLine("// ================================================== SCRIPTS"); WriteLine(); foreach (KeyValuePair <int, AcsScript> pair in Scripts) { int number = pair.Key; AcsScript script = pair.Value; string args = "(void)"; string type = ""; string flags = ""; if (script.NumberOfArguments > 0) { args = "("; for (int i = 0; i < script.NumberOfArguments; i++) { args += $"int _p_{ParameterCounter:x4}_"; ParameterCounter++; if (i < script.NumberOfArguments - 1) { args += ", "; } } args += ")"; } else if (script.NumberOfArguments == 0 && script.Type != ScriptType.Closed) { args = ""; } if (script.Type != ScriptType.Closed) { type = script.Type.ToString().ToUpper(); } if ((script.Flags & (int)ScriptFlags.Net) != 0) { flags += "NET "; } if ((script.Flags & (int)ScriptFlags.Clientside) != 0) { flags += "CLIENTSIDE "; } string argsSpace = (String.IsNullOrEmpty(args) ? "" : " "); string typeSpace = (script.Type != ScriptType.Closed ? " " : ""); string name = (String.IsNullOrEmpty(script.Name) ? number.ToString() : $"\"{script.Name}\""); WriteLine($"// Pointer: {script.Pointer}; Size = {script.CodeSize}"); WriteLine($"Script {name}{argsSpace}{args}{typeSpace}{type} {flags}"); WriteLine("{"); WriteCode(script.Code); WriteLine("}"); WriteLine(); } }