예제 #1
0
        /// <summary>
        /// See http://www.w3.org/TR/html-imports/#dfn-import-request.
        /// </summary>
        public override async Task LoadAsync(IConfiguration configuration, IResourceLoader loader)
        {
            var link = Link;
            var document = link.Owner;
            var list = ImportLists.GetOrCreateValue(document);
            var location = Url;
            var request = link.CreateRequestFor(location);
            var item = new ImportEntry 
            { 
                Relation = this,
                IsCycle = CheckCycle(document, location)
            };
            _isasync = link.HasAttribute(AttributeNames.Async);
            list.Add(item);
            
            if (!item.IsCycle)
            {
                var nestedStatus = new TaskCompletionSource<Boolean>();
                var download = loader.DownloadAsync(request);
                SetDownload(download);

                await link.ProcessResponse(download, async response =>
                {
                    var context = new BrowsingContext(document.Context, Sandboxes.None);
                    var options = new CreateDocumentOptions(response, configuration)
                    {
                        ImportAncestor = document
                    };
                    _import = await context.OpenAsync(options, CancellationToken.None).ConfigureAwait(false);
                    nestedStatus.SetResult(true);
                }).ConfigureAwait(false);
                await nestedStatus.Task.ConfigureAwait(false);
            }
        }
        private void BuildX86CorStub(ImportEntry entry)
        {
            int pos = 0;

            // jmp
            _blob.Write(ref pos, new byte[] { 0xFF, 0x25 });

            // VA of IAT
            _relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
            _blob.Write(ref pos, (uint)0);

            PE.Fixups.Add(new X86CorStubFixup(_blob, entry));
        }
        private void Scan_WwiseEvent(TreeViewItem topLevelTree, byte[] data, int binarystart)
        {
            try
            {
                int binarypos = binarystart;
                List <TreeViewItem> subnodes = new List <TreeViewItem>();
                int count = BitConverter.ToInt32(data, binarypos);
                subnodes.Add(new TreeViewItem()
                {
                    Header = $"0x{binarypos:X4} Count: {count.ToString()}"
                });
                binarypos += 4; //+ int
                if (count > 0)
                {
                    string nodeText = $"0x{binarypos:X4} ";
                    int    val      = BitConverter.ToInt32(data, binarypos);
                    string name     = val.ToString();
                    if (val > 0 && val <= CurrentLoadedExport.FileRef.Exports.Count)
                    {
                        IExportEntry exp = CurrentLoadedExport.FileRef.Exports[val - 1];
                        nodeText += $"{name} {exp.PackageFullName}.{exp.ObjectName} ({exp.ClassName})";
                    }
                    else if (val < 0 && val != int.MinValue && Math.Abs(val) <= CurrentLoadedExport.FileRef.Imports.Count)
                    {
                        int         csImportVal = Math.Abs(val) - 1;
                        ImportEntry imp         = CurrentLoadedExport.FileRef.Imports[csImportVal];
                        nodeText += $"{name} {imp.PackageFullName}.{imp.ObjectName} ({imp.ClassName})";
                    }

                    subnodes.Add(new TreeViewItem()
                    {
                        Header = nodeText,
                        Tag    = nodeType.StructLeafObject,
                        Name   = "_" + binarypos.ToString()
                    });

                    /*
                     *
                     *                  int objectindex = BitConverter.ToInt32(data, binarypos);
                     *                  IEntry obj = pcc.getEntry(objectindex);
                     *                  string nodeValue = obj.GetFullPath;
                     *                  node.Tag = nodeType.StructLeafObject;
                     */
                }
                topLevelTree.ItemsSource = subnodes;
            }
            catch (Exception ex)
            {
                topLevelTree.Items.Add($"An error occured parsing the wwiseevent: {ex.Message}");
            }
        }
예제 #4
0
            public ImportSection(BinaryReader reader) : base(reader)
            {
                uint count = LEB128.ReadUInt32(reader);

                if (count > int.MaxValue)
                {
                    throw new NotImplementedException($"Count larger than {int.MaxValue} bytes not supported.");
                }
                entries = new ImportEntry[count];

                for (uint i = 0; i < count; i++)
                {
                    entries[i] = new ImportEntry(reader);
                }
            }
예제 #5
0
        public static void ReadImports()
        {
            int pos = header.ImportOffset;

            importlist = new List <ImportEntry>();
            for (int i = 0; i < header.ImportCount; i++)
            {
                ImportEntry e = new ImportEntry();
                e.Package = GetInt(pos);
                e.Link    = GetInt(pos + 16);
                e.Name    = GetInt(pos + 20);
                pos      += 0x1C;
                importlist.Add(e);
            }
        }
        private void BuildAMD64CorStub(ImportEntry entry)
        {
            int pos = 0;

            // rex.w rex.b mov rax,[following address]
            _blob.Write(ref pos, new byte[] { 0x48, 0xA1 });

            // VA of IAT
            _relocTable.Add(_blob, pos, BaseRelocationType.DIR64);
            _blob.Write(ref pos, (ulong)0);

            // jmp [rax]
            _blob.Write(ref pos, new byte[] { 0xFF, 0xE0 });

            PE.Fixups.Add(new AMD64CorStubFixup(_blob, entry));
        }
예제 #7
0
 private void ReadImportTable()
 {
     try
     {
         DebugLog.PrintLn("Reading Import Table...");
         Imports = new List <ImportEntry>();
         if (GeneralInfo.compressed)
         {
             UncompressRange(Header._offsetCompFlagEnd + 0xC, Header.HeaderLength - (Header._offsetCompFlagEnd + 0xC));
             Header.DeCompBuffer.Seek(Header.ImportOffset, 0);
             for (int i = 0; i < Header.ImportCount; i++)
             {
                 ImportEntry e = new ImportEntry();
                 e.idxPackage = ReadInt(Header.DeCompBuffer);
                 e.Unk1       = ReadInt(Header.DeCompBuffer);
                 e.idxClass   = ReadInt(Header.DeCompBuffer);
                 e.Unk2       = ReadInt(Header.DeCompBuffer);
                 e.idxLink    = ReadInt(Header.DeCompBuffer);
                 e.idxName    = ReadInt(Header.DeCompBuffer);
                 e.Unk3       = ReadInt(Header.DeCompBuffer);
                 Imports.Add(e);
             }
         }
         else
         {
             Source.Seek(Header.ImportOffset, 0);
             for (int i = 0; i < Header.ImportCount; i++)
             {
                 ImportEntry e = new ImportEntry();
                 e.idxPackage = ReadInt(Source);
                 e.Unk1       = ReadInt(Source);
                 e.idxClass   = ReadInt(Source);
                 e.Unk2       = ReadInt(Source);
                 e.idxLink    = ReadInt(Source);
                 e.idxName    = ReadInt(Source);
                 e.Unk3       = ReadInt(Source);
                 Imports.Add(e);
             }
         }
         DebugLog.PrintLn("Done.");
     }
     catch (Exception ex)
     {
         DebugLog.PrintLn("PCCPACKAGE::READIMPORTTABLE ERROR:\n" + ex.Message);
     }
 }
예제 #8
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();
         import.Package = Names[fs.ReadValueS32()];
         fs.Seek(12, SeekOrigin.Current);
         import.link = fs.ReadValueS32();
         import.Name = Names[fs.ReadValueS32()];
         fs.Seek(-24, SeekOrigin.Current);
         import.raw = fs.ReadBytes(28);
         Imports.Add(import);
     }
 }
예제 #9
0
 public void CloneEntry(int uIndex)
 {
     if (uIndex > 0)
     {
         ExportEntry e = Exports[uIndex - 1];
         ExportEntry n = new ExportEntry();
         n.Data         = CopyArray(GetObjectData(uIndex - 1));
         n.DataLoaded   = true;
         n.Datasize     = n.Data.Length;
         n.idxClass     = e.idxClass;
         n.idxParent    = e.idxParent;
         n.idxLink      = e.idxLink;
         n.idxName      = e.idxName;
         n.Index        = GetBiggestIndex() + 1;
         n.idxArchetype = e.idxArchetype;
         n.Unk1         = e.Unk1;
         n.ObjectFlags  = e.ObjectFlags;
         n.Unk2         = e.Unk2;
         n.Unk3         = new int[e.Unk3.Length];
         for (int i = 0; i < e.Unk3.Length; i++)
         {
             n.Unk3[i] = e.Unk3[i];
         }
         n.Unk2 = e.Unk4;
         n.Unk2 = e.Unk5;
         n.Unk2 = e.Unk6;
         n.Unk2 = e.Unk7;
         n.Unk2 = e.Unk8;
         Exports.Add(n);
         Header.ExportCount++;
     }
     else
     {
         ImportEntry e = Imports[-uIndex - 1];
         ImportEntry n = new ImportEntry();
         n.idxPackage = e.idxPackage;
         n.Unk1       = e.Unk1;
         n.idxClass   = e.idxClass;
         n.Unk2       = e.Unk2;
         n.idxLink    = e.idxLink;
         n.idxName    = e.idxName;
         n.Unk3       = e.Unk3;
         Imports.Add(n);
         Header.ImportCount++;
     }
 }
예제 #10
0
        private void IndexBox_TextChanged(object sender, EventArgs e)
        {
            int  destIndex = -1;
            bool succeeded = Int32.TryParse(indexField.Text, out destIndex);

            if (succeeded)
            {
                if (((SupportedInputTypes & SUPPORTS_EXPORTS_ONLY) != 0))
                {
                    if (destIndex >= 0 && destIndex < pcc.Exports.Count)
                    {
                        //Parse
                        IExportEntry destExport = pcc.Exports[destIndex];
                        selectedItemLabel.Text = destExport.GetFullPath + " (EXPORT)";;
                        acceptButton.Enabled   = true;
                    }
                    else
                    {
                        selectedItemLabel.Text = "Invalid export index (out of bounds)";
                        acceptButton.Enabled   = false;
                    }
                }
                else if (((SupportedInputTypes & SUPPORTS_IMPORTS_ONLY) != 0))
                {
                    if (destIndex < 0 && -destIndex + 1 < pcc.Imports.Count)
                    {
                        //Parse
                        ImportEntry import = pcc.Imports[-destIndex + 1];
                        selectedItemLabel.Text = import.GetFullPath + " (IMPORT)";
                        acceptButton.Enabled   = true;
                    }
                    else
                    {
                        selectedItemLabel.Text = "Invalid import index (out of bounds)";
                        acceptButton.Enabled   = false;
                    }
                }
            }
            else
            {
                selectedItemLabel.Text = "Invalid input";
                acceptButton.Enabled   = false;
            }
        }
