private void ReadImports(MemoryStream fs) { DebugOutput.PrintLn("Reading Imports..."); imports = new List <ImportEntry>(); fs.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { ImportEntry import = new ImportEntry(this, fs); import.Index = i; import.PropertyChanged += importChanged; imports.Add(import); } }
public static string FollowLink(this IMEPackage pcc, int uIndex) { if (pcc.isUExport(uIndex)) { ExportEntry parent = pcc.getUExport(uIndex); return(pcc.FollowLink(parent.idxLink) + parent.ObjectName + "."); } if (pcc.isImport(uIndex)) { ImportEntry parent = pcc.getImport(uIndex); return(pcc.FollowLink(parent.idxLink) + parent.ObjectName + "."); } return(""); }
public void addImport(ImportEntry importEntry) { if (importEntry.FileRef != this) { throw new Exception("you cannot add a new import entry from another package file, it has invalid references!"); } importEntry.Index = imports.Count; imports.Add(importEntry); importEntry.EntryHasPendingChanges = true; ImportCount = imports.Count; OnPropertyChanged(nameof(ImportCount)); }
public void addImport(ImportEntry importEntry) { if (importEntry.FileRef != this) { throw new Exception("you cannot add a new import entry from another pcc file, it has invalid references!"); } importEntry.Index = imports.Count; importEntry.PropertyChanged += importChanged; imports.Add(importEntry); ImportCount = imports.Count; updateTools(PackageChange.ImportAdd, ImportCount - 1); }
//if neccessary, will fill in parents as Package Imports (if the import you need has non-Package parents, don't use this method) public static IEntry getEntryOrAddImport(this IMEPackage pcc, string fullPath, string className = "Class", string packageFile = "Core") { if (string.IsNullOrEmpty(fullPath)) { return(null); } //see if this import exists locally foreach (ImportEntry imp in pcc.Imports) { if (imp.GetFullPath == fullPath) { return(imp); } } //see if this is an export and exists locally foreach (ExportEntry exp in pcc.Exports) { if (exp.GetFullPath == fullPath) { return(exp); } } string[] pathParts = fullPath.Split('.'); IEntry parent = pcc.getEntryOrAddImport(string.Join(".", pathParts.Take(pathParts.Length - 1)), "Package"); var import = new ImportEntry(pcc) { idxLink = parent?.UIndex ?? 0, idxClassName = pcc.FindNameOrAdd(className), idxObjectName = pcc.FindNameOrAdd(pathParts.Last()), idxPackageFile = pcc.FindNameOrAdd(packageFile) }; pcc.addImport(import); return(import); }
private ME2Package(string path) { DebugOutput.PrintLn("Load file : " + path); FileName = Path.GetFullPath(path); MemoryStream tempStream = new MemoryStream(); if (!File.Exists(FileName)) { throw new FileNotFoundException("PCC file not found"); } using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { FileInfo tempInfo = new FileInfo(FileName); tempStream.WriteFromStream(fs, tempInfo.Length); if (tempStream.Length != tempInfo.Length) { throw new FileLoadException("File not fully read in. Try again later"); } } tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadValueS32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerations = tempStream.ReadValueS32(); tempStream.Seek(36 + tempGenerations * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position; tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { DebugOutput.PrintLn("Magic number incorrect: " + magic); throw new FormatException("This is not a pcc file. The magic number is incorrect."); } MemoryStream listsStream; if (IsCompressed) { DebugOutput.PrintLn("File is compressed"); { listsStream = CompressionHelper.DecompressME1orME2(tempStream); //Correct the header IsCompressed = false; listsStream.Seek(0, SeekOrigin.Begin); listsStream.WriteBytes(header); //Set numblocks to zero listsStream.WriteValueS32(0); //Write the magic number listsStream.WriteValueS32(1026281201); //Write 8 bytes of 0 listsStream.WriteValueS32(0); listsStream.WriteValueS32(0); } } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); listsStream = tempStream; } names = new List <string>(); listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { int len = listsStream.ReadValueS32(); string s = listsStream.ReadString((uint)(len - 1)); //skipping irrelevant data listsStream.Seek(5, SeekOrigin.Current); names.Add(s); } imports = new List <ImportEntry>(); listsStream.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { ImportEntry import = new ImportEntry(this, listsStream); import.Index = i; import.PropertyChanged += importChanged; imports.Add(import); } exports = new List <IExportEntry>(); listsStream.Seek(ExportOffset, SeekOrigin.Begin); for (int i = 0; i < ExportCount; i++) { ME2ExportEntry exp = new ME2ExportEntry(this, listsStream); exp.Index = i; exp.PropertyChanged += exportChanged; exports.Add(exp); } }
private void ReadImports(MemoryStream fs) { DebugOutput.PrintLn("Reading Imports..."); imports = new List<ImportEntry>(); fs.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { ImportEntry import = new ImportEntry(this, fs); import.Index = i; import.PropertyChanged += importChanged; imports.Add(import); } }
/// <summary> /// UDKPackage class constructor. It also load namelist, importlist and exportinfo (not exportdata) from udk file /// </summary> /// <param name="UDKPackagePath">full path + file name of desired udk file.</param> /// <param name="create">Create a file instead of reading from disk</param> private UDKPackage(string UDKPackagePath, bool create = false) : base(Path.GetFullPath(UDKPackagePath)) { ME3ExpMemoryAnalyzer.MemoryAnalyzer.AddTrackedMemoryItem($"UDKPackage {Path.GetFileName(UDKPackagePath)}", new WeakReference(this)); if (create) { folderName = "None"; engineVersion = 12791; //reasonable defaults? Flags = EPackageFlags.AllowDownload | EPackageFlags.NoExportsData; return; } using (var fs = File.OpenRead(FilePath)) { #region Header uint magic = fs.ReadUInt32(); if (magic != packageTag) { throw new FormatException("Not an Unreal package!"); } ushort unrealVersion = fs.ReadUInt16(); ushort licenseeVersion = fs.ReadUInt16(); FullHeaderSize = fs.ReadInt32(); int foldernameStrLen = fs.ReadInt32(); //always "None", so don't bother saving result if (foldernameStrLen > 0) { folderName = fs.ReadStringASCIINull(foldernameStrLen); } else { folderName = fs.ReadStringUnicodeNull(foldernameStrLen * -2); } Flags = (EPackageFlags)fs.ReadUInt32(); //if (Flags.HasFlag(EPackageFlags.Compressed)) //{ // throw new FormatException("Cannot read compressed UDK packages!"); //} NameCount = fs.ReadInt32(); NameOffset = fs.ReadInt32(); ExportCount = fs.ReadInt32(); ExportOffset = fs.ReadInt32(); ImportCount = fs.ReadInt32(); ImportOffset = fs.ReadInt32(); DependencyTableOffset = fs.ReadInt32(); importExportGuidsOffset = fs.ReadInt32(); importGuidsCount = fs.ReadInt32(); exportGuidsCount = fs.ReadInt32(); thumbnailTableOffset = fs.ReadInt32(); PackageGuid = fs.ReadGuid(); uint generationsTableCount = fs.ReadUInt32(); if (generationsTableCount > 0) { generationsTableCount--; Gen0ExportCount = fs.ReadInt32(); Gen0NameCount = fs.ReadInt32(); Gen0NetworkedObjectCount = fs.ReadInt32(); } //don't care about other gens, so skip them fs.Skip(generationsTableCount * 12); engineVersion = fs.ReadInt32(); cookedContentVersion = fs.ReadInt32(); //skip compression type chunks. Decompressor will handle that long compressionInfoOffset = fs.Position; fs.SkipInt32(); int numChunks = fs.ReadInt32(); fs.Skip(numChunks * 16); packageSource = fs.ReadUInt32(); //additional packages to cook, and texture allocation, but we don't care about those, so we won't read them in. #endregion Stream inStream = fs; if (IsCompressed && numChunks > 0) { inStream = CompressionHelper.DecompressUDK(fs, compressionInfoOffset); } inStream.JumpTo(NameOffset); for (int i = 0; i < NameCount; i++) { names.Add(inStream.ReadUnrealString()); inStream.Skip(8); } inStream.JumpTo(ImportOffset); for (int i = 0; i < ImportCount; i++) { ImportEntry imp = new ImportEntry(this, inStream) { Index = i }; imp.PropertyChanged += importChanged; imports.Add(imp); } //read exportTable (ExportEntry constructor reads export data) inStream.JumpTo(ExportOffset); for (int i = 0; i < ExportCount; i++) { ExportEntry e = new ExportEntry(this, inStream) { Index = i }; e.PropertyChanged += exportChanged; exports.Add(e); } } }
private MEPackage(string filePath, MEGame forceGame = MEGame.Unknown) : base(Path.GetFullPath(filePath)) { ME3ExpMemoryAnalyzer.MemoryAnalyzer.AddTrackedMemoryItem($"MEPackage {Path.GetFileName(filePath)}", new WeakReference(this)); if (forceGame != MEGame.Unknown) { //new Package Game = forceGame; //reasonable defaults? Flags = EPackageFlags.Cooked | EPackageFlags.AllowDownload | EPackageFlags.DisallowLazyLoading | EPackageFlags.RequireImportsAlreadyLoaded; return; } using (var fs = File.OpenRead(filePath)) { #region Header uint magic = fs.ReadUInt32(); if (magic != packageTag) { throw new FormatException("Not an Unreal package!"); } ushort unrealVersion = fs.ReadUInt16(); ushort licenseeVersion = fs.ReadUInt16(); switch (unrealVersion) { case ME1UnrealVersion when licenseeVersion == ME1LicenseeVersion: Game = MEGame.ME1; break; case ME2UnrealVersion when licenseeVersion == ME2LicenseeVersion: Game = MEGame.ME2; break; case ME3UnrealVersion when licenseeVersion == ME3LicenseeVersion: Game = MEGame.ME3; break; default: throw new FormatException("Not a Mass Effect Package!"); } FullHeaderSize = fs.ReadInt32(); int foldernameStrLen = fs.ReadInt32(); //always "None", so don't bother saving result if (foldernameStrLen > 0) { fs.ReadStringASCIINull(foldernameStrLen); } else { fs.ReadStringUnicodeNull(foldernameStrLen * -2); } Flags = (EPackageFlags)fs.ReadUInt32(); if (Game == MEGame.ME3 && Flags.HasFlag(EPackageFlags.Cooked)) { fs.SkipInt32(); //always 0 } NameCount = fs.ReadInt32(); NameOffset = fs.ReadInt32(); ExportCount = fs.ReadInt32(); ExportOffset = fs.ReadInt32(); ImportCount = fs.ReadInt32(); ImportOffset = fs.ReadInt32(); DependencyTableOffset = fs.ReadInt32(); if (Game == MEGame.ME3) { ImportExportGuidsOffset = fs.ReadInt32(); fs.SkipInt32(); //ImportGuidsCount always 0 fs.SkipInt32(); //ExportGuidsCount always 0 fs.SkipInt32(); //ThumbnailTableOffset always 0 } PackageGuid = fs.ReadGuid(); uint generationsTableCount = fs.ReadUInt32(); if (generationsTableCount > 0) { generationsTableCount--; Gen0ExportCount = fs.ReadInt32(); Gen0NameCount = fs.ReadInt32(); Gen0NetworkedObjectCount = fs.ReadInt32(); } //should never be more than 1 generation, but just in case fs.Skip(generationsTableCount * 12); fs.SkipInt32(); //engineVersion Like unrealVersion and licenseeVersion, these 2 are determined by what game this is, fs.SkipInt32(); //cookedContentVersion so we don't have to read them in if (Game == MEGame.ME2 || Game == MEGame.ME1) { fs.SkipInt32(); //always 0 fs.SkipInt32(); //always 47699 unknown4 = fs.ReadInt32(); fs.SkipInt32(); //always 1 in ME1, always 1966080 in ME2 } unknown6 = fs.ReadInt32(); fs.SkipInt32(); //always -1 in ME1 and ME2, always 145358848 in ME3 if (Game == MEGame.ME1) { fs.SkipInt32(); //always -1 } //skip compression type chunks. Decompressor will handle that fs.SkipInt32(); int numChunks = fs.ReadInt32(); fs.Skip(numChunks * 16); packageSource = fs.ReadUInt32(); if (Game == MEGame.ME2 || Game == MEGame.ME1) { fs.SkipInt32(); //always 0 } //Doesn't need to be written out, so it doesn't need to be read in //keep this here in case one day we learn that this has a purpose /*if (Game == MEGame.ME2 || Game == MEGame.ME3) * { * int additionalPackagesToCookCount = fs.ReadInt32(); * var additionalPackagesToCook = new string[additionalPackagesToCookCount]; * for (int i = 0; i < additionalPackagesToCookCount; i++) * { * int strLen = fs.ReadInt32(); * if (strLen > 0) * { * additionalPackagesToCook[i] = fs.ReadStringASCIINull(strLen); * } * else * { * additionalPackagesToCook[i] = fs.ReadStringUnicodeNull(strLen * -2); * } * } * }*/ #endregion Stream inStream = fs; if (IsCompressed && numChunks > 0) { inStream = Game == MEGame.ME3 ? CompressionHelper.DecompressME3(fs) : CompressionHelper.DecompressME1orME2(fs); } //read namelist inStream.JumpTo(NameOffset); for (int i = 0; i < NameCount; i++) { names.Add(inStream.ReadUnrealString()); if (Game == MEGame.ME1) { inStream.Skip(8); } else if (Game == MEGame.ME2) { inStream.Skip(4); } } //read importTable inStream.JumpTo(ImportOffset); for (int i = 0; i < ImportCount; i++) { ImportEntry imp = new ImportEntry(this, inStream) { Index = i }; imp.PropertyChanged += importChanged; imports.Add(imp); } //read exportTable (ExportEntry constructor reads export data) inStream.JumpTo(ExportOffset); for (int i = 0; i < ExportCount; i++) { ExportEntry e = new ExportEntry(this, inStream) { Index = i }; e.PropertyChanged += exportChanged; exports.Add(e); } if (Game == MEGame.ME1) { ReadLocalTLKs(); } } }
public void RemoveTrailingTrash() { ExportEntry trashPackage = exports.FirstOrDefault(exp => exp.ObjectName == TrashPackageName); if (trashPackage == null) { return; } int trashPackageUIndex = trashPackage.UIndex; //make sure the first trashed export is the trashpackage foreach (ExportEntry exp in exports) { if (exp == trashPackage) { //trashpackage is the first trashed export, so we're good break; } if (exp.idxLink == trashPackageUIndex) { //turn this into trashpackage, turn old trashpackage into regular Trash, and point all trash entries to the new trashpackage exp.ObjectName = TrashPackageName; exp.idxLink = 0; exp.PackageGUID = TrashPackageGuid; trashPackage.ObjectName = "Trash"; trashPackage.idxLink = exp.UIndex; trashPackage.PackageGUID = Guid.Empty; foreach (IEntry entry in trashPackage.GetChildren()) { entry.idxLink = exp.UIndex; } trashPackage = exp; trashPackageUIndex = trashPackage.UIndex; break; } } //remove imports for (int i = ImportCount - 1; i >= 0; i--) { ImportEntry lastImport = imports[i]; if (lastImport.idxLink != trashPackageUIndex) { //non-trash import, so stop removing break; } imports.RemoveAt(i); } if (ImportCount != imports.Count) { ImportCount = imports.Count; OnPropertyChanged(nameof(ImportCount)); } //remove exports for (int i = ExportCount - 1; i >= 0; i--) { ExportEntry lastExport = exports[i]; if (lastExport.idxLink != trashPackageUIndex) { //non-trash export, so stop removing break; } exports.RemoveAt(i); } if (ExportCount != exports.Count) { ExportCount = exports.Count; OnPropertyChanged(nameof(ExportCount)); } //if there are no more trashed imports or exports, and if the TrashPackage is the last export, remove it if (exports.LastOrDefault() is ExportEntry finalExport && finalExport == trashPackage && trashPackage.GetChildren().IsEmpty()) { exports.Remove(trashPackage); } if (ExportCount != exports.Count) { ExportCount = exports.Count; OnPropertyChanged(nameof(ExportCount)); } }
private void importImport(IMEPackage importpcc, int n, int link) { ImportEntry imp = importpcc.getImport(n); ImportEntry nimp = new ImportEntry(pcc, imp.header); nimp.idxLink = link; nimp.idxClassName = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxClassName)); nimp.idxObjectName = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxObjectName)); nimp.idxPackageFile = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxPackageFile)); pcc.addImport(nimp); }
/// <summary> /// PCCObject class constructor. It also loads namelist, importlist, exportinfo, and exportdata from pcc file /// </summary> /// <param name="pccFilePath">full path + file name of desired pcc file.</param> private ME3Package(string pccFilePath) { FileName = Path.GetFullPath(pccFilePath); MemoryStream listsStream; names = new List <string>(); imports = new List <ImportEntry>(); exports = new List <ME3ExportEntry>(); using (FileStream pccStream = File.OpenRead(FileName)) { header = pccStream.ReadBytes(headerSize); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { throw new FormatException("not a pcc file"); } if (lowVers != 684 && highVers != 194) { throw new FormatException("unsupported version"); } if (IsCompressed) { listsStream = CompressionHelper.DecompressME3(pccStream); //correcting the header listsStream.Seek(0, SeekOrigin.Begin); listsStream.Read(header, 0, header.Length); } else { listsStream = new MemoryStream(); pccStream.Seek(0, SeekOrigin.Begin); pccStream.CopyTo(listsStream); } } // fill names list listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { long currOffset = listsStream.Position; int strLength = listsStream.ReadValueS32(); string str = listsStream.ReadString(strLength * -2, true, Encoding.Unicode); names.Add(str); } // fill import list listsStream.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { long offset = listsStream.Position; ImportEntry imp = new ImportEntry(this, listsStream); imp.Index = i; imp.PropertyChanged += importChanged; imports.Add(imp); } // fill export list listsStream.Seek(ExportOffset, SeekOrigin.Begin); byte[] buffer; for (int i = 0; i < ExportCount; i++) { uint expInfoOffset = (uint)listsStream.Position; listsStream.Seek(44, SeekOrigin.Current); int count = listsStream.ReadValueS32(); listsStream.Seek(-48, SeekOrigin.Current); int expInfoSize = 68 + (count * 4); buffer = new byte[expInfoSize]; listsStream.Read(buffer, 0, buffer.Length); ME3ExportEntry e = new ME3ExportEntry(this, buffer, expInfoOffset); long headerEnd = listsStream.Position; buffer = new byte[e.DataSize]; listsStream.Seek(e.DataOffset, SeekOrigin.Begin); listsStream.Read(buffer, 0, buffer.Length); e.Data = buffer; e.DataChanged = false; e.Index = i; e.PropertyChanged += exportChanged; exports.Add(e); listsStream.Seek(headerEnd, SeekOrigin.Begin); } }
/*public class ImportEntry : IEntry * { * public static int byteSize = 28; * internal byte[] header = new byte[byteSize]; * internal UDKPackage udkRef; * * public int idxPackageFile { get { return BitConverter.ToInt32(header, 0); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 0, sizeof(int)); } } * public int idxClassName { get { return BitConverter.ToInt32(header, 8); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 8, sizeof(int)); } } * public int idxLink { get { return BitConverter.ToInt32(header, 16); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 16, sizeof(int)); } } * public int idxObjectName { get { return BitConverter.ToInt32(header, 20); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 20, sizeof(int)); } } * * public string ClassName { get { return udkRef.getName(idxClassName); } } * public string PackageFile { get { return udkRef.Names[idxPackageFile] + ".udk"; } } * public string ObjectName { get { return udkRef.getName(idxObjectName); } } * public string PackageName * { * get * { * int val = idxLink; * if (val != 0) * { * IEntry entry = udkRef.getEntry(val); * return udkRef.getName(entry.idxObjectName); * } * else return "Package"; * } * } * public string PackageFullName * { * get * { * string result = PackageName; * int idxNewPackName = idxLink; * * while (idxNewPackName != 0) * { * string newPackageName = udkRef.getEntry(idxNewPackName).PackageName; * if (newPackageName != "Package") * result = newPackageName + "." + result; * idxNewPackName = udkRef.getEntry(idxNewPackName).idxLink; * } * return result; * } * } * * public string GetFullPath * { * get * { * string s = ""; * if (PackageFullName != "Class" && PackageFullName != "Package") * s += PackageFullName + "."; * s += ObjectName; * return s; * } * } * * public ImportEntry(UDKPackage UDKPackage, byte[] importData) * { * udkRef = UDKPackage; * header = (byte[])importData.Clone(); * } * * public ImportEntry(UDKPackage UDKPackage, Stream importData) * { * udkRef = UDKPackage; * header = new byte[ImportEntry.byteSize]; * importData.Read(header, 0, header.Length); * } * * public ImportEntry Clone() * { * ImportEntry newImport = (ImportEntry)MemberwiseClone(); * newImport.header = (byte[])this.header.Clone(); * return newImport; * } * } */ /* * public class ExportEntry : IEntry // class containing info about export entry (header info + data) * { * internal byte[] header; // holds data about export header, not the export data. * public UDKPackage udkRef; * public uint offset { get; set; } * * public int idxClass { get { return BitConverter.ToInt32(header, 0); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 0, sizeof(int)); } } * public int idxClassParent { get { return BitConverter.ToInt32(header, 4); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 4, sizeof(int)); } } * public int idxLink { get { return BitConverter.ToInt32(header, 8); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 8, sizeof(int)); } } * public int idxPackageName { get { return BitConverter.ToInt32(header, 8) - 1; } set { Buffer.BlockCopy(BitConverter.GetBytes(value + 1), 0, header, 8, sizeof(int)); } } * public int idxObjectName { get { return BitConverter.ToInt32(header, 12); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 12, sizeof(int)); } } * public int indexValue { get { return BitConverter.ToInt32(header, 16); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 16, sizeof(int)); } } * public int idxArchtype { get { return BitConverter.ToInt32(header, 20); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 20, sizeof(int)); } } * public ulong ObjectFlags { get { return BitConverter.ToUInt64(header, 24); } set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 24, sizeof(long)); } } * * public string ObjectName { get { return udkRef.getName(idxObjectName); } } * public string ClassName { get { int val = idxClass; if (val != 0) return udkRef.getName(udkRef.getEntry(val).idxObjectName); else return "Class"; } } * public string ClassParent { get { int val = idxClassParent; if (val != 0) return udkRef.getName(udkRef.getEntry(val).idxObjectName); else return "Class"; } } * public string PackageName { get { int val = idxPackageName; if (val >= 0) return udkRef.getName(udkRef.Exports[val].idxObjectName); else return "Package"; } } * public string PackageFullName * { * get * { * string result = PackageName; * int idxNewPackName = idxPackageName; * * while (idxNewPackName >= 0) * { * string newPackageName = udkRef.Exports[idxNewPackName].PackageName; * if (newPackageName != "Package") * result = newPackageName + "." + result; * idxNewPackName = udkRef.Exports[idxNewPackName].idxPackageName; * } * return result; * } * } * * public string ContainingPackage * { * get * { * string result = PackageName; * if (result.EndsWith(ObjectName)) * { * result = ""; * } * int idxNewPackName = idxPackageName; * * while (idxNewPackName >= 0) * { * string newPackageName = udkRef.Exports[idxNewPackName].PackageName; * if (newPackageName != "Package") * { * if (!result.Equals("")) * { * result = newPackageName + "." + result; * } * else * { * result = newPackageName; * } * } * idxNewPackName = udkRef.Exports[idxNewPackName].idxPackageName; * } * return result; * } * } * * public string GetFullPath * { * get * { * string s = ""; * if (PackageFullName != "Class" && PackageFullName != "Package") * s += PackageFullName + "."; * s += ObjectName; * return s; * } * } * public string ArchtypeName { get { int val = idxArchtype; if (val != 0) return udkRef.(udkRef.getEntry(val).idxObjectName); else return "None"; } } * * public int DataSize { get { return BitConverter.ToInt32(header, 32); } internal set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 32, sizeof(int)); } } * public int DataOffset { get { return BitConverter.ToInt32(header, 36); } internal set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, header, 36, sizeof(int)); } } * public int DataOffsetTmp; * byte[] _data = null; * public byte[] Data // holds data about export data * { * get * { * // if data isn't loaded then fill it from udk file (load-on-demand) * if (_data == null) * { * udkRef.getData(DataOffset, this); * } * return _data; * } * * set { _data = value; hasChanged = true; } * } * public bool likelyCoalescedVal * { * get * { * return (Data.Length < 25) ? false : (Data[25] == 64); //0x40 * } * set { } * } * public bool hasChanged { get; internal set; } * * public ExportEntry(UDKPackage UDKPackage, byte[] importData, uint exportOffset) * { * udkRef = UDKPackage; * header = (byte[])importData.Clone(); * offset = exportOffset; * hasChanged = false; * } * * public ExportEntry() * { * // TODO: Complete member initialization * } * * public ExportEntry Clone() * { * ExportEntry newExport = (ExportEntry)this.MemberwiseClone(); // copy all reference-types vars * // now creates new copies of referenced objects * newExport.header = (byte[])this.header.Clone(); * newExport.Data = (byte[])this.Data.Clone(); * int index = 0; * string name = ObjectName; * foreach (ExportEntry ent in udkRef.Exports) * { * if (name == ent.ObjectName && ent.indexValue > index) * { * index = ent.indexValue; * } * } * index++; * newExport.indexValue = index; * return newExport; * } * }*/ /// <summary> /// UDKPackage class constructor. It also load namelist, importlist and exportinfo (not exportdata) from udk file /// </summary> /// <param name="UDKPackagePath">full path + file name of desired udk file.</param> public UDKPackage(string UDKPackagePath, bool fullFileInMemory = false) { string path = UDKPackagePath; DebugOutput.PrintLn("Load file : " + path); FileName = Path.GetFullPath(path); MemoryStream tempStream = new MemoryStream(); if (!File.Exists(FileName)) { throw new FileNotFoundException("UPK file not found"); } using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { FileInfo tempInfo = new FileInfo(FileName); tempStream.WriteFromStream(fs, tempInfo.Length); if (tempStream.Length != tempInfo.Length) { throw new FileLoadException("File not fully read in. Try again later"); } } //tempStream.Seek(12, SeekOrigin.Begin); //int tempNameSize = tempStream.ReadValueS32(); //tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); //int tempGenerations = tempStream.ReadValueS32(); //tempStream.Seek(36 + tempGenerations * 12, SeekOrigin.Current); //int tempPos = (int)tempStream.Position; tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(headerSize); tempStream.Seek(0, SeekOrigin.Begin); MemoryStream listsStream; if (IsCompressed) { /*DebugOutput.PrintLn("File is compressed"); * { * listsStream = CompressionHelper.DecompressME1orME2(tempStream); * * //Correct the header * IsCompressed = false; * listsStream.Seek(0, SeekOrigin.Begin); * listsStream.WriteBytes(header); * * //Set numblocks to zero * listsStream.WriteValueS32(0); * //Write the magic number * listsStream.WriteValueS32(1026281201); * //Write 8 bytes of 0 * listsStream.WriteValueS32(0); * listsStream.WriteValueS32(0); * }*/ throw new FileLoadException("Compressed UPK packages are not supported."); } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); listsStream = tempStream; } names = new List <string>(); listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { try { int len = listsStream.ReadValueS32(); string s = listsStream.ReadString((uint)(len - 1)); //skipping irrelevant data listsStream.Seek(9, SeekOrigin.Current); // 8 + 1 for terminator character names.Add(s); } catch (Exception e) { Debugger.Break(); throw e; } } imports = new List <ImportEntry>(); listsStream.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { ImportEntry import = new ImportEntry(this, listsStream); import.Index = i; import.PropertyChanged += importChanged; imports.Add(import); } exports = new List <IExportEntry>(); listsStream.Seek(ExportOffset, SeekOrigin.Begin); for (int i = 0; i < ExportCount; i++) { UDKExportEntry exp = new UDKExportEntry(this, listsStream); exp.Index = i; exp.PropertyChanged += exportChanged; exports.Add(exp); } }
public void addImport(ImportEntry importEntry) { if (importEntry.FileRef != this) throw new Exception("you cannot add a new import entry from another pcc file, it has invalid references!"); importEntry.Index = imports.Count; importEntry.PropertyChanged += importChanged; imports.Add(importEntry); ImportCount = imports.Count; updateTools(PackageChange.ImportAdd, ImportCount - 1); }