public static byte[] ConvertPrePropBinary(ExportEntry export, MEGame newGame)
        {
            if (export.HasStack)
            {
                var   ms        = new MemoryStream(export.Data);
                int   node      = ms.ReadInt32();
                int   stateNode = ms.ReadInt32();
                ulong probeMask = ms.ReadUInt64();
                if (export.Game == MEGame.ME3)
                {
                    ms.SkipInt16();
                }
                else
                {
                    ms.SkipInt32();
                }

                int    count      = ms.ReadInt32();
                byte[] stateStack = ms.ReadToBuffer(count * 12);
                int    offset     = 0;
                if (node != 0)
                {
                    offset = ms.ReadInt32();
                }

                int netIndex = ms.ReadInt32();

                var os = new MemoryStream();
                os.WriteInt32(node);
                os.WriteInt32(stateNode);
                os.WriteUInt64(probeMask);
                if (newGame == MEGame.ME3)
                {
                    os.WriteUInt16(0);
                }
                else
                {
                    os.WriteUInt32(0);
                }
                os.WriteInt32(count);
                os.WriteFromBuffer(stateStack);
                if (node != 0)
                {
                    os.WriteInt32(offset);
                }
                os.WriteInt32(netIndex);

                return(os.ToArray());
            }

            switch (export.ClassName)
            {
            case "DominantSpotLightComponent":
            case "DominantDirectionalLightComponent":
                //todo: do conversion for these
                break;
            }

            return(export.Data.Slice(0, export.GetPropertyStart()));
        }
Beispiel #2
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);
        }
Beispiel #3
0
        public void Write2DAToExport()
        {
            using (var stream = new MemoryStream())
            {
                //Cell count
                if (IsIndexed)
                {
                    //Indexed ones seem to have 0 at start
                    stream.WriteBytes(BitConverter.GetBytes(0));
                }
                stream.WriteBytes(BitConverter.GetBytes(PopulatedCellCount));

                //Write cell data
                for (int rowindex = 0; rowindex < RowCount; rowindex++)
                {
                    for (int colindex = 0; colindex < ColumnCount; colindex++)
                    {
                        Bio2DACell cell = Cells[rowindex, colindex];
                        if (cell != null)
                        {
                            if (IsIndexed)
                            {
                                //write index
                                int index = (rowindex * ColumnCount) + colindex; //+1 because they are not zero based indexes since they are numerals
                                stream.WriteBytes(BitConverter.GetBytes(index));
                            }
                            stream.WriteByte((byte)cell.Type);
                            stream.WriteBytes(cell.Data);
                        }
                        else
                        {
                            if (IsIndexed)
                            {
                                //this is a blank cell. It is not present in the table.
                                continue;
                            }
                            else
                            {
                                Debug.WriteLine("THIS SHOULDN'T OCCUR!");
                                Debugger.Break();
                                throw new Exception("A non-indexed Bio2DA cannot have null cells.");
                            }
                        }
                    }
                }

                //Write Columns
                if (!IsIndexed)
                {
                    stream.WriteBytes(BitConverter.GetBytes(0)); //seems to be a 0 before column definitions
                }
                //Console.WriteLine("Columns defs start at " + stream.Position.ToString("X6"));
                stream.WriteBytes(BitConverter.GetBytes(ColumnCount));
                for (int colindex = 0; colindex < ColumnCount; colindex++)
                {
                    //Console.WriteLine("Writing column definition " + columnNames[colindex]);
                    int nameIndexForCol = export.FileRef.FindNameOrAdd(ColumnNames[colindex]);
                    stream.WriteBytes(BitConverter.GetBytes(nameIndexForCol));
                    stream.WriteBytes(BitConverter.GetBytes(0)); //second half of name reference in 2da is always zero since they're always indexed at 0
                    stream.WriteBytes(BitConverter.GetBytes(colindex));
                }

                int    propsEnd   = export.propsEnd();
                byte[] binarydata = stream.ToArray();

                //Todo: Rewrite properties here
                PropertyCollection props = new PropertyCollection();
                if (export.ClassName == "Bio2DA")
                {
                    var indicies = new ArrayProperty <NameProperty>("m_sRowLabel");
                    foreach (var rowname in RowNames)
                    {
                        indicies.Add(new NameProperty(rowname));
                    }
                    props.Add(indicies);
                }
                else
                {
                    var indices = new ArrayProperty <IntProperty>("m_lstRowNumbers");
                    foreach (var rowname in RowNames)
                    {
                        indices.Add(new IntProperty(int.Parse(rowname)));
                    }
                    props.Add(indices);
                }

                MemoryStream propsStream = new MemoryStream();
                props.WriteTo(propsStream, export.FileRef);
                MemoryStream currentDataStream   = new MemoryStream(export.Data);
                byte[]       propertydata        = propsStream.ToArray();
                int          propertyStartOffset = export.GetPropertyStart();
                var          newExportData       = new byte[propertyStartOffset + propertydata.Length + binarydata.Length];
                Buffer.BlockCopy(export.Data, 0, newExportData, 0, propertyStartOffset);
                propertydata.CopyTo(newExportData, propertyStartOffset);
                binarydata.CopyTo(newExportData, propertyStartOffset + propertydata.Length);
                //Console.WriteLine("Old data size: " + export.Data.Length);
                //Console.WriteLine("NEw data size: " + newExportData.Length);

                //This assumes the input and output data sizes are the same. We should not assume this with new functionality
                //if (export.Data.Length != newExportData.Length)
                //{
                //    Debug.WriteLine("FILES ARE WRONG SIZE");
                //    Debugger.Break();
                //}
                export.Data = newExportData;
            }
        }