예제 #11
0
        public static void TrashEntries(IMEPackage pcc, IEnumerable <IEntry> itemsToTrash)
        {
            ExportEntry trashTopLevel = pcc.Exports.FirstOrDefault(x => x.idxLink == 0 && x.ObjectName == UnrealPackageFile.TrashPackageName);
            ImportEntry packageImport = pcc.Imports.FirstOrDefault(x => x.GetFullPath == "Core.Package");

            if (packageImport == null)
            {
                ImportEntry coreImport = pcc.Imports.FirstOrDefault(x => x.GetFullPath == "Core");
                if (coreImport == null)
                {
                    //really small file
                    coreImport = new ImportEntry(pcc)
                    {
                        idxObjectName  = pcc.FindNameOrAdd("Core"),
                        idxClassName   = pcc.FindNameOrAdd("Package"),
                        idxLink        = 0,
                        idxPackageFile = pcc.FindNameOrAdd("Core")
                    };
                    pcc.addImport(coreImport);
                }

                //Package isn't an import, could be one of the 2DA files or other small ones
                packageImport = new ImportEntry(pcc)
                {
                    idxObjectName  = pcc.FindNameOrAdd("Package"),
                    idxClassName   = pcc.FindNameOrAdd("Class"),
                    idxLink        = coreImport.UIndex,
                    idxPackageFile = pcc.FindNameOrAdd("Core")
                };
                pcc.addImport(packageImport);
            }

            foreach (IEntry entry in itemsToTrash)
            {
                if (entry == trashTopLevel || entry.ObjectName == "Trash") //don't trash what's already been trashed
                {
                    continue;
                }
                trashTopLevel = TrashEntry(entry, trashTopLevel, packageImport.UIndex);
            }
            pcc.RemoveTrailingTrash();
        }
        public bool Match(ImportEntry importEntry, ImportEntry matchEntry)
        {
            if (!importEntry.IsErrorStatusCode())
            {
                _logger.Log("Error status code.");

                return(false);
            }

            if (!importEntry.IsMatching(matchEntry))
            {
                _logger.Log("Error not matching.");

                return(false);
            }

            _logger.Log("Matching hobbies!");

            return(true);
        }
        /// <summary>
        /// Converts an AnimSet export to an import
        /// </summary>
        /// <param name="origEntry"></param>
        /// <param name="targetPackage"></param>
        /// <returns></returns>
        private static IEntry ConvertAnimSetExportToImport(IEntry origEntry, IMEPackage targetPackage)
        {
            // Check if this item is available already
            var found = targetPackage.FindEntry(origEntry.InstancedFullPath);

            if (found != null)
            {
                return(found);
            }

            // Setup the link for our import
            var parentPackage = targetPackage.FindEntry(origEntry.Parent.InstancedFullPath);

            if (parentPackage == null)
            {
                // We must add a package import
                parentPackage = new ImportEntry(targetPackage)
                {
                    idxLink     = 0,
                    ClassName   = "Package",
                    ObjectName  = origEntry.Parent.ObjectName,
                    PackageFile = "Core"
                };
                targetPackage.AddImport((ImportEntry)parentPackage);
            }

            // Install the import
            ImportEntry imp = new ImportEntry(targetPackage)
            {
                ClassName   = origEntry.ClassName,
                idxLink     = parentPackage.UIndex,
                ObjectName  = origEntry.ObjectName,
                PackageFile = "Engine"
            };

            targetPackage.AddImport(imp);

            return(imp);
        }
예제 #14
0
        /// <summary>
        /// See http://www.w3.org/TR/html-imports/#dfn-import-request.
        /// </summary>
        public override Task LoadAsync()
        {
            var link = Link;
            var document = link.Owner;
            var list = ImportLists.GetOrCreateValue(document);
            var location = Url;
            var processor = Processor;
            var item = new ImportEntry 
            { 
                Relation = this,
                IsCycle = CheckCycle(document, location)
            };
            list.Add(item);
            
            if (!item.IsCycle)
            {
                var request = link.CreateRequestFor(location);
                _isasync = link.HasAttribute(AttributeNames.Async);
                return processor?.ProcessAsync(request);
            }

            return null;
        }
예제 #15
0
        /// <summary>
        /// See http://www.w3.org/TR/html-imports/#dfn-import-request.
        /// </summary>
        public override async Task LoadAsync(IConfiguration configuration, IResourceLoader loader)
        {
            var link     = Link;
            var document = link.Owner;
            var list     = ImportLists.GetOrCreateValue(document);
            var location = Url;
            var request  = link.CreateRequestFor(location);
            var item     = new ImportEntry
            {
                Relation = this,
                IsCycle  = CheckCycle(document, location)
            };

            _isasync = link.HasAttribute(AttributeNames.Async);
            list.Add(item);

            if (!item.IsCycle)
            {
                var nestedStatus = new TaskCompletionSource <Boolean>();
                var download     = loader.DownloadAsync(request);
                SetDownload(download);

                await link.ProcessResponse(download, async response =>
                {
                    var context = new BrowsingContext(document.Context, Sandboxes.None);
                    var options = new CreateDocumentOptions(response, configuration)
                    {
                        ImportAncestor = document
                    };
                    _import = await context.OpenAsync(options, CancellationToken.None).ConfigureAwait(false);
                    nestedStatus.SetResult(true);
                }).ConfigureAwait(false);

                await nestedStatus.Task.ConfigureAwait(false);
            }
        }
예제 #16
0
        public static IEntry cloneEntry(IEntry entry, Dictionary <IEntry, IEntry> objectMap = null)
        {
            IEntry newEntry;

            if (entry is ExportEntry export)
            {
                ExportEntry ent = export.Clone();
                entry.FileRef.AddExport(ent);
                newEntry = ent;
                if (objectMap != null)
                {
                    objectMap[export] = ent;
                }
            }
            else
            {
                ImportEntry imp = ((ImportEntry)entry).Clone();
                entry.FileRef.AddImport(imp);
                newEntry = imp;
                //Imports are not relinked when cloning
            }

            return(newEntry);
        }
        /// <summary>
        /// See http://www.w3.org/TR/html-imports/#dfn-import-request.
        /// </summary>
        public override Task LoadAsync()
        {
            var link      = Link;
            var document  = link.Owner;
            var list      = ImportLists.GetOrCreateValue(document);
            var location  = Url;
            var processor = Processor;
            var item      = new ImportEntry
            {
                Relation = this,
                IsCycle  = location != null && CheckCycle(document, location)
            };

            list.Add(item);

            if (location != null && !item.IsCycle)
            {
                var request = link.CreateRequestFor(location);
                _async = link.HasAttribute(AttributeNames.Async);
                return(processor?.ProcessAsync(request));
            }

            return(Task.CompletedTask);
        }
