private int GenerateSpecialStructProp(TreeNode t, string s, int pos, PropertyReader.Property prop) { if (pos > memory.Length) { throw new Exception(": tried to read past bounds of Export Data"); } int n; TreeNode node; UnrealObjectInfo.PropertyInfo propInfo; switch (prop.TypeVal) { case PropertyReader.Type.FloatProperty: s += BitConverter.ToSingle(memory, pos).ToString("0.0######"); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafFloat; t.Nodes.Add(node); pos += 4; break; case PropertyReader.Type.IntProperty: s += BitConverter.ToInt32(memory, pos).ToString(); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafInt; t.Nodes.Add(node); pos += 4; break; case PropertyReader.Type.ObjectProperty: n = BitConverter.ToInt32(memory, pos); s += n + " (" + pcc.getObjectName(n) + ")"; node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafObject; t.Nodes.Add(node); pos += 4; break; case PropertyReader.Type.StringRefProperty: n = BitConverter.ToInt32(memory, pos); s += "#" + n + ": "; s += TalkFiles.tlkList.Count == 0 ? "(.tlk not loaded)" : TalkFiles.findDataById(n); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafInt; t.Nodes.Add(node); pos += 4; break; case PropertyReader.Type.NameProperty: n = BitConverter.ToInt32(memory, pos); pos += 4; s += "\"" + pcc.getNameEntry(n) + "\"_" + BitConverter.ToInt32(memory, pos); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafName; t.Nodes.Add(node); pos += 4; break; case PropertyReader.Type.BoolProperty: s += (memory[pos] > 0).ToString(); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafBool; t.Nodes.Add(node); pos += 1; break; case PropertyReader.Type.ByteProperty: if (prop.Size != 1) { string enumName = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name))?.reference; if (enumName != null) { s += "\"" + enumName + "\", "; } s += "\"" + pcc.getNameEntry(BitConverter.ToInt32(memory, pos)) + "\""; node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafEnum; t.Nodes.Add(node); pos += 8; } else { s += "(byte)" + memory[pos].ToString(); node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafByte; t.Nodes.Add(node); pos += 1; } break; case PropertyReader.Type.StrProperty: n = BitConverter.ToInt32(memory, pos); pos += 4; s += "\""; for (int i = 0; i < n - 1; i++) { s += (char)memory[pos + i * 2]; } s += "\""; node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafStr; t.Nodes.Add(node); pos += n * 2; break; case PropertyReader.Type.ArrayProperty: n = BitConverter.ToInt32(memory, pos); s += n + " elements"; node = new TreeNode(s); node.Name = pos.ToString(); node.Tag = nodeType.StructLeafArray; pos += 4; propInfo = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name)); UnrealObjectInfo.ArrayType arrayType = UnrealObjectInfo.getArrayType(propInfo); TreeNode node2; string s2; for (int i = 0; i < n; i++) { if (arrayType == UnrealObjectInfo.ArrayType.Struct) { readerpos = pos; node2 = new TreeNode(i + ": (" + propInfo.reference + ")"); node2.Name = (-pos).ToString(); node2.Tag = nodeType.StructLeafStruct; GenerateSpecialStruct(node2, propInfo.reference, 0); node.Nodes.Add(node2); pos = readerpos; } else { s2 = ""; PropertyReader.Type type = PropertyReader.Type.None; int size = 0; switch (arrayType) { case UnrealObjectInfo.ArrayType.Object: type = PropertyReader.Type.ObjectProperty; break; case UnrealObjectInfo.ArrayType.Name: type = PropertyReader.Type.NameProperty; break; case UnrealObjectInfo.ArrayType.Byte: type = PropertyReader.Type.ByteProperty; size = 1; break; case UnrealObjectInfo.ArrayType.Enum: type = PropertyReader.Type.ByteProperty; break; case UnrealObjectInfo.ArrayType.Bool: type = PropertyReader.Type.BoolProperty; break; case UnrealObjectInfo.ArrayType.String: type = PropertyReader.Type.StrProperty; break; case UnrealObjectInfo.ArrayType.Float: type = PropertyReader.Type.FloatProperty; break; case UnrealObjectInfo.ArrayType.Int: type = PropertyReader.Type.IntProperty; break; } pos = GenerateSpecialStructProp(node, s2, pos, new PropertyReader.Property { TypeVal = type, Size = size }); } } t.Nodes.Add(node); break; case PropertyReader.Type.StructProperty: propInfo = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name)); s += propInfo.reference; node = new TreeNode(s); node.Name = (-pos).ToString(); node.Tag = nodeType.StructLeafStruct; readerpos = pos; GenerateSpecialStruct(node, propInfo.reference, 0); pos = readerpos; t.Nodes.Add(node); break; case PropertyReader.Type.DelegateProperty: throw new NotImplementedException($"at position {pos.ToString("X4")}: cannot read Delegate property of Immutable struct"); case PropertyReader.Type.Unknown: throw new NotImplementedException($"at position {pos.ToString("X4")}: cannot read Unkown property of Immutable struct"); case PropertyReader.Type.None: default: break; } return(pos); }
public TreeNode GenerateNode(PropHeader p) { string s = p.offset.ToString("X4") + ": "; s += "Name: \"" + pcc.getNameEntry(p.name) + "\" "; s += "Type: \"" + pcc.getNameEntry(p.type) + "\" "; s += "Size: " + p.size.ToString() + " Value: "; nodeType propertyType = getType(pcc.getNameEntry(p.type)); int idx; byte val; switch (propertyType) { case nodeType.IntProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += idx.ToString(); break; case nodeType.ObjectProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += idx.ToString() + " (" + pcc.getObjectName(idx) + ")"; break; case nodeType.StrProperty: int count = BitConverter.ToInt32(memory, p.offset + 24); s += "\""; for (int i = 0; i < count * -1 - 1; i++) { s += (char)memory[p.offset + 28 + i * 2]; } s += "\""; break; case nodeType.BoolProperty: val = memory[p.offset + 24]; s += (val == 1).ToString(); break; case nodeType.FloatProperty: float f = BitConverter.ToSingle(memory, p.offset + 24); s += f.ToString("0.0######"); break; case nodeType.NameProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += "\"" + pcc.getNameEntry(idx) + "\"_" + BitConverter.ToInt32(memory, p.offset + 28); break; case nodeType.StructProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += "\"" + pcc.getNameEntry(idx) + "\""; break; case nodeType.ByteProperty: if (p.size == 1) { val = memory[p.offset + 32]; s += val.ToString(); } else { idx = BitConverter.ToInt32(memory, p.offset + 24); int idx2 = BitConverter.ToInt32(memory, p.offset + 32); s += "\"" + pcc.getNameEntry(idx) + "\",\"" + pcc.getNameEntry(idx2) + "\""; } break; case nodeType.ArrayProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += idx.ToString() + "(count)"; break; case nodeType.StringRefProperty: idx = BitConverter.ToInt32(memory, p.offset + 24); s += "#" + idx.ToString() + ": "; s += TalkFiles.tlkList.Count == 0 ? "(.tlk not loaded)" : TalkFiles.findDataById(idx); break; } TreeNode ret = new TreeNode(s); ret.Tag = propertyType; ret.Name = p.offset.ToString(); return(ret); }
static void Main(string[] args) { var options = new Options(); CommandLine.Parser parser = new CommandLine.Parser(s => { s.MutuallyExclusive = true; s.CaseSensitive = true; s.HelpWriter = Console.Out; }); if (parser.ParseArguments(args, options)) { //Package p = new Package(options.TargetFile); //endProgram(0); // Values are available here if (options.Verbose) { Verbose = true; writeVerboseLine("Verbose logging is enabled"); } if (options.Compress && !Environment.Is64BitProcess) { Console.WriteLine("Not 64-bit process - Disabling compression due to bugs in zlib."); options.Compress = false; } if (options.GameDir != null) { if (Directory.Exists(options.GameDir)) { GamePath = options.GameDir; if (!GamePath.EndsWith("\\")) { GamePath += "\\"; } Console.WriteLine("Game path set to " + GamePath); } else { Console.Error.WriteLine("Specified game dir doesn't exist: " + options.GameDir); endProgram(CODE_INPUT_FOLDER_NOT_FOUND); } } if (options.InputFile == null && options.InputFolder == null) { Console.Error.WriteLine("--inputfile or --inputfolder argument is required for all operations."); Console.Error.WriteLine(options.GetUsage()); endProgram(CODE_NO_INPUT); } if (options.InputFile != null && !File.Exists(options.InputFile)) { Console.Error.WriteLine("Input file does not exist: " + options.InputFile); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (options.InputFolder != null && !options.InputFolder.EndsWith(@"\")) { options.InputFolder = options.InputFolder + @"\"; } if (options.InputFolder != null && !Directory.Exists(options.InputFolder)) { Console.Error.WriteLine("Input folder does not exist: " + options.InputFolder); endProgram(CODE_INPUT_FOLDER_NOT_FOUND); } if (options.OutputFolder != null) { if (!options.OutputFolder.EndsWith("\\")) { options.OutputFolder += "\\"; } Console.WriteLine("Redirecting output to " + options.OutputFolder); } //Operation Switch if (options.VerifyPCC) { if (options.InputFile != null) { Console.WriteLine("Checking PCC can load " + options.TargetFile); int result = VerifyPCC(options.InputFile); } else { Console.Error.WriteLine("Can only verify single pcc integrity, --inputfile is the only allowed input for this operation."); endProgram(CODE_INPUT_FILE_NOT_FOUND); } } else if (options.PathFindingDump) { if (options.InputFile != null) { Console.WriteLine("Dumping Pathfinding on file " + options.InputFile); bool[] dumpargs = new bool[] { false, false, false, false, false, false, false, false, true, false }; //meshmap only dumpPCCFile(options.InputFile, dumpargs, options.OutputFolder); } endProgram(0); } else if (options.GUIScan) { if (options.InputFile != null) { Console.WriteLine("Scanning for whitelisted GFxMovieInfo exports on " + options.InputFile); endProgram(doesPCCContainGUIs(options.InputFile, false) ? 1 : 0); } else { Console.Error.WriteLine("Can only scan 1 pcc at a time, --inputfile is the only allowed input for this operation."); endProgram(2); } } else if (options.DMSQL) { if (options.InputFile != null) { Console.WriteLine("Dumping SQL from " + options.InputFile); dumpDynamicMixInsFromPCC(options.InputFile); Console.WriteLine("done"); endProgram(0); } else { Console.Error.WriteLine("Can only scan 1 pcc at a time, --inputfile is the only allowed input for this operation."); endProgram(2); } } else if (options.DWSQL) { if (options.InputFolder != null) { Console.WriteLine("Dumping Weapon SQL from " + options.InputFolder); dumpModMakerWeaponDynamicSQL(options.InputFolder); Console.WriteLine("done"); endProgram(0); } else { Console.Error.WriteLine("Can only scan 1 pcc at a time, --inputfile is the only allowed input for this operation."); endProgram(2); } } else if (options.Inject) { if (options.TargetFile == null) { Console.Error.WriteLine("--targetfile is required for this operation."); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (!File.Exists(options.TargetFile)) { Console.Error.WriteLine("Target file does not exist: " + options.TargetFile); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (options.Compress) { Console.WriteLine("Compression option is enabled."); } if (options.InputFile != null) { Console.WriteLine("Injecting SWF into " + options.TargetFile); endProgram(replaceSingleSWF(options.InputFile, options.TargetFile, options.TargetExport)); } else if (options.InputFolder != null) { Console.WriteLine("Injecting SWFs into " + options.TargetFile); endProgram(replaceSWFs_MEM(options.InputFolder, options.TargetFile, options.Compress)); } } else if (options.GuiExtract) { if (options.InputFile != null) { writeVerboseLine("Extracting GFX files from " + options.InputFile); extractAllGFxMovies(options.InputFile, options.OutputFolder); } else if (options.InputFolder != null) { writeVerboseLine("Extracting GFX files from " + options.InputFolder); extractAllGFxMoviesFromFolder(options.InputFolder, options.OutputFolder); } } else if (options.ExecDump) { if (options.InputFile != null) { writeVerboseLine("Dumping all Exec functions from " + options.InputFile); dumpAllExecFromFile(options.InputFile, options.OutputFolder); } if (options.InputFolder != null) { writeVerboseLine("Dumping all Exec functions from " + options.InputFolder); dumpAllExecFromFolder(options.InputFolder, options.OutputFolder); } } else if (options.Extract) { if (options.Imports || options.Exports || options.Data || options.Scripts || options.Coalesced || options.Names || options.SWFs) { if (options.Data) { options.Exports = true; } bool[] dumpargs = new bool[] { options.Imports, options.Exports, options.Data, options.Scripts, options.Coalesced, options.Names, !options.LineSeparator, options.Properties, false, options.SWFs }; if ((options.InputFile != null || options.InputFolder != null) && options.TlkCachePath != null && Directory.Exists(options.TlkCachePath)) { //Load TLKs var ext = new List <string> { "tlk" }; var tlks = Directory.EnumerateFiles(options.TlkCachePath, "*INT.tlk", SearchOption.AllDirectories); Console.WriteLine("Loading " + tlks.Count() + " TLK(s) from " + options.TlkCachePath); foreach (string tlk in tlks) { TalkFiles.addTLK(tlk); } } if (options.InputFile != null) { Console.Out.WriteLine("Dumping pcc data of " + options.InputFile + " [Imports: " + options.Imports + ", Exports: " + options.Exports + ", Data: " + options.Data + ", Scripts: " + options.Scripts + ", Coalesced: " + options.Coalesced + ", Names: " + options.Names + ", Properties: " + options.Properties + ", SWF: " + options.SWFs + "]"); dumpPCCFile(options.InputFile, dumpargs, options.OutputFolder); } if (options.InputFolder != null) { Console.Out.WriteLine("Dumping pcc data from " + options.InputFolder + " [Imports: " + options.Imports + ", Exports: " + options.Exports + ", Data: " + options.Data + ", Scripts: " + options.Scripts + ", Coalesced: " + options.Coalesced + ", Names: " + options.Names + ", Properties: " + options.Properties + ", SWF: " + options.SWFs + "]"); dumpPCCFolder(options.InputFolder, dumpargs, options.OutputFolder); } } else { Console.Error.WriteLine("Nothing was selected to dump. Use --scripts, --names, --data, --imports, --exports, --swf or --coalesced to dump items from a pcc."); endProgram(CODE_NO_DATA_TO_DUMP); } } else if (options.Transplant) { if (options.InputFile == null) { Console.Error.WriteLine("--transplant requires --inputfile."); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (options.TargetFile == null) { Console.Error.WriteLine("--targetfile is required for this operation."); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (!File.Exists(options.TargetFile)) { Console.Error.WriteLine("Target file does not exist: " + options.TargetFile); endProgram(CODE_INPUT_FILE_NOT_FOUND); } if (options.TargetFile.ToLower() == options.InputFile.ToLower()) { Console.Error.WriteLine("Cannot transplant GUI files into self"); endProgram(CODE_SAME_IN_OUT_FILE); } Console.WriteLine("Transplanting GUI files from " + options.InputFile + " to " + options.TargetFile); Console.WriteLine("Extracting GUI files"); string gfxfolder = AppDomain.CurrentDomain.BaseDirectory + @"extractedgfx\"; writeVerboseLine("Extracting GFX Files from source to " + gfxfolder); extractAllGFxMovies(options.InputFile, gfxfolder); Console.WriteLine("Installing GUI files"); replaceSWFs(gfxfolder, options.TargetFile, options.Compress); } else { Console.Error.WriteLine("No operation was specified"); Console.Error.WriteLine(options.GetUsage()); endProgram(CODE_NO_OPERATION); } } endProgram(0); }