Beispiel #1
0
        static void Main(string[] args)
        {
            // If there are no arguments passed then it acts as if help command is ran but through an invalid usage
            if (args.Count() == 0)
            {
                Program.ShowHelpText(true);
                return;
            }

            switch (args[0].ToLower())
            {
            default:
            {
                // Allows for drag & drop of file/folders to be converted
                if (args.Count() == 1)
                {
                    if (File.Exists(args[0]))
                    {
                        string input = args[0];
                        args    = new string[3];
                        args[0] = string.Empty;         // Can equal blank string value

                        args[1] = "-in";
                        args[2] = input;

                        goto case "-c";
                    }
                }

                Program.ShowHelpText(true);
                return;
            }

            case "-h":
            case "-help":
            {
                Program.ShowHelpText();
                return;
            }

            case "-c":
            case "-convert":
            {
                string input  = null;
                string output = null;

                for (uint i = 1; i < args.Count(); i++)
                {
                    string option = args[i];

                    switch (option)
                    {
                    default:
                    {
                        Program.ShowHelpText(true);
                        return;
                    }

                    case "-in":
                    {
                        i++;
                        input = args[i];

                        break;
                    }

                    case "-out":
                    {
                        i++;
                        output = args[i];

                        break;
                    }
                    }
                }

                if (string.IsNullOrEmpty(input))
                {
                    Program.ShowHelpText(true);
                    return;
                }

                Console.WriteLine("Converting " + Path.GetFileName(input) + "...");
                NormalMap.ConvertToPS3(input, string.IsNullOrEmpty(output) ? input : output);

                Console.WriteLine("\nDone!\n");
                break;
            }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Writes BSA for Oblivion PS3.
        /// </summary>
        /// <param name="path">Real filesystem path to write BSA to.</param>
        /// <param name="assetList">List of <see cref="Asset"/> to write in BSA.</param>
        /// <param name="compress">True or false if assets in BSA should be compressed.</param>
        /// <param name="usePS3FileFlags">True or false if PS3 file flags should be used.</param>
        /// <param name="extendDDS">True or false if DDS texture file data should be extended.</param>
        /// <param name="convertNormalMaps">True or false if normal maps should be converted to PS3.</param>
        public static void Write(string path, List <Asset> assetList, bool compress, bool usePS3FileFlags, bool extendDDS, bool convertNormalMaps)
        {
            var  folderDict            = new Dictionary <string, List <Asset> >();
            var  extList               = new List <string>();
            uint totalFolderNameLength = 0;
            uint totalFileNameLength   = 0;

            // Sets up all assets to be in folderDict
            foreach (Asset asset in assetList)
            {
                string folderName = Path.GetDirectoryName(asset.EntryStr);

                if (!folderDict.ContainsKey(folderName))
                {
                    folderDict.Add(folderName, new List <Asset>());
                    totalFolderNameLength += (uint)folderName.Length + 1; // Includes null terminator, not prefixed length sbyte
                }

                totalFileNameLength += (uint)asset.FileName.Length + 1; // Includes null terminator
                folderDict[folderName].Add(asset);
                if (!extList.Contains(asset.Extension))
                {
                    extList.Add(asset.Extension);
                }
            }

            // Begins writing of archive
            using (var writer = new BinaryWriter(File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read)))
            {
                writer.Write(0x00415342); // "BSA" + 0x00, archive magic
                writer.Write(103);        // Version
                writer.Write(36);         // Folder records offset
                writer.Write(compress ? 0x00000707 : 0x00000703);
                writer.Write(folderDict.Count());
                writer.Write(assetList.Count());
                writer.Write(totalFolderNameLength);
                writer.Write(totalFileNameLength);
                writer.Write(BSA.GetFileFlags(extList, usePS3FileFlags)); // Texture archive file flags

                var folderOrdList = new List <string>();                  // Keeps order of folders, with folder names
                var folderOffList = new List <uint>();

                // Loops through the folder dictionary, while also organizing folders to follow Oblivion BSA rules
                foreach (KeyValuePair <string, List <Asset> > folder in folderDict.OrderBy(folder => OblivionBSAHash.GetPC(folder.Key)))
                {
                    folderOrdList.Add(folder.Key);
                    folder.Value.Sort((a, b) => a.Hash.CompareTo(b.Hash)); // Assets in folder sorted to follow Oblivion BSA rules

                    writer.Write(OblivionBSAHash.GetPC(folder.Key));
                    writer.Write(folder.Value.Count());
                    writer.Write(-1); // Temporary, file record offset
                }

                foreach (string folder in folderOrdList)
                {
                    folderOffList.Add((uint)writer.BaseStream.Position);
                    writer.Write((byte)(folder.Length + 1));
                    writer.Write(folder.ToCharArray());
                    writer.Write((byte)0);

                    foreach (Asset asset in folderDict[folder])
                    {
                        writer.Write(asset.Hash);
                        writer.Write((long)-1); // Temporary, asset size + offset
                    }
                }

                foreach (string folder in folderOrdList)
                {
                    foreach (Asset asset in folderDict[folder])
                    {
                        writer.WriteNullTerminatedString(asset.FileName);
                    }
                }

                foreach (string folder in folderOrdList)
                {
                    foreach (Asset asset in folderDict[folder])
                    {
                        asset.Offset = (uint)writer.BaseStream.Position;
                        byte[] data;

                        if (convertNormalMaps && asset.IsDDS && asset.IsNormalMap)
                        {
                            string tempPath  = Path.GetTempFileName();
                            bool   converted = NormalMap.ConvertToPS3(asset.RealPath, tempPath);

                            data = File.ReadAllBytes(converted ? tempPath : asset.RealPath);
                            File.Delete(tempPath); // Cleans up
                        }
                        else
                        {
                            data = File.ReadAllBytes(asset.RealPath);
                        }

                        bool extendAsset = extendDDS && asset.IsDDS && !asset.IsExtended;

                        if (compress)
                        {
                            asset.OriginalSize = extendAsset ? (uint)data.Length + (uint)asset.EntryStr.Length + 1 : (uint)data.Length;

                            writer.Write(asset.OriginalSize);
                            writer.Write(BSA.GetCompressedZlibData(data, asset, extendAsset));
                        }
                        else
                        {
                            asset.Size = (uint)data.Length;
                            writer.Write(data);

                            if (extendAsset)
                            {
                                asset.Size += (uint)asset.EntryStr.Length + 1; // +1 is accounting for null terminator
                                writer.Write(asset.EntryStr);
                            }
                        }
                    }
                }

                writer.BaseStream.Position = 36; // Folder record offset
                foreach (uint off in folderOffList)
                {
                    writer.BaseStream.Position += 12; // Skips hash and file count
                    writer.Write(off + totalFileNameLength);
                }

                foreach (string folder in folderOrdList)
                {
                    writer.BaseStream.Position += folder.Length + 2;

                    foreach (Asset asset in folderDict[folder])
                    {
                        writer.BaseStream.Position += 8; // Skips hash

                        writer.Write(asset.Size);
                        writer.Write(asset.Offset);
                    }
                }
            }
        }