/// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> private static string DecompileCommand(byte[] data) { MeleeCMDAction act = ActionCommon.GetMeleeCMDAction((byte)(data[0] >> 2)); string o = act.Name + "("; if (act != null) { o += act.Decompile(data); } else { for (int i = 0; i < data.Length; i++) { if (i == 0) { o += "0x" + (data[i] & 0x3).ToString("x"); } else { o += ",0x" + data[i].ToString("x"); } } } o += ");"; return(o); }
private static byte[] CompileCommand(string name, string[] parameters) { if (name.Equals("")) { return(new byte[0]); } MeleeCMDAction action = ActionCommon.GetMeleeCMDAction(name); byte[] data = new byte[] { (byte)(action.Command << 2), 0, 0, 0 }; if (action != null) { data = action.Compile(parameters); if (data == null) { //ErrorCode = CompileError.ParameterCount; return(null); } } return(data); }
/// <summary> /// /// </summary> /// <param name="output"></param> /// <param name="name"></param> /// <param name="datas"></param> /// <param name="structToFunctionName"></param> private void DecompileGroup(StringBuilder output, string name, HSDStruct datas) { if (structToFunctionName.ContainsKey(datas)) { return; } structToFunctionName.Add(datas, name); output.AppendLine(name); output.AppendLine("{"); using (BinaryReaderExt r = new BinaryReaderExt(new MemoryStream(datas.GetData()))) { byte flag = (byte)(r.ReadByte() >> 2); var cmd = ActionCommon.GetMeleeCMDAction(flag); while (flag != 0) { r.BaseStream.Position -= 1; var size = cmd.ByteSize; var command = r.GetSection(r.Position, size); r.Skip((uint)size); if (flag == 5 || flag == 7) //goto { var re = datas.GetReference <HSDAccessor>((int)r.BaseStream.Position - 4); if (re != null) { if (!tempStructToName.ContainsKey(re._s)) { if (structToFunctionName.ContainsKey(re._s)) { tempStructToName.Add(re._s, structToFunctionName[re._s]); } else { tempStructToName.Add(re._s, name + "_" + ((int)r.BaseStream.Position - 4).ToString("X4")); } } var funcname = tempStructToName[re._s]; output.AppendLine("\t" + (flag == 5 ? "Goto" : "Subroutine") + "(" + funcname + ");"); } } else { output.AppendLine("\t" + DecompileCommand(command)); } if (r.BaseStream.Position >= r.BaseStream.Length) { break; } flag = (byte)(r.ReadByte() >> 2); cmd = ActionCommon.GetMeleeCMDAction(flag); } } output.AppendLine("}"); foreach (var re in datas.References) { DecompileGroup(output, name + "_" + re.Key.ToString("X4"), re.Value); } }
/// <summary> /// Compiles script into subaction byte code /// </summary> public static void Compile(string script) { if (scriptToBinary.ContainsKey(script) || scriptToReference.ContainsKey(script)) { return; } HSDStruct main = null; var stream = Regex.Replace(script, @"\s+", string.Empty); if (script.StartsWith("ref:")) { var name = stream.Split(':')[1]; scriptToReference.Add(script, name); return; } var functions = Regex.Matches(stream, @"([^\{])*\{([^\}]*)\}"); foreach (Match g in functions) { var name = Regex.Match(g.Value, @".+?(?={)").Value; var code = Regex.Match(g.Value, @"(?<=\{).+?(?=\})").Value.Split(';'); if (nameToFunction.ContainsKey(name)) { continue; } HSDStruct s = new HSDStruct(); nameToFunction.Add(name, s); structToOffsetToFunction.Add(s, new Dictionary <int, string>()); if (main == null) { main = s; } List <byte> output = new List <byte>(); bool returned = false; foreach (var c in code) { var cname = Regex.Match(c, @".+?(?=\()").Value; var cparameters = Regex.Match(c, @"(?<=\().+?(?=\))").Value.Split(','); if (cname == "Return") { returned = true; } byte flag = ActionCommon.GetMeleeCMDAction(cname).Command; if (flag == 0x5 || flag == 0x7) //goto and subroutine { structToOffsetToFunction[s].Add(output.Count + 4, cparameters[0]); output.AddRange(new byte[] { (byte)(flag << 2), 0, 0, 0, 0, 0, 0, 0 }); } else { output.AddRange(CompileCommand(cname, cparameters)); } // padd if (output.Count % 4 != 0) { output.AddRange(new byte[4 - (output.Count % 4)]); } } if (true) { output.Add(0); if (output.Count % 4 != 0) { output.AddRange(new byte[4 - (output.Count % 4)]); } } s.SetData(output.ToArray()); } if (main == null) { main = new HSDStruct(4); } scriptToBinary.Add(script, main); }