예제 #18
0
        /// <summary>
        /// Attempts to relink unreal binary data to object pointers if they are part of the clone tree.
        /// It's gonna be an ugly mess.
        /// </summary>
        /// <param name="importpcc">PCC being imported from</param>
        private List <string> relinkBinaryObjects(IMEPackage importpcc)
        {
            List <string> relinkFailedReport = new List <string>();

            foreach (KeyValuePair <int, int> entry in crossPCCObjectMap)
            {
                if (entry.Key > 0)
                {
                    IExportEntry exp        = pcc.getExport(entry.Value);
                    byte[]       binarydata = exp.getBinaryData();
                    if (binarydata.Length > 0)
                    {
                        //has binary data
                        //This is temporary until I find a more permanent style for relinking binary
                        try
                        {
                            switch (exp.ClassName)
                            {
                            case "WwiseEvent":
                            {
                                int count = BitConverter.ToInt32(binarydata, 0);
                                for (int i = 0; i < count; i++)
                                {
                                    int  originalValue    = BitConverter.ToInt32(binarydata, 4 + (i * 4));
                                    int  currentObjectRef = unrealIndexToME3ExpIndexing(originalValue);        //count + i * intsize
                                    int  mapped;
                                    bool isMapped = crossPCCObjectMap.TryGetValue(currentObjectRef, out mapped);
                                    if (isMapped)
                                    {
                                        mapped = me3ExpIndexingToUnreal(mapped, originalValue < 0);         //if the value is 0, it would have an error anyways.
                                        Debug.WriteLine("Binary relink hit for WwiseEvent Export " + exp.UIndex + " 0x" + (4 + (i * 4)).ToString("X6") + " " + originalValue + " -> " + (mapped + 1));
                                        WriteMem(4 + (i * 4), binarydata, BitConverter.GetBytes(mapped));
                                        int newValue = BitConverter.ToInt32(binarydata, 4 + (i * 4));
                                        Debug.WriteLine(originalValue + " -> " + newValue);
                                    }
                                    else
                                    {
                                        Debug.WriteLine("Binary relink missed WwiseEvent Export " + exp.UIndex + " 0x" + (4 + (i * 4)).ToString("X6") + " " + originalValue);
                                        relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: WwiseEvent referenced WwiseStream " + originalValue + " is not in the mapping tree and could not be relinked");
                                    }
                                }
                                exp.setBinaryData(binarydata);
                            }
                            break;

                            case "Class":
                            {
                                if (exp.FileRef.Game != importpcc.Game)
                                {
                                    //Cannot relink against a different game.
                                    continue;
                                }
                                IExportEntry importingExp = importpcc.getExport(entry.Key);
                                if (importingExp.ClassName != "Class")
                                {
                                    continue;         //the class was not actually set, so this is not really class.
                                }

                                //This is going to be pretty ugly
                                try
                                {
                                    byte[] newdata = importpcc.Exports[entry.Key].Data;         //may need to rewrite first unreal header
                                    byte[] data    = importpcc.Exports[entry.Key].Data;

                                    int offset            = 0;
                                    int unrealExportIndex = BitConverter.ToInt32(data, offset);
                                    offset += 4;


                                    int superclassIndex = BitConverter.ToInt32(data, offset);
                                    if (superclassIndex < 0)
                                    {
                                        //its an import
                                        ImportEntry superclassImportEntry = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(superclassIndex))];
                                        ImportEntry newSuperclassValue    = getOrAddCrossImport(superclassImportEntry.GetFullPath, importpcc, exp.FileRef);
                                        WriteMem(offset, newdata, BitConverter.GetBytes(newSuperclassValue.UIndex));
                                    }
                                    else
                                    {
                                        relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Superclass is an export in the source package and was not relinked.");
                                    }


                                    int unknown1 = BitConverter.ToInt32(data, offset);
                                    offset += 4;

                                    int classObjTree = BitConverter.ToInt32(data, offset);         //Don't know if I need to do this.
                                    offset += 4;


                                    //I am not sure what these mean. However if Pt1&2 are 33/25, the following bytes that follow are extended.
                                    int   headerUnknown1 = BitConverter.ToInt32(data, offset);
                                    Int64 ignoreMask     = BitConverter.ToInt64(data, offset);
                                    offset += 8;

                                    Int16 labelOffset = BitConverter.ToInt16(data, offset);
                                    offset += 2;
                                    int skipAmount = 0x6;
                                    //Find end of script block. Seems to be 10 FF's.
                                    while (offset + skipAmount + 10 < data.Length)
                                    {
                                        //Debug.WriteLine("Cheecking at 0x"+(offset + skipAmount + 10).ToString("X4"));
                                        bool isEnd = true;
                                        for (int i = 0; i < 10; i++)
                                        {
                                            byte b = data[offset + skipAmount + i];
                                            if (b != 0xFF)
                                            {
                                                isEnd = false;
                                                break;
                                            }
                                        }
                                        if (isEnd)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            skipAmount++;
                                        }
                                    }

                                    int offsetEnd = offset + skipAmount + 10;
                                    offset += skipAmount + 10;         //heuristic to find end of script
                                    uint stateMask = BitConverter.ToUInt32(data, offset);
                                    offset += 4;

                                    int localFunctionsTableCount = BitConverter.ToInt32(data, offset);
                                    offset += 4;
                                    bool isMapped;
                                    for (int i = 0; i < localFunctionsTableCount; i++)
                                    {
                                        int           nameTableIndex = BitConverter.ToInt32(data, offset);
                                        int           nameIndex      = BitConverter.ToInt32(data, offset + 4);
                                        NameReference importingName  = importpcc.getNameEntry(nameTableIndex);
                                        int           newFuncName    = exp.FileRef.FindNameOrAdd(importingName);
                                        WriteMem(offset, newdata, BitConverter.GetBytes(newFuncName));
                                        offset += 8;

                                        int functionObjectIndex = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset));
                                        int mapped;
                                        isMapped = crossPCCObjectMap.TryGetValue(functionObjectIndex, out mapped);
                                        if (isMapped)
                                        {
                                            mapped = me3ExpIndexingToUnreal(mapped, functionObjectIndex < 0);         //if the value is 0, it would have an error anyways.
                                            WriteMem(offset, newdata, BitConverter.GetBytes(mapped));
                                        }
                                        else
                                        {
                                            relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Local function[" + i + "] could not be remapped during porting: " + functionObjectIndex + " is not in the mapping tree and could not be relinked");
                                        }
                                        offset += 4;
                                    }

                                    int classMask = BitConverter.ToInt32(data, offset);
                                    offset += 4;
                                    if (importpcc.Game != MEGame.ME3)
                                    {
                                        offset += 1;         //seems to be a blank byte here
                                    }

                                    int coreReference = BitConverter.ToInt32(data, offset);
                                    if (coreReference < 0)
                                    {
                                        //its an import
                                        ImportEntry outerclassReferenceImport = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(coreReference))];
                                        ImportEntry outerclassNewImport       = getOrAddCrossImport(outerclassReferenceImport.GetFullPath, importpcc, exp.FileRef);
                                        WriteMem(offset, newdata, BitConverter.GetBytes(outerclassNewImport.UIndex));
                                    }
                                    else
                                    {
                                        relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Outerclass is an export in the original package, not relinked.");
                                    }
                                    offset += 4;


                                    if (importpcc.Game == MEGame.ME3)
                                    {
                                        offset = ClassParser_RelinkComponentsTable(importpcc, exp, relinkFailedReport, ref newdata, offset);
                                        offset = ClassParser_ReadImplementsTable(importpcc, exp, relinkFailedReport, ref newdata, offset);
                                        int    postComponentsNoneNameIndex = BitConverter.ToInt32(data, offset);
                                        int    postComponentNoneIndex      = BitConverter.ToInt32(data, offset + 4);
                                        string postCompName = importpcc.getNameEntry(postComponentsNoneNameIndex);         //This appears to be unused in ME3, it is always None it seems.
                                        int    newFuncName  = exp.FileRef.FindNameOrAdd(postCompName);
                                        WriteMem(offset, newdata, BitConverter.GetBytes(newFuncName));
                                        offset += 8;

                                        int unknown4 = BitConverter.ToInt32(data, offset);
                                        offset += 4;
                                    }
                                    else
                                    {
                                        offset = ClassParser_ReadImplementsTable(importpcc, exp, relinkFailedReport, ref data, offset);
                                        offset = ClassParser_RelinkComponentsTable(importpcc, exp, relinkFailedReport, ref data, offset);

                                        int me12unknownend1 = BitConverter.ToInt32(data, offset);
                                        offset += 4;

                                        int me12unknownend2 = BitConverter.ToInt32(data, offset);
                                        offset += 4;
                                    }

                                    int defaultsClassLink = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset));
                                    int defClassLink;
                                    isMapped = crossPCCObjectMap.TryGetValue(defaultsClassLink, out defClassLink);
                                    if (isMapped)
                                    {
                                        defClassLink = me3ExpIndexingToUnreal(defClassLink, defaultsClassLink < 0);         //if the value is 0, it would have an error anyways.
                                        WriteMem(offset, newdata, BitConverter.GetBytes(defClassLink));
                                    }
                                    else
                                    {
                                        relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: DefaultsClassLink cannot be currently automatically relinked by Binary Relinker. Please manually set this in Binary Editor");
                                    }
                                    offset += 4;

                                    if (importpcc.Game == MEGame.ME3)
                                    {
                                        int functionsTableCount = BitConverter.ToInt32(data, offset);
                                        offset += 4;

                                        for (int i = 0; i < functionsTableCount; i++)
                                        {
                                            int functionsTableIndex = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset));
                                            int mapped;
                                            isMapped = crossPCCObjectMap.TryGetValue(functionsTableIndex, out mapped);
                                            if (isMapped)
                                            {
                                                mapped = me3ExpIndexingToUnreal(mapped, functionsTableIndex < 0);         //if the value is 0, it would have an error anyways.
                                                WriteMem(offset, newdata, BitConverter.GetBytes(mapped));
                                            }
                                            else
                                            {
                                                if (functionsTableIndex < 0)
                                                {
                                                    ImportEntry functionObjIndex    = importpcc.Imports[Math.Abs(functionsTableIndex)];
                                                    ImportEntry newFunctionObjIndex = getOrAddCrossImport(functionObjIndex.GetFullPath, importpcc, exp.FileRef);
                                                    WriteMem(offset, newdata, BitConverter.GetBytes(newFunctionObjIndex.UIndex));
                                                }
                                                else
                                                {
                                                    relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Full Functions List function[" + i + "] could not be remapped during porting: " + functionsTableIndex + " is not in the mapping tree and could not be relinked");
                                                }
                                            }
                                            offset += 4;
                                        }
                                    }
                                    exp.Data = newdata;
                                }
                                catch (Exception ex)
                                {
                                    relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Exception relinking: " + ex.Message);
                                }
                            }
                            break;

                            default:
                                continue;
                            }
                        }
                        catch (Exception e)
                        {
                            relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relinking failed: " + e.Message);
                        }
                        //Run an interpreter pass over it - we will find objectleafnodes and attempt to update the same offset in the destination file.
                        //BinaryInterpreter binaryrelinkInterpreter = new ME3Explorer.BinaryInterpreter(importpcc, importpcc.Exports[entry.Key], pcc, pcc.Exports[entry.Value], crossPCCObjectMapping);
                    }
                }
            }
            return(relinkFailedReport);
        }
예제 #19
0
파일: Package.cs 프로젝트: Renmiri/Gaming
 public static void ReadImports()
 {
     int pos = header.ImportOffset;
     importlist = new List<ImportEntry>();
     for (int i = 0; i < header.ImportCount; i++)
     {
         ImportEntry e = new ImportEntry();
         e.Package = GetInt(pos);
         e.Link = GetInt(pos + 16);
         e.Name = GetInt(pos + 20);
         pos += 0x1C;
         importlist.Add(e);
     }
 }
예제 #20
0
        public static IEntry GetEntryOrAddImport(IMEPackage Pcc, string importFullName)
        {
            //foreach (ImportEntry imp in Pcc.Imports)
            //{
            //    if (imp.GetFullPath == importFullName)
            //    {
            //        return imp;
            //    }
            //}

            var fullPathMappingList = new List <(string fullpath, IEntry entry)>();

            foreach (ImportEntry imp in Pcc.Imports)
            {
                fullPathMappingList.Add((imp.GetFullPath, imp));
            }
            foreach (ExportEntry exp in Pcc.Exports)
            {
                fullPathMappingList.Add((exp.GetFullPath, exp));
            }

            var directMapping = fullPathMappingList.Where(x => x.fullpath == importFullName).ToList();

            if (directMapping.Count == 1)
            {
                return(directMapping[0].entry);                          //direct single match
            }
            //Find an upstream entry to attach our import to (we can't add exports)
            string[] importParts   = importFullName.Split('.');
            int      upstreamCount = 1;

            IEntry upstreamEntryToAttachTo = null;
            string upstreamfullpath;

            while (upstreamCount < importParts.Length)
            {
                upstreamfullpath = string.Join(".", importParts, 0, importParts.Length - upstreamCount);
                var upstreammatchinglist = fullPathMappingList.Where(x => x.fullpath == upstreamfullpath).ToList();
                if (upstreammatchinglist.Where(x => x.entry is ExportEntry).HasExactly(1) || upstreammatchinglist.Where(x => x.entry is ImportEntry).HasExactly(1))
                {
                    upstreamEntryToAttachTo = upstreammatchinglist[0].entry;
                    break;
                }

                /*if (upstreamEntryToAttachTo != null)
                 * {
                 *  break;
                 * }*/
                upstreamCount++;
            }

            //upstreamImport = Pcc.Imports.FirstOrDefault(x => x.GetFullPath == upstream);



            //Check if this is an export instead

            /* itemAsImport = Pcc.Exports.FirstOrDefault(x => x.GetFullPath == importFullName && x.indexValue == 0);
             * if (itemAsImport != null)
             * {
             *  return itemAsImport;
             * }*/

            //Import doesn't exist, so we're gonna need to add it
            //But first we need to figure out what needs to be added.
            //string[] importParts = importFullName.Split('.');
            //List<int> upstreamLinks = new List<int>(); //0 = top level, 1 = next level... n = what we wanted to import

            /*ImportEntry upstreamImport = null;
             * string upstream = null;
             * while (upstreamCount < importParts.Count())
             * {
             *  upstreamfullpath = string.Join(".", importParts, 0, importParts.Count() - upstreamCount);
             *  upstreamImport = Pcc.Imports.FirstOrDefault(x => x.GetFullPath == upstreamfullpath);
             *
             *  if (upstreamImport != null)
             *  {
             *      break;
             *  }
             *  upstreamCount++;
             * }*/

            if (upstreamEntryToAttachTo == null)
            {
                //There is nothing we can attach to.
                Debug.WriteLine("cannot find a top level item to attach to for " + importFullName);
                return(null);
            }

            //Have an upstream import, now we need to add downstream imports.
            ImportEntry mostdownstreamimport = null;

            while (upstreamCount > 0)
            {
                upstreamCount--;
                string fullobjectname = String.Join(".", importParts, 0, importParts.Length - upstreamCount);
                Dictionary <string, string> importdbinfo = ImportClassDB[fullobjectname];

                int downstreamName = Pcc.FindNameOrAdd(importParts[importParts.Length - upstreamCount - 1]);
                Debug.WriteLine(Pcc.Names[downstreamName]);
                int downstreamLinkIdx = upstreamEntryToAttachTo.UIndex;
                Debug.WriteLine(upstreamEntryToAttachTo.GetFullPath);

                int    downstreamPackageName = Pcc.FindNameOrAdd(importdbinfo["packagefile"]);
                string downstreamClassName   = importdbinfo["fullclasspath"];
                int    lastPeriodIndex       = downstreamClassName.LastIndexOf(".");
                if (lastPeriodIndex > 0)
                {
                    downstreamClassName = importdbinfo["fullclasspath"].Substring(lastPeriodIndex + 1);
                }

                int downstreamClassNameIdx = Pcc.FindNameOrAdd(downstreamClassName);
                Debug.WriteLine("Finding name " + downstreamClassName);
                //ImportEntry classImport = getOrAddImport();
                //int downstreamClass = 0;
                //if (classImport != null) {
                //    downstreamClass = classImport.UIndex; //no recursion pls
                //} else
                //{
                //    throw new Exception("No class was found for importing");
                //}

                mostdownstreamimport = new ImportEntry(Pcc)
                {
                    idxLink        = downstreamLinkIdx,
                    idxClassName   = downstreamClassNameIdx,
                    idxObjectName  = downstreamName,
                    idxPackageFile = downstreamPackageName
                };
                Pcc.addImport(mostdownstreamimport);
                upstreamEntryToAttachTo = mostdownstreamimport;
            }
            return(mostdownstreamimport);
        }
