public static bool ChangeVarValue(byte[] data, File.Code code, string name, int from_value, int to_value) { ErrorContext context = new ErrorContext(code.Name); Ast.ILBlock block = code.Block; bool found = false; foreach (Ast.ILExpression expr in block.GetSelfAndChildrenRecursive <Ast.ILExpression>(x => x.Code == GMCode.Assign)) { Ast.ILVariable v = expr.Arguments[0].Operand as Ast.ILVariable; Ast.ILValue value; if (v.Name == name && Ast.PatternMatching.Match(expr.Arguments[1], GMCode.Constant, out value) && value.IntValue == from_value) { found = true; Context.dataWinChanged |= true; Debug.Assert(value.DataOffset != null); int offset = (int)value.DataOffset; if (value.Type == GM_Type.Short) { ChangeOffset(data, (uint)offset, (short)to_value); } else { ChangeOffset(data, (uint)offset, to_value); } context.Message("Changed {0}={1} to {0}={2} at offset 0x{3:X8}", name, from_value, to_value, (int)value.DataOffset); } } if (!found) { context.Message("Could Not find var '{0}'", name); } return(found); }
static void Main(string[] args) { // Context.doThreads = false; // Context.doXML = true; // Context.doAssigmentOffsets = true; // ugh have to do it here? string dataWinFileName = args.ElementAtOrDefault(0); if (string.IsNullOrWhiteSpace(dataWinFileName)) { InstructionError("Missing data.win file"); } try { File.LoadDataWin(dataWinFileName); } catch (Exception e) { Context.Error(e); InstructionError("Could not open data.win file {0}\n Exception:", dataWinFileName, e.Message); } List <string> chunks = new List <string>(); byte[] changedData = null; for (int i = 1; i < args.Length; i++) { string a = args[i]; if (string.IsNullOrWhiteSpace(a)) { continue; // does this ever happen? } switch (a) { case "-printOffset": { Context.saveChangedDataWin = true; string offset_name = args.ElementAtOrDefault(i + 1); i += 1; uint offset_int; if (!TryParseOffset(offset_name, out offset_int)) { Context.FatalError("Cannot parse {0} value in -printOffset", offset_name); } Context.Message(Context.FormatDebugOffset(changedData ?? File.DataWinRaw, (int)offset_int)); } break; case "-changeInt": case "-changeShort": { Context.saveChangedDataWin = true; string offset_name = args.ElementAtOrDefault(i + 1); string to_value = args.ElementAtOrDefault(i + 2); i += 2; uint offset_int; int to_int; if (!TryParseOffset(offset_name, out offset_int)) { Context.FatalError("Cannot parse {0} value in -changeShort", offset_name); } if (!TryParseHex(to_value, out to_int)) { Context.FatalError("Cannot parse {0} value in -changeShort", to_value); } if (changedData == null) { changedData = File.CopyData(); File.LoadEveything(); } if (a == "-changeShort") { File.ChangeOffset(changedData, offset_int, (short)to_int); } else { File.ChangeOffset(changedData, offset_int, to_int); } } break; case "-changeVar": { Context.saveChangedDataWin = true; string code_name = args.ElementAtOrDefault(i + 1); string var_name = args.ElementAtOrDefault(i + 2) ?? ""; string from_value = args.ElementAtOrDefault(i + 3) ?? ""; string to_value = args.ElementAtOrDefault(i + 4) ?? ""; int from_int; int to_int; if (!TryParseHex(from_value, out from_int)) { Context.FatalError("Cannot parse {0} value in -change", from_value); } if (!TryParseHex(to_value, out to_int)) { Context.FatalError("Cannot parse {0} value in -change", to_value); } i += 4; if (changedData == null) { changedData = File.CopyData(); File.LoadEveything(); } File.Code code = null; File.Script script = null; if (File.TryLookup(code_name, out code) || File.TryLookup(code_name, out script)) { if (script != null) { code = script.Code; } File.ChangeVarValue(changedData, code, var_name, from_int, to_int); } else { Context.Error("'{0}' code/script not found", code_name); } } break; case "-output": { i++; string dir = args.ElementAtOrDefault(i); if (string.IsNullOrWhiteSpace(dir)) { InstructionError("Missing otuput directory"); } Context.CheckAndSetOutputDirectory(dir); } break; case "-delete": Context.deleteDirectorys = true; break; case "-lua": Context.doLua = true; Context.doXML = false; break; case "-oneFile": Context.oneFile = true; break; case "-constOffsets": Context.doAssigmentOffsets = true; break; case "-mask": Context.saveAllMasks = true; break; case "-png": Context.saveAllPngs = true; break; case "-xml": Context.doXML = true; break; case "-search": Context.doSearch = true; break; case "-json": Context.doXML = false; break; case "-old": Context.Version = UndertaleVersion.V10000; break; case "-debug": Context.Debug = true; break; case "-nothread": Context.doThreads = false; break; case "-watch": Context.debugSearch = true; break; default: if (a[0] == '-') { InstructionError("bad flag '{0}'", a); } if (char.IsLetter(a[0])) { chunks.Add(a); } break; } } Context.CheckAndSetOutputDirectory(); ErrorContext.StartErrorSystem(); if (Context.saveChangedDataWin) { if (changedData != null) { using (var file = Context.CreateFileStream("changed_data.win", FileMode.Create, true)) { file.Write(changedData, 0, changedData.Length); file.Flush(); } } } else { File.LoadEveything(); var w = new Writers.AllWriter(); if (Context.doSearch) { var results = File.Search(chunks); if (results.Count == 0) { Context.Error("No data found in search"); } string path = "."; if (Context.doThreads) { Parallel.ForEach(results, result => AllWriter.DoSingleItem(path, result)); } else { foreach (var result in results) { AllWriter.DoSingleItem(path, result); } } } else if (Context.debugSearch) { Context.doThreads = false; Context.Debug = true; var results = File.Search(chunks); if (results.Count == 0) { Context.FatalError("No data found in search"); } foreach (var f in new DirectoryInfo(".").GetFiles("*.txt")) { if (System.IO.Path.GetFileName(f.Name) != "errors.txt") { f.Delete(); // clear out eveything } } foreach (var a in results) { File.Code c = a as File.Code; if (c != null) { var error = new ErrorContext(c.Name); error.Message("Decompiling"); Context.Debug = true; var block = c.Block; if (block != null) { using (Writers.BlockToCode to = new Writers.BlockToCode(c.Name + "_watch.js")) to.Write(block); error.Message("Finished Decompiling"); } else { error.Message("Block is null"); } } else { Context.Error("Code '{0} not found", a); } } //Context.HackyDebugWatch = new HashSet<string>(chunks); // w.AddAction("code"); } else { if (chunks.Count == 0) { chunks.Add("everything"); } foreach (var a in chunks) { w.AddAction(a); } } w.FinishProcessing(); } GoodExit(); }