상속: ViewModelBase, IEntry
예제 #1
0
 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);
     }
 }
예제 #2
0
 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("");
 }
예제 #3
0
        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));
        }
예제 #4
0
        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);
        }
예제 #5
0
        //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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
 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);
     }
 }
예제 #8
0
        /// <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);
                }
            }
        }
예제 #9
0
        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();
                }
            }
        }
예제 #10
0
        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));
            }
        }
예제 #11
0
 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);
 }
예제 #12
0
        /// <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);
            }
        }
예제 #13
0
        /*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);
            }
        }
예제 #14
0
        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);
        }