예제 #21
0
 private void ReadImports(MemoryTributary 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();
         import.Package = Names[fs.ReadValueS32()];
         fs.Seek(12, SeekOrigin.Current);
         import.link = fs.ReadValueS32();
         import.Name = Names[fs.ReadValueS32()];
         fs.Seek(-24, SeekOrigin.Current);
         import.raw = fs.ReadBytes(28);
         Imports.Add(import);
     }
 }
예제 #22
0
        /// <summary>
        ///     UDKFile class constructor. It also load namelist, importlist and exportinfo (not exportdata) from udk file
        /// </summary>
        /// <param name="udkFilePath">full path + file name of desired udk file.</param>
        public UDKFile(string udkFilePath, bool fullFileInMemory = false)
        {
            Loaded   = true;
            FileName = Path.GetFullPath(udkFilePath);
            using (FileStream udkStream = File.OpenRead(FileName))
            {
                Names   = new List <NameEntry>();
                Imports = new List <ImportEntry>();
                Exports = new List <ExportEntry>();

                udkStream.Read(header, 0, header.Length);

                //unsure about magic number. for now just let it try anything
                if (magic != 2653586369)
                {
                    //throw new FormatException("not a udk file");
                }

                //again, unsure of what versions ought to be supported
                if (lowVers != 684 && highVers != 0)
                {
                    //throw new FormatException("unsupported version");
                }

                Stream listsStream;
                listsStream = udkStream;
                headerEnd   = NameOffset;

                // fill names list
                listsStream.Seek(NameOffset, SeekOrigin.Begin);
                for (int i = 0; i < NameCount; i++)
                {
                    long      currOffset = listsStream.Position;
                    int       strLength  = listsStream.ReadValueS32();
                    NameEntry n          = new NameEntry();
                    if (strLength < 0)
                    {
                        n.name = listsStream.ReadString(strLength * -2, true, Encoding.Unicode);
                    }
                    else
                    {
                        n.name = listsStream.ReadString(strLength, true, Encoding.ASCII);
                    }
                    n.unk   = listsStream.ReadValueS32();
                    n.flags = listsStream.ReadValueS32();
                    Names.Add(n);
                }
                //Debug.WriteLine("Names done. Current offset: "+listsStream.Position);
                //Debug.WriteLine("Import Offset: " + ImportOffset);

                // fill import list
                //Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset);
                listsStream.Seek(ImportOffset, SeekOrigin.Begin);
                byte[] buffer = new byte[ImportEntry.byteSize];
                for (int i = 0; i < ImportCount; i++)
                {
                    long        offset = listsStream.Position;
                    ImportEntry e      = new ImportEntry(this, listsStream);
                    Imports.Add(e);
                    //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset);
                }
                ;

                // fill export list (only the headers, not the data)
                listsStream.Seek(ExportOffset, SeekOrigin.Begin);
                //Console.Out.WriteLine("Export OFFSET: " + ImportOffset);
                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);
                    ExportEntry e = new ExportEntry(this, buffer, expInfoOffset);
                    //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize);
                    Exports.Add(e);
                }
            }
            Debug.WriteLine(getMetadataString());
        }
예제 #23
0
 public void Remove(ImportEntry item)
 {
     _list.Remove(item);
 }
예제 #24
0
 public void Add(ImportEntry item)
 {
     _list.Add(item);
 }
예제 #25
0
        private string relinkObjectProperty(IMEPackage importingPCC, IMEPackage destinationPCC, ObjectProperty objProperty, List <KeyValuePair <int, int> > crossPCCObjectMappingList)
        {
            if (objProperty.Value == 0)
            {
                return(null); //do not relink 0
            }
            if (importingPCC == destinationPCC && objProperty.Value < 0)
            {
                return(null); //do not relink same-pcc imports.
            }
            int sourceObjReference = objProperty.Value;

            if (sourceObjReference > 0)
            {
                sourceObjReference--; //make 0 based for mapping.
            }
            if (sourceObjReference < 0)
            {
                sourceObjReference++; //make 0 based for mapping.
            }
            //if (objProperty.Name != null)
            //{
            //    Debug.WriteLine(objProperty.Name);
            //}
            KeyValuePair <int, int> mapping = crossPCCObjectMappingList.Where(pair => pair.Key == sourceObjReference).FirstOrDefault();
            var defaultKVP = default(KeyValuePair <int, int>); //struct comparison

            if (!mapping.Equals(defaultKVP))
            {
                //relink
                int newval = 0;
                if (mapping.Value > 0)
                {
                    newval = mapping.Value + 1; //reincrement
                }
                else if (mapping.Value < 0)
                {
                    newval = mapping.Value - 1; //redecrement
                }
                objProperty.Value = (newval);
                IEntry entry = destinationPCC.getEntry(newval);
                string s     = "";
                if (entry != null)
                {
                    s = entry.GetFullPath;
                }
                Debug.WriteLine("Relink hit: " + sourceObjReference + objProperty.Name + ": " + s);
            }
            else if (objProperty.Value < 0) //It's an unmapped import
            {
                //objProperty is currently pointing to importingPCC as that is where we read the properties from
                int n               = objProperty.Value;
                int origvalue       = n;
                int importZeroIndex = Math.Abs(n) - 1;
                //Debug.WriteLine("Relink miss, attempting JIT relink on " + n + " " + rootNode.Text);
                if (n < 0 && importZeroIndex < importingPCC.ImportCount)
                {
                    //Get the original import
                    ImportEntry origImport         = importingPCC.getImport(importZeroIndex);
                    string      origImportFullName = origImport.GetFullPath;
                    //Debug.WriteLine("We should import " + origImport.GetFullPath);

                    ImportEntry crossImport          = null;
                    string      linkFailedDueToError = null;
                    try
                    {
                        crossImport = getOrAddCrossImport(origImportFullName, importingPCC, destinationPCC);
                    }
                    catch (Exception e)
                    {
                        //Error during relink
                        KFreonLib.Debugging.DebugOutput.StartDebugger("PCC Relinker");
                        DebugOutput.PrintLn("Exception occured during relink: ");
                        DebugOutput.PrintLn(ExceptionHandlerDialogWPF.FlattenException(e));
                        DebugOutput.PrintLn("You may want to consider discarding this sessions' changes as relinking was not able to properly finish.");
                        linkFailedDueToError = e.Message;
                    }
                    if (crossImport != null)
                    {
                        //cache item. Imports are stored +1, Exports-1. Someday I will go back and make this just 0 indexed
                        crossPCCObjectMappingList.Add(new KeyValuePair <int, int>(sourceObjReference, crossImport.UIndex + 1)); //add to mapping to speed up future relinks
                        objProperty.Value = crossImport.UIndex;
                        Debug.WriteLine("Relink hit: Dynamic CrossImport for " + origvalue + " " + importingPCC.getEntry(origvalue).GetFullPath + " -> " + objProperty.Value);
                    }
                    else
                    {
                        if (linkFailedDueToError != null)
                        {
                            Debug.WriteLine("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + ": " + importingPCC.getEntry(origvalue).GetFullPath);
                            return("Relink failed for " + objProperty.Name + " " + objProperty.Value + ": " + linkFailedDueToError);
                        }
                        else
                        if (destinationPCC.getEntry(objProperty.Value) != null)
                        {
                            Debug.WriteLine("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + ": " + importingPCC.getEntry(origvalue).GetFullPath);
                            return("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + " " + destinationPCC.getEntry(objProperty.Value).GetFullPath);
                        }
                        else
                        {
                            return("Relink failed: New export does not exist - this is probably a bug in cross import code for " + objProperty.Name + " " + objProperty.Value);
                        }
                    }
                }
            }
            else
            {
                string path = importingPCC.getEntry(objProperty.Value) != null?importingPCC.getEntry(objProperty.Value).GetFullPath : "Entry not found: " + objProperty.Value;

                Debug.WriteLine("Relink failed: " + objProperty.Name + " " + objProperty.Value + " " + path);
                return("Relink failed: " + objProperty.Name + " " + objProperty.Value + " " + path);
            }
            return(null);
        }
예제 #26
0
        private int ClassParser_RelinkComponentsTable(IMEPackage importpcc, IExportEntry exp, List <string> relinkFailedReport, ref byte[] data, int offset)
        {
            if (importpcc.Game == MEGame.ME3)
            {
                int           componentTableNameIndex = BitConverter.ToInt32(data, offset);
                int           componentTableIndex     = BitConverter.ToInt32(data, offset + 4);
                NameReference importingName           = importpcc.getNameEntry(componentTableNameIndex);
                int           newComponentTableName   = exp.FileRef.FindNameOrAdd(importingName);
                WriteMem(offset, data, BitConverter.GetBytes(newComponentTableName));
                offset += 8;

                int componentTableCount = BitConverter.ToInt32(data, offset);
                offset += 4;

                for (int i = 0; i < componentTableCount; i++)
                {
                    int nameTableIndex = BitConverter.ToInt32(data, offset);
                    int nameIndex      = BitConverter.ToInt32(data, offset + 4);
                    importingName = importpcc.getNameEntry(nameTableIndex);
                    int componentName = exp.FileRef.FindNameOrAdd(importingName);
                    WriteMem(offset, data, BitConverter.GetBytes(componentName));
                    offset += 8;

                    int  componentObjectIndex = BitConverter.ToInt32(data, offset);
                    int  mapped;
                    bool isMapped = crossPCCObjectMap.TryGetValue(componentObjectIndex, out mapped);
                    if (isMapped)
                    {
                        mapped = me3ExpIndexingToUnreal(mapped, componentObjectIndex < 0); //if the value is 0, it would have an error anyways.
                        WriteMem(offset, data, BitConverter.GetBytes(mapped));
                    }
                    else
                    {
                        if (componentObjectIndex < 0)
                        {
                            ImportEntry componentObjectImport    = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(componentObjectIndex))];
                            ImportEntry newComponentObjectImport = getOrAddCrossImport(componentObjectImport.GetFullPath, importpcc, exp.FileRef);
                            WriteMem(offset, data, BitConverter.GetBytes(newComponentObjectImport.UIndex));
                        }
                        else if (componentObjectIndex > 0) //we do not remap on 0 here in binary land
                        {
                            relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Component[" + i + "] could not be remapped during porting: " + componentObjectIndex + " is not in the mapping tree");
                        }
                    }
                    offset += 4;
                }
            }
            else
            {
                int componentTableCount = BitConverter.ToInt32(data, offset);
                offset += 4;

                for (int i = 0; i < componentTableCount; i++)
                {
                    int nameTableIndex = BitConverter.ToInt32(data, offset);
                    int nameIndex      = BitConverter.ToInt32(data, offset + 4);

                    offset += 8;

                    int componentObjectIndex = BitConverter.ToInt32(data, offset);
                    if (componentObjectIndex != 0)
                    {
                        int  mapped;
                        bool isMapped = crossPCCObjectMap.TryGetValue(componentObjectIndex, out mapped);
                        if (isMapped)
                        {
                            mapped = me3ExpIndexingToUnreal(mapped, componentObjectIndex < 0); //if the value is 0, it would have an error anyways.
                            WriteMem(offset, data, BitConverter.GetBytes(mapped));
                        }
                        else
                        {
                            if (componentObjectIndex < 0)
                            {
                                ImportEntry componentObjectImport    = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(componentObjectIndex))];
                                ImportEntry newComponentObjectImport = getOrAddCrossImport(componentObjectImport.GetFullPath, importpcc, exp.FileRef);
                                WriteMem(offset, data, BitConverter.GetBytes(newComponentObjectImport.UIndex));
                            }
                            else
                            {
                                relinkFailedReport.Add("Binary Class Component[" + i + "] could not be remapped during porting: " + componentObjectIndex + " is not in the mapping tree");
                            }
                        }
                    }
                    offset += 4;
                }
            }
            return(offset);
        }
