public static DecompressME1orME2 ( Stream raw ) : |
||
raw | Stream | pcc file passed in stream format |
return |
private ME1Package(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 + 4; 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 an ME1 Package 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.WriteBytes(new byte[] { 0xF2, 0x56, 0x1B, 0x4E }); // Write 4 bytes of 0 listsStream.WriteValueS32(0); } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); //listsStream = tempStream; listsStream = new MemoryStream(); tempStream.WriteTo(listsStream); } tempStream.Dispose(); ReadNames(listsStream); ReadImports(listsStream); ReadExports(listsStream); }
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 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(); } } }