コード例 #1
0
ファイル: ME3Package.cs プロジェクト: aquadran/ME3Explorer
 private static void UpdateOffsets(IExportEntry export)
 {
     //update offsets for pcc-stored audio in wwisestreams
     if (export.ClassName == "WwiseStream" && export.GetProperty <NameProperty>("Filename") == null)
     {
         byte[] binData = export.getBinaryData();
         binData.OverwriteRange(12, BitConverter.GetBytes(export.DataOffset + export.propsEnd() + 16));
         export.setBinaryData(binData);
     }
     //update offsets for pcc-stored movies in texturemovies
     if (export.ClassName == "TextureMovie" && export.GetProperty <NameProperty>("TextureFileCacheName") == null)
     {
         byte[] binData = export.getBinaryData();
         binData.OverwriteRange(12, BitConverter.GetBytes(export.DataOffset + export.propsEnd() + 16));
         export.setBinaryData(binData);
     }
     //update offsets for pcc-stored mips in Textures
     else if (export.ClassName == "Texture2D" || export.ClassName == "LightMapTexture2D" || export.ClassName == "TextureFlipBook")
     {
         int          baseOffset = export.DataOffset + export.propsEnd();
         MemoryStream binData    = new MemoryStream(export.getBinaryData());
         for (int i = binData.ReadValueS32(); i > 0 && binData.Position < binData.Length; i--)
         {
             if (binData.ReadValueS32() == 0) //pcc-stored
             {
                 int uncompressedSize = binData.ReadValueS32();
                 binData.Seek(4, SeekOrigin.Current);                           //skip compressed size
                 binData.WriteValueS32(baseOffset + (int)binData.Position + 4); //update offset
                 binData.Seek(uncompressedSize + 8, SeekOrigin.Current);        //skip texture and width + height values
             }
             else
             {
                 binData.Seek(20, SeekOrigin.Current);//skip whole rest of mip definition
             }
         }
         export.setBinaryData(binData.ToArray());
     }
 }
コード例 #2
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);
        }