예제 #27
0
 private void ReadImportTable()
 {
     try
     {
         DebugLog.PrintLn("Reading Import Table...");
         Imports = new List<ImportEntry>();
         if (GeneralInfo.compressed)
         {
             UncompressRange(Header._offsetCompFlagEnd + 0xC, Header.HeaderLength - (Header._offsetCompFlagEnd + 0xC));
             Header.DeCompBuffer.Seek(Header.ImportOffset, 0);
             for (int i = 0; i < Header.ImportCount; i++)
             {
                 ImportEntry e = new ImportEntry();
                 e.idxPackage = ReadInt(Header.DeCompBuffer);
                 e.Unk1 = ReadInt(Header.DeCompBuffer);
                 e.idxClass = ReadInt(Header.DeCompBuffer);
                 e.Unk2 = ReadInt(Header.DeCompBuffer);
                 e.idxLink = ReadInt(Header.DeCompBuffer);
                 e.idxName = ReadInt(Header.DeCompBuffer);
                 e.Unk3 = ReadInt(Header.DeCompBuffer);
                 Imports.Add(e);
             }
         }
         else
         {
             Source.Seek(Header.ImportOffset, 0);
             for (int i = 0; i < Header.ImportCount; i++)
             {
                 ImportEntry e = new ImportEntry();
                 e.idxPackage = ReadInt(Source);
                 e.Unk1 = ReadInt(Source);
                 e.idxClass = ReadInt(Source);
                 e.Unk2 = ReadInt(Source);
                 e.idxLink = ReadInt(Source);
                 e.idxName = ReadInt(Source);
                 e.Unk3 = ReadInt(Source);
                 Imports.Add(e);
             }
         }
         DebugLog.PrintLn("Done.");
     }
     catch (Exception ex)
     {
         DebugLog.PrintLn("PCCPACKAGE::READIMPORTTABLE ERROR:\n" + ex.Message);
     }
 }
예제 #28
0
        /// <summary>
        ///     PCCObject class constructor. It also load namelist, importlist and exportinfo (not exportdata) from pcc file
        /// </summary>
        /// <param name="pccFilePath">full path + file name of desired pcc file.</param>
        public PCCObject(string pccFilePath, bool fullFileInMemory = false)
        {
            Loaded = true;
            pccFileName = Path.GetFullPath(pccFilePath);
            using (FileStream pccStream = File.OpenRead(pccFileName))
            {
                Names   = new List<string>();
                Imports = new List<ImportEntry>();
                Exports = new List<ExportEntry>();

                pccStream.Read(header, 0, header.Length);
                if (magic != ZBlock.magic &&
                    magic.Swap() != ZBlock.magic)
                {
                    throw new FormatException("not a pcc file");
                }

                // BitConverter isn't working?!?!
                if (magic == 0x9E2A83C1)
                    BitConverter.IsLittleEndian = true;
                else
                    BitConverter.IsLittleEndian = true;

                if (lowVers != 684 && highVers != 194)
                {
                    throw new FormatException("unsupported version");
                }

                Stream listsStream;

                if (bCompressed)
                {
                    // seeks the blocks info position
                    pccStream.Seek(idxOffsets + 60, SeekOrigin.Begin);
                    int generator = pccStream.ReadValueS32();
                    pccStream.Seek((generator * 12) + 20, SeekOrigin.Current);

                    int blockCount = pccStream.ReadValueS32();
                    blockList = new List<Block>();

                    // creating the Block list
                    for (int i = 0; i < blockCount; i++)
                    {
                        Block temp = new Block();
                        temp.uncOffset = pccStream.ReadValueS32();
                        temp.uncSize = pccStream.ReadValueS32();
                        temp.cprOffset = pccStream.ReadValueS32();
                        temp.cprSize = pccStream.ReadValueS32();
                        blockList.Add(temp);
                    }

                    // correcting the header, in case there's need to be saved
                    Buffer.BlockCopy(BitConverter.GetBytes((int)0), 0, header, header.Length - 12, sizeof(int));
                    pccStream.Read(header, header.Length - 8, 8);
                    headerEnd = (int)pccStream.Position;

                    // copying the extraNamesList
                    int extraNamesLenght = blockList[0].cprOffset - headerEnd;
                    if (extraNamesLenght > 0)
                    {
                        extraNamesList = new byte[extraNamesLenght];
                        pccStream.Read(extraNamesList, 0, extraNamesLenght);
                        //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin");
                        //fileStream.Write(extraNamesList, 0, extraNamesLenght);
                        //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8"));
                    }

                    // decompress first block that holds infos about names, imports and exports
                    pccStream.Seek(blockList[0].cprOffset, SeekOrigin.Begin);
                    byte[] uncBlock = ZBlock.Decompress(pccStream, blockList[0].cprSize);

                    // write decompressed block inside temporary stream
                    listsStream = new MemoryStream();
                    listsStream.Seek(blockList[0].uncOffset, SeekOrigin.Begin);
                    listsStream.Write(uncBlock, 0, uncBlock.Length);
                }
                else
                {
                    listsStream = pccStream;
                    headerEnd = (int)NameOffset;

                    // copying the extraNamesList
                    int extraNamesLenght = headerEnd - headerSize;
                    if (extraNamesLenght > 0)
                    {
                        extraNamesList = new byte[extraNamesLenght];
                        listsStream.Seek(headerSize, SeekOrigin.Begin);
                        listsStream.Read(extraNamesList, 0, extraNamesLenght);
                        //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin");
                        //fileStream.Write(extraNamesList, 0, extraNamesLenght);
                        //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8"));
                    }
                }

                /*if(bExtraNamesList)
                {
                    int extraNamesListSize = namesOffset - headerEnd;
                    extraNamesList = new byte[extraNamesListSize];
                    pccStream.Seek(headerEnd, SeekOrigin.Begin);
                    pccStream.Read(extraNamesList, 0, extraNamesList.Length);
                }*/

                // 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);
                    //Debug.WriteLine("Read name "+i+" "+str+" length: " + strLength+", offset: "+currOffset);
                    Names.Add(str);
                }
                //Debug.WriteLine("Names done. Current offset: "+listsStream.Position);
                //Debug.WriteLine("Import Offset: " + ImportOffset);

                // fill import list
                Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset);
                listsStream.Seek(ImportOffset, SeekOrigin.Begin);
                byte[] buffer = new byte[ImportEntry.byteSize];
                for (int i = 0; i < ImportCount; i++)
                {

                    long offset = listsStream.Position;
                    ImportEntry e = new ImportEntry(this, listsStream);
                    Imports.Add(e);
                    //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset);
                }

                Debug.WriteLine("Imports done. Current offset: " + listsStream.Position);
                Debug.WriteLine("Export Offset: " + ExportOffset);

                // fill export list (only the headers, not the data)
                listsStream.Seek(ExportOffset, SeekOrigin.Begin);
                Console.Out.WriteLine("Export OFFSET: " + ImportOffset);
                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);
                    ExportEntry e = new ExportEntry(this, buffer, expInfoOffset);
                    //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize);

                    Exports.Add(e);
                }
            }
            Debug.WriteLine(getMetadataString());
        }
예제 #29
0
 public void CloneEntry(int uIndex)
 {
     if (uIndex > 0)
     {
         ExportEntry e = Exports[uIndex - 1];
         ExportEntry n = new ExportEntry();
         n.Data = CopyArray(GetObjectData(uIndex - 1));
         n.DataLoaded = true;
         n.Datasize = n.Data.Length;
         n.idxClass = e.idxClass;
         n.idxParent = e.idxParent;
         n.idxLink = e.idxLink;
         n.idxName = e.idxName;
         n.Index = GetBiggestIndex() + 1;
         n.idxArchetype = e.idxArchetype;
         n.Unk1 = e.Unk1;
         n.ObjectFlags = e.ObjectFlags;
         n.Unk2 = e.Unk2;
         n.Unk3 = new int[e.Unk3.Length];
         for (int i = 0; i < e.Unk3.Length; i++)
             n.Unk3[i] = e.Unk3[i];
         n.Unk2 = e.Unk4;
         n.Unk2 = e.Unk5;
         n.Unk2 = e.Unk6;
         n.Unk2 = e.Unk7;
         n.Unk2 = e.Unk8;
         Exports.Add(n);
         Header.ExportCount++;
     }
     else
     {
         ImportEntry e = Imports[-uIndex - 1];
         ImportEntry n = new ImportEntry();
         n.idxPackage = e.idxPackage;
         n.Unk1 = e.Unk1;
         n.idxClass = e.idxClass;
         n.Unk2 = e.Unk2;
         n.idxLink = e.idxLink;
         n.idxName = e.idxName;
         n.Unk3 = e.Unk3;
         Imports.Add(n);
         Header.ImportCount++;
     }
 }
