Example #1
0
 public byte[] GetImageBytesForMip(Texture2DMipInfo info, GameTarget target, bool useLowerMipsIfTFCMissing, List <string> additionalTFCs = null)
 {
     byte[] imageBytes = null;
     try
     {
         imageBytes = GetTextureData(info, target, additionalTFCs: additionalTFCs);
     }
     catch (FileNotFoundException e)
     {
         if (useLowerMipsIfTFCMissing)
         {
             Debug.WriteLine("External cache not found. Defaulting to internal mips.");
             //External archive not found - using built in mips (will be hideous, but better than nothing)
             info = Mips.FirstOrDefault(x => x.storageType == StorageTypes.pccUnc);
             if (info != null)
             {
                 imageBytes = GetTextureData(info, target);
             }
         }
         else
         {
             throw e; //rethrow
         }
     }
     if (imageBytes == null)
     {
         throw new Exception("Could not fetch texture data for texture " + info?.Export.ObjectName);
     }
     return(imageBytes);
 }
Example #2
0
        public static List <Texture2DMipInfo> GetTexture2DMipInfos(ExportEntry exportEntry, string cacheName)
        {
            MemoryStream ms = new MemoryStream(exportEntry.Data);

            ms.Seek(exportEntry.propsEnd(), SeekOrigin.Begin);
            if (exportEntry.FileRef.Game != Mod.MEGame.ME3)
            {
                ms.Skip(4);                     //BulkDataFlags
                ms.Skip(4);                     //ElementCount
                int bulkDataSize = ms.ReadInt32();
                ms.Seek(4, SeekOrigin.Current); // position in the package
                ms.Skip(bulkDataSize);          //skips over thumbnail png, if it exists
            }

            var mips       = new List <Texture2DMipInfo>();
            int numMipMaps = ms.ReadInt32();

            for (int l = 0; l < numMipMaps; l++)
            {
                Texture2DMipInfo mip = new Texture2DMipInfo
                {
                    Export            = exportEntry,
                    index             = l,
                    storageType       = (StorageTypes)ms.ReadInt32(),
                    uncompressedSize  = ms.ReadInt32(),
                    compressedSize    = ms.ReadInt32(),
                    externalOffset    = ms.ReadInt32(),
                    localExportOffset = (int)ms.Position,
                    TextureCacheName  = cacheName //If this is ME1, this will simply be ignored in the setter
                };
                switch (mip.storageType)
                {
                case StorageTypes.pccUnc:
                    ms.Seek(mip.uncompressedSize, SeekOrigin.Current);
                    break;

                case StorageTypes.pccLZO:
                case StorageTypes.pccZlib:
                    ms.Seek(mip.compressedSize, SeekOrigin.Current);
                    break;
                }

                mip.width  = ms.ReadInt32();
                mip.height = ms.ReadInt32();
                if (mip.width == 4 && mips.Exists(m => m.width == mip.width))
                {
                    mip.width = mips.Last().width / 2;
                }
                if (mip.height == 4 && mips.Exists(m => m.height == mip.height))
                {
                    mip.height = mips.Last().height / 2;
                }
                if (mip.width == 0)
                {
                    mip.width = 1;
                }
                if (mip.height == 0)
                {
                    mip.height = 1;
                }
                mips.Add(mip);
            }

            return(mips);
        }
Example #3
0
        public static byte[] GetTextureData(Texture2DMipInfo mipToLoad, GameTarget target, bool decompress = true, List <string> additionalTFCs = null)
        {
            var imagebytes = new byte[decompress ? mipToLoad.uncompressedSize : mipToLoad.compressedSize];

            //Debug.WriteLine("getting texture data for " + mipToLoad.Export.FullPath);
            if (mipToLoad.storageType == StorageTypes.pccUnc)
            {
                Buffer.BlockCopy(mipToLoad.Export.Data, mipToLoad.localExportOffset, imagebytes, 0, mipToLoad.uncompressedSize);
            }
            else if (mipToLoad.storageType == StorageTypes.pccLZO || mipToLoad.storageType == StorageTypes.pccZlib)
            {
                if (decompress)
                {
                    try
                    {
                        TextureCompression.DecompressTexture(imagebytes,
                                                             new MemoryStream(mipToLoad.Export.Data, mipToLoad.localExportOffset, mipToLoad.compressedSize),
                                                             mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                    }
                    catch (Exception e)
                    {
                        throw new Exception($"{e.Message}\nStorageType: {mipToLoad.storageType}\n");
                    }
                }
                else
                {
                    Buffer.BlockCopy(mipToLoad.Export.Data, mipToLoad.localExportOffset, imagebytes, 0, mipToLoad.compressedSize);
                }
            }
            else if (mipToLoad.storageType == StorageTypes.extUnc || mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib)
            {
                string        filename    = null;
                List <string> loadedFiles = MEDirectories.EnumerateGameFiles(target.Game, target.TargetPath);
                if (mipToLoad.Export.Game == Mod.MEGame.ME1)
                {
                    var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(mipToLoad.TextureCacheName, StringComparison.InvariantCultureIgnoreCase));

                    if (fullPath != null)
                    {
                        filename = fullPath;
                    }
                    else
                    {
                        throw new FileNotFoundException($"Externally referenced texture file not found in game: {mipToLoad.TextureCacheName}.");
                    }
                }
                else
                {
                    string archive = mipToLoad.TextureCacheName + ".tfc";

                    var localDirectoryTFCPath = Path.Combine(Path.GetDirectoryName(mipToLoad.Export.FileRef.FilePath), archive);
                    if (File.Exists(localDirectoryTFCPath))
                    {
                        filename = localDirectoryTFCPath;
                    }
                    else if (additionalTFCs != null && additionalTFCs.Any(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        filename = additionalTFCs.First(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                    }
                    else
                    {
                        var tfcs = loadedFiles.Where(x => x.EndsWith(@".tfc")).ToList();

                        var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                        if (fullPath != null)
                        {
                            filename = fullPath;
                        }
                        else
                        {
                            throw new FileNotFoundException($@"Externally referenced texture cache not found: {archive}.");
                        }
                    }
                }

                //exceptions above will prevent filename from being null here

                try
                {
                    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
                    {
                        try
                        {
                            fs.Seek(mipToLoad.externalOffset, SeekOrigin.Begin);
                            if (mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib)
                            {
                                if (decompress)
                                {
                                    using (MemoryStream tmpStream = new MemoryStream(fs.ReadToBuffer(mipToLoad.compressedSize)))
                                    {
                                        try
                                        {
                                            TextureCompression.DecompressTexture(imagebytes, tmpStream, mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                                        }
                                        catch (Exception e)
                                        {
                                            throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                                                "StorageType: " + mipToLoad.storageType + "\n" +
                                                                "External file offset: " + mipToLoad.externalOffset);
                                        }
                                    }
                                }
                                else
                                {
                                    fs.Read(imagebytes, 0, mipToLoad.compressedSize);
                                }
                            }
                            else
                            {
                                fs.Read(imagebytes, 0, mipToLoad.uncompressedSize);
                            }
                        }
                        catch (Exception e)
                        {
                            throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                                "StorageType: " + mipToLoad.storageType + "\n" +
                                                "External file offset: " + mipToLoad.externalOffset);
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                        "StorageType: " + mipToLoad.storageType + "\n" +
                                        "External file offset: " + mipToLoad.externalOffset);
                }
            }
            return(imagebytes);
        }