예제 #30
0
        /// <summary>
        /// Adds an import from the importingPCC to the destinationPCC with the specified importFullName, or returns the existing one if it can be found.
        /// This method will look at importingPCC's import upstream chain and check for the most downstream one's existence in destinationPCC,
        /// including if none can be founc (in which case the entire upstream is copied). It will then create new imports to match the remaining
        /// downstream ones and return the originally named import, however now located in destinationPCC.
        /// </summary>
        /// <param name="importFullName">GetFullPath() of an import from ImportingPCC</param>
        /// <param name="importingPCC">PCC to import imports from</param>
        /// <param name="destinationPCC">PCC to add imports to</param>
        /// <returns></returns>
        private ImportEntry getOrAddCrossImport(string importFullName, IMEPackage importingPCC, IMEPackage destinationPCC, int?forcedLinkIdx = null)
        {
            //This code is kind of ugly, sorry.

            //see if this import exists locally
            foreach (ImportEntry imp in destinationPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    return(imp);
                }
            }

            //Import doesn't exist, so we're gonna need to add it
            //But first we need to figure out what needs to be added upstream as links
            //Search upstream until we find something, or we can't get any more upstreams
            ImportEntry mostdownstreamimport = null;

            string[] importParts = importFullName.Split('.');

            if (!forcedLinkIdx.HasValue)
            {
                List <int> upstreamLinks = new List <int>(); //0 = top level, 1 = next level... n = what we wanted to import
                int        upstreamCount = 1;

                ImportEntry upstreamImport = null;
                //get number of required upstream imports that do not yet exist
                while (upstreamCount < importParts.Count())
                {
                    string upstream = String.Join(".", importParts, 0, importParts.Count() - upstreamCount);
                    foreach (ImportEntry imp in destinationPCC.Imports)
                    {
                        if (imp.GetFullPath == upstream)
                        {
                            upstreamImport = imp;
                            break;
                        }
                    }

                    if (upstreamImport != null)
                    {
                        //We found an upsteam import that already exists
                        break;
                    }
                    upstreamCount++;
                }

                IExportEntry donorUpstreamExport = null;
                if (upstreamImport == null)
                {
                    //We have to import the entire upstream chain
                    string      fullobjectname      = importParts[0];
                    ImportEntry donorTopLevelImport = null;
                    foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc
                    {
                        if (imp.GetFullPath == fullobjectname)
                        {
                            donorTopLevelImport = imp;
                            break;
                        }
                    }

                    if (donorTopLevelImport == null)
                    {
                        //This is issue KinkoJiro had. It is aborting relinking at this step. Will need to find a way to
                        //work with exports as parents for imports which will block it.
                        //Update: This has been partially implemented.
                        Debug.WriteLine("No upstream import was found in the source file. It's probably an export: " + importFullName);
                        foreach (IExportEntry exp in destinationPCC.Exports) //importing side info we will move to our dest pcc
                        {
                            //Console.WriteLine(exp.GetFullPath);
                            if (exp.GetFullPath == fullobjectname)
                            {
                                // = imp;
                                //We will need to find a way to cross map this as this will block cross import mapping unless these exports already exist.
                                Debug.WriteLine("FOUND UPSTREAM, AS EXPORT!");
                                KFreonLib.Debugging.DebugOutput.StartDebugger("Package Editor Relinker");
                                KFreonLib.Debugging.DebugOutput.PrintLn("Error: Upstream item that is required is an export in the pcc to import from: " + fullobjectname);
                                donorUpstreamExport = exp;
                                upstreamCount--; //level 1 now from the top down
                                                 //Create new import with this as higher IDK
                                break;
                            }
                        }
                        if (donorUpstreamExport == null)
                        {
                            Debug.WriteLine("An error has occured. Could not find an upstream import or export for relinking: " + fullobjectname + " from " + pcc.FileName);
                            return(null);
                        }
                    }

                    if (donorUpstreamExport == null)
                    {
                        //Create new toplevel import and set that as the most downstream one. (top = bottom at this point)
                        int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorTopLevelImport.PackageFile));
                        int downstreamClassName   = destinationPCC.FindNameOrAdd(donorTopLevelImport.ClassName);
                        int downstreamName        = destinationPCC.FindNameOrAdd(fullobjectname);

                        mostdownstreamimport = new ImportEntry(destinationPCC);
                        // mostdownstreamimport.idxLink = downstreamLinkIdx; ??
                        mostdownstreamimport.idxClassName   = downstreamClassName;
                        mostdownstreamimport.idxObjectName  = downstreamName;
                        mostdownstreamimport.idxPackageFile = downstreamPackageFile;
                        destinationPCC.addImport(mostdownstreamimport); //Add new top level downstream import
                        upstreamImport = mostdownstreamimport;
                        upstreamCount--;                                //level 1 now from the top down
                                                                        //return null;
                    }
                }

                //Have an upstream import, now we need to add downstream imports.
                while (upstreamCount > 0)
                {
                    upstreamCount--;
                    string      fullobjectname = String.Join(".", importParts, 0, importParts.Count() - upstreamCount);
                    ImportEntry donorImport    = null;

                    //Get or create names for creating import and get upstream linkIdx
                    int downstreamName = destinationPCC.FindNameOrAdd(importParts[importParts.Count() - upstreamCount - 1]);
                    foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc
                    {
                        if (imp.GetFullPath == fullobjectname)
                        {
                            donorImport = imp;
                            break;
                        }
                    }
                    if (donorImport == null)
                    {
                        throw new Exception("No suitable upstream import was found for porting - this may be an export in the source file that is referenced as a parent or dependency. You should import this object and its parents first. " + fullobjectname + "(as part of " + importFullName + ")");
                    }

                    int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorImport.PackageFile));
                    int downstreamClassName   = destinationPCC.FindNameOrAdd(donorImport.ClassName);

                    mostdownstreamimport                = new ImportEntry(destinationPCC);
                    mostdownstreamimport.idxLink        = donorUpstreamExport == null ? upstreamImport.UIndex : donorUpstreamExport.UIndex;
                    mostdownstreamimport.idxClassName   = downstreamClassName;
                    mostdownstreamimport.idxObjectName  = downstreamName;
                    mostdownstreamimport.idxPackageFile = downstreamPackageFile;
                    destinationPCC.addImport(mostdownstreamimport);
                    upstreamImport = mostdownstreamimport;
                }
            }
            else
            {
                //get importing import
                ImportEntry importingImport = importingPCC.Imports.FirstOrDefault(x => x.GetFullPath == importFullName); //this shouldn't be null
                mostdownstreamimport                = new ImportEntry(destinationPCC);
                mostdownstreamimport.idxLink        = forcedLinkIdx.Value;
                mostdownstreamimport.idxClassName   = destinationPCC.FindNameOrAdd(importingImport.ClassName);
                mostdownstreamimport.idxObjectName  = destinationPCC.FindNameOrAdd(importingImport.ObjectName);
                mostdownstreamimport.idxPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(importingImport.PackageFile));
                destinationPCC.addImport(mostdownstreamimport);
            }
            return(mostdownstreamimport);
        }
예제 #31
0
        /// <summary>
        /// Creates a preview of the given <see cref="SkeletalMesh"/>.
        /// </summary>
        /// <param name="Device">The Direct3D device to use for buffer creation.</param>
        /// <param name="m">The mesh to generate a preview for.</param>
        /// <param name="texcache">The texture cache for loading textures.</param>
        public ModelPreview(Device Device, SkeletalMesh m, PreviewTextureCache texcache, PackageCache assetCache, PreloadedModelData preloadedData = null)
        {
            // STEP 1: MATERIALS
            if (preloadedData == null)
            {
                for (int i = 0; i < m.Materials.Length; i++)
                {
                    UIndex materialUIndex        = m.Materials[i];
                    MaterialInstanceConstant mat = null;
                    if (materialUIndex.value > 0)
                    {
                        mat = new MaterialInstanceConstant(m.Export.FileRef.GetUExport(materialUIndex.value));
                    }
                    else if (materialUIndex.value < 0)
                    {
                        // The material instance is an import!
                        ImportEntry matImport     = m.Export.FileRef.GetImport(materialUIndex.value);
                        var         externalAsset = EntryImporter.ResolveImport(matImport, null, assetCache);
                        if (externalAsset != null)
                        {
                            mat = new MaterialInstanceConstant(externalAsset);
                        }
                    }

                    if (mat != null)
                    {
                        ModelPreviewMaterial material;
                        // TODO: pick what material class best fits based on what properties the
                        // MaterialInstanceConstant mat has.
                        // For now, just use the default material.
                        material = new TexturedPreviewMaterial(texcache, mat, assetCache);
                        AddMaterial(material.Properties["Name"], material);
                    }
                }
            }
            else
            {
                //Preloaded
                //sections = preloadedData.sections;
                var uniqueMaterials = preloadedData.texturePreviewMaterials.Select(x => x.MaterialExport).Distinct();
                foreach (var mat in uniqueMaterials)
                {
                    var material = new TexturedPreviewMaterial(texcache, new MaterialInstanceConstant(mat), assetCache, preloadedData.texturePreviewMaterials);
                    AddMaterial(mat.ObjectName.Name, material);
                }
            }

            // STEP 2: LODS
            foreach (var lodmodel in m.LODModels)
            {
                // Vertices
                List <WorldVertex> vertices = new List <WorldVertex>(m.Export.Game == MEGame.ME1 ? lodmodel.ME1VertexBufferGPUSkin.Length : lodmodel.VertexBufferGPUSkin.VertexData.Length);
                if (m.Export.Game == MEGame.ME1)
                {
                    foreach (var vertex in lodmodel.ME1VertexBufferGPUSkin)
                    {
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y)));
                    }
                }
                else
                {
                    foreach (var vertex in lodmodel.VertexBufferGPUSkin.VertexData)
                    {
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y)));
                    }
                }
                // Triangles
                List <Triangle> triangles = new List <Triangle>(lodmodel.IndexBuffer.Length / 3);
                for (int i = 0; i < lodmodel.IndexBuffer.Length; i += 3)
                {
                    triangles.Add(new Triangle(lodmodel.IndexBuffer[i], lodmodel.IndexBuffer[i + 1], lodmodel.IndexBuffer[i + 2]));
                }
                WorldMesh mesh = new WorldMesh(Device, triangles, vertices);
                // Sections
                List <ModelPreviewSection> sections = new List <ModelPreviewSection>();
                foreach (var section in lodmodel.Sections)
                {
                    if (section.MaterialIndex < Materials.Count)
                    {
                        sections.Add(new ModelPreviewSection(Materials.Keys.ElementAt(section.MaterialIndex), section.BaseIndex, (uint)section.NumTriangles));
                    }
                }
                LODs.Add(new ModelPreviewLOD(mesh, sections));
            }
        }
예제 #32
0
 private void ReadImports(FileStream fs)
 {
     int pos = ImportOffset;
     Imports = new List<ImportEntry>();
     for (int i = 0; i < ImportCount; i++)
     {
         int start = pos;
         int package = ReadInt32(fs, pos);
         pos += 16;
         int link = ReadInt32(fs, pos);
         pos += 4;
         int name = ReadInt32(fs, pos);
         pos += 8;
         int len = pos - start;
         byte[] buff = new byte[len];
         fs.Seek(start, SeekOrigin.Begin);
         for (int j = 0; j < len; j++)
             buff[j] = (byte)fs.ReadByte();
         ImportEntry e = new ImportEntry();
         e.Package = package;
         e.link = link;
         e.name = name;
         e.raw = buff;
         Imports.Add(e);
     }
 }
 public static bool IsErrorStatusCode(this ImportEntry importEntry)
 {
     return(importEntry.StatusCode != 0);
 }
예제 #34
0
 public void Remove(ImportEntry item)
 {
     _list.Remove(item);
 }
예제 #35
0
        /// <summary>
        /// Imports an export from another package file.
        /// </summary>
        /// <param name="mePackage"></param>
        /// <param name="ex">Export object from the other package to import</param>
        /// <param name="link">Local parent node UIndex</param>
        /// <param name="outputEntry">Newly generated export entry reference</param>
        /// <returns></returns>
        private static bool importExport(IMEPackage mePackage, ExportEntry ex, int link, out ExportEntry outputEntry)
        {
            byte[] prePropBinary;
            if (ex.HasStack)
            {
                if (mePackage.Game < MEGame.ME3)
                {
                    prePropBinary = new byte[]
                    {
                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
                    };
                }
                else
                {
                    prePropBinary = new byte[]
                    {
                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
                    };
                }
            }
            else
            {
                int start = ex.GetPropertyStart();
                prePropBinary = new byte[start];
            }

            PropertyCollection props = ex.GetProperties();
            //store copy of names list in case something goes wrong
            List <string> names = mePackage.Names.ToList();

            try
            {
                if (ex.Game != mePackage.Game)
                {
                    props = EntryPruner.RemoveIncompatibleProperties(ex.FileRef, props, ex.ClassName, mePackage.Game);
                }
            }
            catch (Exception exception)
            {
                //restore namelist in event of failure.
                mePackage.setNames(names);
                Console.WriteLine($"Error occured while trying to import {ex.ObjectName} : {exception.Message}");
                //MessageBox.Show($"Error occured while trying to import {ex.ObjectName} : {exception.Message}");
                outputEntry = null;
                return(false);
            }

            //takes care of slight header differences between ME1/2 and ME3
            byte[] newHeader = ex.GenerateHeader(mePackage.Game);

            //for supported classes, this will add any names in binary to the Name table, as well as take care of binary differences for cross-game importing
            //for unsupported classes, this will just copy over the binary
            byte[] binaryData = ExportBinaryConverter.ConvertPostPropBinary(ex, mePackage.Game).ToArray(mePackage);

            int classValue = 0;
            int archetype  = 0;
            int superclass = 0;

            //Set class. This will only work if the class is an import, as we can't reliably pull in exports without lots of other stuff.
            if (ex.idxClass < 0)
            {
                //The class of the export we are importing is an import. We should attempt to relink this.
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxClass);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                classValue = newClassImport.UIndex;
            }
            else if (ex.idxClass > 0)
            {
                //Todo: Add cross mapping support as multi-mode will allow this to work now
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxClass);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    classValue = matchingExport.UIndex;
                }
            }

            //Set superclass
            if (ex.idxSuperClass < 0)
            {
                //The class of the export we are importing is an import. We should attempt to relink this.
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxSuperClass);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                superclass = newClassImport.UIndex;
            }
            else if (ex.idxSuperClass > 0)
            {
                //Todo: Add cross mapping support as multi-mode will allow this to work now
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxSuperClass);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    superclass = matchingExport.UIndex;
                }
            }

            //Check archetype.
            if (ex.idxArchtype < 0)
            {
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxArchtype);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                archetype = newClassImport.UIndex;
            }
            else if (ex.idxArchtype > 0)
            {
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxArchtype);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    archetype = matchingExport.UIndex;
                }
            }

            outputEntry = new ExportEntry(mePackage, prePropBinary, props, binaryData)
            {
                Header        = newHeader,
                idxClass      = classValue,
                idxObjectName = mePackage.FindNameOrAdd(ex.FileRef.getNameEntry(ex.idxObjectName)),
                idxLink       = link,
                idxSuperClass = superclass,
                idxArchtype   = archetype
            };
            mePackage.addExport(outputEntry);

            return(true);
        }
예제 #36
0
        /// <summary>
        ///     PCCObject class constructor. It also load namelist, importlist and exportinfo (not exportdata) from pcc file
        /// </summary>
        /// <param name="pccFilePath">full path + file name of desired pcc file.</param>
        public PCCObject(string pccFilePath, bool fullFileInMemory = false)
        {
            Loaded      = true;
            pccFileName = Path.GetFullPath(pccFilePath);
            Debug.WriteLine("Loading pcc " + pccFileName);
            using (FileStream pccStream = File.OpenRead(pccFileName))
            {
                Names   = new List <string>();
                Imports = new List <ImportEntry>();
                Exports = new List <ExportEntry>();

                pccStream.Read(header, 0, header.Length);
                if (magic != ZBlock.magic &&
                    magic.Swap() != ZBlock.magic)
                {
                    throw new FormatException("not a pcc file");
                }

                // BitConverter isn't working?!?!
                if (magic == 0x9E2A83C1)
                {
                    BitConverter.IsLittleEndian = true;
                }
                else
                {
                    BitConverter.IsLittleEndian = true;
                }

                if (lowVers != 684 && highVers != 194)
                {
                    throw new FormatException("unsupported version");
                }

                Stream listsStream;

                if (bCompressed)
                {
                    Debug.WriteLine("COMPRESSED...");
                    // seeks the blocks info position
                    pccStream.Seek(idxOffsets + 60, SeekOrigin.Begin);
                    int generator = pccStream.ReadValueS32();
                    pccStream.Seek((generator * 12) + 20, SeekOrigin.Current);

                    int blockCount = pccStream.ReadValueS32();
                    blockList = new List <Block>();

                    // creating the Block list
                    for (int i = 0; i < blockCount; i++)
                    {
                        Block temp = new Block();
                        temp.uncOffset = pccStream.ReadValueS32();
                        temp.uncSize   = pccStream.ReadValueS32();
                        temp.cprOffset = pccStream.ReadValueS32();
                        temp.cprSize   = pccStream.ReadValueS32();
                        blockList.Add(temp);
                    }

                    // correcting the header, in case there's need to be saved
                    Buffer.BlockCopy(BitConverter.GetBytes((int)0), 0, header, header.Length - 12, sizeof(int));
                    pccStream.Read(header, header.Length - 8, 8);
                    headerEnd = (int)pccStream.Position;

                    // copying the extraNamesList
                    int extraNamesLenght = blockList[0].cprOffset - headerEnd;
                    if (extraNamesLenght > 0)
                    {
                        extraNamesList = new byte[extraNamesLenght];
                        pccStream.Read(extraNamesList, 0, extraNamesLenght);
                        //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin");
                        //fileStream.Write(extraNamesList, 0, extraNamesLenght);
                        //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8"));
                    }

                    // decompress first block that holds infos about names, imports and exports
                    pccStream.Seek(blockList[0].cprOffset, SeekOrigin.Begin);
                    byte[] uncBlock = ZBlock.Decompress(pccStream, blockList[0].cprSize);

                    // write decompressed block inside temporary stream
                    listsStream = new MemoryStream();
                    listsStream.Seek(blockList[0].uncOffset, SeekOrigin.Begin);
                    listsStream.Write(uncBlock, 0, uncBlock.Length);
                }
                else
                {
                    listsStream = pccStream;
                    headerEnd   = (int)NameOffset;

                    // copying the extraNamesList
                    int extraNamesLenght = headerEnd - headerSize;
                    if (extraNamesLenght > 0)
                    {
                        extraNamesList = new byte[extraNamesLenght];
                        listsStream.Seek(headerSize, SeekOrigin.Begin);
                        listsStream.Read(extraNamesList, 0, extraNamesLenght);
                        //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin");
                        //fileStream.Write(extraNamesList, 0, extraNamesLenght);
                        //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8"));
                    }
                }

                /*if(bExtraNamesList)
                 * {
                 *  int extraNamesListSize = namesOffset - headerEnd;
                 *  extraNamesList = new byte[extraNamesListSize];
                 *  pccStream.Seek(headerEnd, SeekOrigin.Begin);
                 *  pccStream.Read(extraNamesList, 0, extraNamesList.Length);
                 * }*/

                // 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);
                    //Debug.WriteLine("Read name "+i+" "+str+" length: " + strLength+", offset: "+currOffset);
                    Names.Add(str);
                }
                //Debug.WriteLine("Names done. Current offset: "+listsStream.Position);
                //Debug.WriteLine("Import Offset: " + ImportOffset);

                // fill import list
                //Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset);
                listsStream.Seek(ImportOffset, SeekOrigin.Begin);
                byte[] buffer = new byte[ImportEntry.byteSize];
                for (int i = 0; i < ImportCount; i++)
                {
                    long        offset = listsStream.Position;
                    ImportEntry e      = new ImportEntry(this, listsStream);
                    Imports.Add(e);
                    //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset);
                }
                ;

                // fill export list (only the headers, not the data)
                listsStream.Seek(ExportOffset, SeekOrigin.Begin);
                //Console.Out.WriteLine("Export OFFSET: " + ImportOffset);
                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);
                    ExportEntry e = new ExportEntry(this, buffer, expInfoOffset);
                    //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize);
                    Exports.Add(e);
                }
            }
            //Debug.WriteLine(getMetadataString());
        }
예제 #37
0
        /// <summary>
        /// Adds an import from the importingPCC to the destinationPCC with the specified importFullName, or returns the existing one if it can be found.
        /// This will add parent imports and packages as neccesary
        /// </summary>
        /// <param name="importFullName">GetFullPath() of an import from ImportingPCC</param>
        /// <param name="importingPCC">PCC to import imports from</param>
        /// <param name="destinationPCC">PCC to add imports to</param>
        /// <param name="forcedLink">force this as parent</param>
        /// <returns></returns>
        public static IEntry getOrAddCrossImportOrPackage(string importFullName, IMEPackage importingPCC, IMEPackage destinationPCC, int?forcedLink = null)
        {
            if (string.IsNullOrEmpty(importFullName))
            {
                return(null);
            }

            //see if this import exists locally
            foreach (ImportEntry imp in destinationPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    return(imp);
                }
            }

            //see if this is an export Package and exists locally
            foreach (ExportEntry exp in destinationPCC.Exports)
            {
                if (exp.ClassName == "Package" && exp.GetFullPath == importFullName)
                {
                    return(exp);
                }
            }

            if (forcedLink is int link)
            {
                ImportEntry importingImport = importingPCC.Imports.First(x => x.GetFullPath == importFullName); //this shouldn't be null
                var         newImport       = new ImportEntry(destinationPCC)
                {
                    idxLink        = link,
                    idxClassName   = destinationPCC.FindNameOrAdd(importingImport.ClassName),
                    idxObjectName  = destinationPCC.FindNameOrAdd(importingImport.ObjectName),
                    idxPackageFile = destinationPCC.FindNameOrAdd(importingImport.PackageFile)
                };
                destinationPCC.addImport(newImport);
                return(newImport);
            }

            string[] importParts = importFullName.Split('.');

            //recursively ensure parent package exists. when importParts.Length == 1, this will return null
            IEntry parent = getOrAddCrossImportOrPackage(string.Join(".", importParts.Take(importParts.Length - 1)), importingPCC, destinationPCC);


            foreach (ImportEntry imp in importingPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    var import = new ImportEntry(destinationPCC)
                    {
                        idxLink        = parent?.UIndex ?? 0,
                        idxClassName   = destinationPCC.FindNameOrAdd(imp.ClassName),
                        idxObjectName  = destinationPCC.FindNameOrAdd(imp.ObjectName),
                        idxPackageFile = destinationPCC.FindNameOrAdd(imp.PackageFile)
                    };
                    destinationPCC.addImport(import);
                    return(import);
                }
            }

            foreach (ExportEntry exp in importingPCC.Exports)
            {
                if (exp.ClassName == "Package" && exp.GetFullPath == importFullName)
                {
                    importExport(destinationPCC, exp, parent?.UIndex ?? 0, out ExportEntry package);
                    return(package);
                }
            }

            throw new Exception($"Unable to add {importFullName} to file! Could not find it!");
        }
예제 #38
0
        // Todo: ME3Exp 5.1: Get rid of this and use the import resolver. It must support a cache so we don't constnatly open packages
        internal static ExportEntry FindExternalAsset(ImportEntry entry, List <ExportEntry> alreadyLoadedPackageEntries, List <IMEPackage> openedPackages)
        {
            //Debug.WriteLine("Finding external asset " + entry.GetFullPath);
            if (entry.Game == MEGame.ME1)
            {
                var    sourcePackageInternalPath = entry.FullPath.Substring(entry.FullPath.IndexOf('.') + 1);
                string baseName = entry.FileRef.FollowLink(entry.idxLink).Split('.')[0].ToUpper() + ".upk"; //Get package filename
                var    preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(baseName, StringComparison.InvariantCultureIgnoreCase));
                if (preloadedPackageEntry == null && MELoadedFiles.GetFilesLoadedInGame(MEGame.ME1).TryGetValue(baseName, out string packagePath))
                {
                    var package = MEPackageHandler.OpenMEPackage(packagePath);
                    if (openedPackages != null && !openedPackages.Contains(package))
                    {
                        openedPackages.Add(package);
                    }

                    var foundExp = package.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    if (openedPackages == null)
                    {
                        package.Dispose();
                    }
                }
                else
                {
                    Debug.WriteLine("ME1 External Asset lookup: Using existing preloaded export package");
                    var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                }
            }
            else
            {
                // Next, split the filename by underscores
                string filenameWithoutExtension = Path.GetFileNameWithoutExtension(entry.FileRef.FilePath).ToLower();
                string containingDirectory      = Path.GetDirectoryName(entry.FileRef.FilePath);
                var    packagesToCheck          = new List <string>();
                var    gameFiles = MELoadedFiles.GetFilesLoadedInGame(entry.Game);

                if (filenameWithoutExtension.StartsWith("bioa_") || filenameWithoutExtension.StartsWith("biod_"))
                {
                    string[] parts = filenameWithoutExtension.Split('_');
                    if (parts.Length >= 2) //BioA_Nor_WowThatsAlot310.pcc
                    {
                        string bioad    = $"{parts[0]}_{parts[1]}.pcc";
                        string filename = Path.Combine(containingDirectory, bioad); //BioA_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }

                        string biop = $"BioP_{parts[1]}.pcc";
                        filename = Path.Combine(containingDirectory, biop); //BioP_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }
                    }
                }

                // Add globals
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "SFXGame.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "EntryMenu.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), entry.Game == MEGame.ME3 ? "Startup.pcc" : "Startup_INT.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "Engine.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "Engine.u")); //ME1

                foreach (string packagePath in packagesToCheck)
                {
                    if (File.Exists(packagePath))
                    {
                        var preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(packagePath, StringComparison.InvariantCultureIgnoreCase));
                        if (preloadedPackageEntry == null)
                        {
                            var sentry = searchPackageForEntry(packagePath, entry.FullPath, entry.ClassName, openedPackages);
                            if (sentry != null)
                            {
                                return(sentry);
                            }
                        }
                        else
                        {
                            Debug.WriteLine("ME2/3 External Asset lookup: Using existing preloaded export package");
                            var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                            if (foundExp != null)
                            {
                                return(foundExp);
                            }
                        }
                    }
                }
            }

            Debug.WriteLine("Could not find external asset: " + entry.FullPath);
            return(null);
        }
예제 #39
0
 public void Add(ImportEntry item)
 {
     _list.Add(item);
 }
예제 #40
0
        private static string relinkUIndex(IMEPackage importingPCC, ExportEntry relinkingExport, ref int uIndex, string propertyName,
                                           OrderedMultiValueDictionary <IEntry, IEntry> crossPCCObjectMappingList, string prefix, bool importExportDependencies = false)
        {
            if (uIndex == 0)
            {
                return(null); //do not relink 0
            }

            IMEPackage destinationPcc = relinkingExport.FileRef;

            if (importingPCC == destinationPcc && uIndex < 0)
            {
                return(null); //do not relink same-pcc imports.
            }
            int sourceObjReference = uIndex;

            //Debug.WriteLine($"{prefix} Relinking:{propertyName}");

            if (crossPCCObjectMappingList.TryGetValue(entry => entry.UIndex == sourceObjReference, out IEntry targetEntry))
            {
                //relink
                uIndex = targetEntry.UIndex;

                //Debug.WriteLine($"{prefix} Relink hit: {sourceObjReference}{propertyName} : {targetEntry.FullPath}");
            }
            else if (uIndex < 0) //It's an unmapped import
            {
                //objProperty is currently pointing to importingPCC as that is where we read the properties from
                int n         = uIndex;
                int origvalue = n;
                //Debug.WriteLine("Relink miss, attempting JIT relink on " + n + " " + rootNode.Text);
                if (importingPCC.IsImport(n))
                {
                    //Get the original import
                    ImportEntry origImport         = importingPCC.GetImport(n);
                    string      origImportFullName = origImport.FullPath;
                    //Debug.WriteLine("We should import " + origImport.GetFullPath);

                    IEntry crossImport          = null;
                    string linkFailedDueToError = null;
                    try
                    {
                        crossImport = EntryImporter.GetOrAddCrossImportOrPackage(origImportFullName, importingPCC, destinationPcc);
                    }
                    catch (Exception e)
                    {
                        //Error during relink
                        DebugOutput.StartDebugger("PCC Relinker");
                        DebugOutput.PrintLn("Exception occured during relink: ");
                        DebugOutput.PrintLn(ExceptionHandlerDialogWPF.FlattenException(e));
                        DebugOutput.PrintLn("You may want to consider discarding this sessions' changes as relinking was not able to properly finish.");
                        linkFailedDueToError = e.Message;
                    }

                    if (crossImport != null)
                    {
                        crossPCCObjectMappingList.Add(origImport, crossImport); //add to mapping to speed up future relinks
                        uIndex = crossImport.UIndex;
                        // Debug.WriteLine($"Relink hit: Dynamic CrossImport for {origvalue} {importingPCC.GetEntry(origvalue).FullPath} -> {uIndex}");
                    }
                    else
                    {
                        string path = importingPCC.GetEntry(uIndex) != null?importingPCC.GetEntry(uIndex).FullPath : "Entry not found: " + uIndex;

                        if (linkFailedDueToError != null)
                        {
                            Debug.WriteLine($"Relink failed: CrossImport porting failed for {relinkingExport.ObjectName.Instanced} {relinkingExport.UIndex}: {propertyName} ({uIndex}): {importingPCC.GetEntry(origvalue).FullPath}");
                            return($"Relink failed for {prefix}{propertyName} {uIndex} in export {path}({relinkingExport.UIndex}): {linkFailedDueToError}");
                        }

                        if (destinationPcc.GetEntry(uIndex) != null)
                        {
                            Debug.WriteLine($"Relink failed: CrossImport porting failed for {relinkingExport.ObjectName.Instanced} {relinkingExport.UIndex}: {propertyName} ({uIndex}): {importingPCC.GetEntry(origvalue).FullPath}");
                            return($"Relink failed: CrossImport porting failed for {prefix}{propertyName} {uIndex} {destinationPcc.GetEntry(uIndex).FullPath} in export {relinkingExport.FullPath}({relinkingExport.UIndex})");
                        }

                        return($"Relink failed: New export does not exist - this is probably a bug in cross import code for {prefix}{propertyName} {uIndex} in export {relinkingExport.FullPath}({relinkingExport.UIndex})");
                    }
                }
            }
            else
            {
                //It's an export
                //Attempt lookup
                ExportEntry sourceExport  = importingPCC.GetUExport(uIndex);
                string      fullPath      = sourceExport.FullPath;
                int         indexValue    = sourceExport.indexValue;
                IEntry      existingEntry = destinationPcc.Exports.FirstOrDefault(x => x.FullPath == fullPath && indexValue == x.indexValue);
                existingEntry ??= destinationPcc.Imports.FirstOrDefault(x => x.FullPath == fullPath);
                if (existingEntry != null)
                {
                    //Debug.WriteLine($"Relink hit [EXPERIMENTAL]: Existing entry in file was found, linking to it:  {uIndex} {sourceExport.InstancedFullPath} -> {existingEntry.InstancedFullPath}");
                    uIndex = existingEntry.UIndex;
                }
                else if (importExportDependencies)
                {
                    if (!crossPCCObjectMappingList.TryGetValue(sourceExport.Parent, out IEntry parent))
                    {
                        parent = EntryImporter.GetOrAddCrossImportOrPackage(sourceExport.ParentFullPath, importingPCC, destinationPcc, true, crossPCCObjectMappingList);
                    }
                    ExportEntry importedExport = EntryImporter.ImportExport(destinationPcc, sourceExport, parent?.UIndex ?? 0, true, crossPCCObjectMappingList);
                    uIndex = importedExport.UIndex;
                }
                else
                {
                    string path = importingPCC.GetEntry(uIndex)?.FullPath ?? $"Entry not found: {uIndex}";
                    Debug.WriteLine($"Relink failed in {relinkingExport.ObjectName.Instanced} {relinkingExport.UIndex}: {propertyName} {uIndex} {path}");
                    return($"Relink failed: {prefix}{propertyName} {uIndex} in export {relinkingExport.FullPath}({relinkingExport.UIndex})");
                }
            }

            return(null);
        }
예제 #41
0
        /// <summary>
        ///     UDKFile class constructor. It also load namelist, importlist and exportinfo (not exportdata) from udk file
        /// </summary>
        /// <param name="udkFilePath">full path + file name of desired udk file.</param>
        public UDKFile(string udkFilePath, bool fullFileInMemory = false)
        {
            Loaded = true;
            FileName = Path.GetFullPath(udkFilePath);
            using (FileStream udkStream = File.OpenRead(FileName))
            {
                Names = new List<NameEntry>();
                Imports = new List<ImportEntry>();
                Exports = new List<ExportEntry>();

                udkStream.Read(header, 0, header.Length);

                //unsure about magic number. for now just let it try anything
                if (magic != 2653586369)
                {
                    //throw new FormatException("not a udk file");
                }

                //again, unsure of what versions ought to be supported
                if (lowVers != 684 && highVers != 0)
                {
                    //throw new FormatException("unsupported version");
                }

                Stream listsStream;
                listsStream = udkStream;
                headerEnd = NameOffset;

                // fill names list
                listsStream.Seek(NameOffset, SeekOrigin.Begin);
                for (int i = 0; i < NameCount; i++)
                {
                    long currOffset = listsStream.Position;
                    int strLength = listsStream.ReadValueS32();
                    NameEntry n = new NameEntry();
                    if (strLength < 0)
                    {
                        n.name = listsStream.ReadString(strLength * -2, true, Encoding.Unicode); 
                    }
                    else
                    {
                        n.name = listsStream.ReadString(strLength, true, Encoding.ASCII);
                    }
                    n.unk = listsStream.ReadValueS32();
                    n.flags = listsStream.ReadValueS32();
                    Names.Add(n);
                }
                //Debug.WriteLine("Names done. Current offset: "+listsStream.Position);
                //Debug.WriteLine("Import Offset: " + ImportOffset);

                // fill import list
                //Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset);
                listsStream.Seek(ImportOffset, SeekOrigin.Begin);
                byte[] buffer = new byte[ImportEntry.byteSize];
                for (int i = 0; i < ImportCount; i++)
                {

                    long offset = listsStream.Position;
                    ImportEntry e = new ImportEntry(this, listsStream);
                    Imports.Add(e);
                    //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset);
                };

                // fill export list (only the headers, not the data)
                listsStream.Seek(ExportOffset, SeekOrigin.Begin);
                //Console.Out.WriteLine("Export OFFSET: " + ImportOffset);
                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);
                    ExportEntry e = new ExportEntry(this, buffer, expInfoOffset);
                    //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize); 
                    Exports.Add(e);
                }
            }
            Debug.WriteLine(getMetadataString());
        }