예제 #1
0
        public static readonly uint Magic1 = 4;         // Maybe represents format version? Similar to survival file.

        public void MakeBinary(List <AbstractAsset> allAssets, string outputPath, ProgressWrapper progress)
        {
            progress.Report("Initializing 'particle' file creation.");

            allAssets = allAssets.Where(a => File.Exists(a.EditorPath)).ToList();

            byte[] fileBuffer;
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(BitConverter.GetBytes(4), 0, sizeof(int));
                stream.Write(BitConverter.GetBytes(allAssets.Count), 0, sizeof(int));
                int i = 0;
                foreach (KeyValuePair <string, byte[]> kvp in GetChunks(allAssets))
                {
                    progress.Report($"Writing file contents of \"{kvp.Key}\" to 'particle' file.", i++ / (float)allAssets.Count);

                    stream.Write(Encoding.Default.GetBytes(kvp.Key), 0, kvp.Key.Length);
                    stream.Write(kvp.Value, 0, kvp.Value.Length);
                }

                fileBuffer = stream.ToArray();
            }

            progress.Report("Writing 'particle' file.");
            File.WriteAllBytes(outputPath, fileBuffer);
        }
        private static void CreateFiles(string outputPath, byte[] sourceFileBytes, IEnumerable <ResourceChunk> chunks, ProgressWrapper progress)
        {
            int chunksDone  = 0;
            int totalChunks = chunks.Count();

            foreach (ResourceChunk chunk in chunks)
            {
                if (chunk.Size == 0)                 // Filter empty chunks (garbage in TOC buffers).
                {
                    continue;
                }

                string fileExtension = chunk.AssetType.GetFileExtension();

                progress.Report(
                    $"Creating {chunk.AssetType} file{(chunk.AssetType == AssetType.Shader ? "s" : string.Empty)} for chunk \"{chunk.Name}\".",
                    chunksDone++ / (float)totalChunks);

                byte[] buffer = new byte[chunk.Size];
                Buffer.BlockCopy(sourceFileBytes, (int)chunk.StartOffset, buffer, 0, (int)chunk.Size);

                chunk.Buffer = buffer;

                foreach (FileResult fileResult in chunk.ExtractBinary())
                {
                    string assetTypeDirectory = chunk.AssetType.GetFolderName();
                    if (!Directory.Exists(assetTypeDirectory))
                    {
                        Directory.CreateDirectory(Path.Combine(outputPath, assetTypeDirectory));
                    }
                    File.WriteAllBytes(Path.Combine(outputPath, assetTypeDirectory, fileResult.Name + (fileResult.Name == "loudness" && fileExtension == ".wav" ? ".ini" : fileExtension)), fileResult.Buffer.ToArray());
                }
            }
        }
        /// <summary>
        /// Extracts a binary file into multiple asset files.
        /// </summary>
        /// <param name="inputPath">The binary file path.</param>
        /// <param name="outputPath">The path where the extracted asset files will be placed.</param>
        /// <param name="progress">The progress wrapper to report progress to.</param>
        public void ExtractBinary(string inputPath, string outputPath, ProgressWrapper progress)
        {
            byte[] sourceFileBytes = File.ReadAllBytes(inputPath);

            progress.Report("Validating file.");
            ValidateFile(sourceFileBytes);

            progress.Report("Reading TOC buffer.");
            byte[] tocBuffer = ReadTocBuffer(sourceFileBytes);

            progress.Report("Creating chunks.");
            List <ResourceChunk> chunks = ReadChunks(tocBuffer);

            progress.Report("Initializing extraction.");
            CreateFiles(outputPath, sourceFileBytes, chunks, progress);
        }
        private static List <ResourceChunk> CreateChunksFromAssets(List <AbstractAsset> allAssets, ProgressWrapper progress)
        {
            StringBuilder loudness = new StringBuilder();

            List <ResourceChunk> chunks = new List <ResourceChunk>();

            foreach (AbstractAsset asset in allAssets)
            {
                progress.Report($"Generating {asset.AssetType} chunk \"{asset.AssetName}\".", chunks.Count / (float)allAssets.Count / 2);

                if (asset is AudioAsset audioAsset)
                {
                    loudness.AppendLine($"{audioAsset.AssetName} = {audioAsset.Loudness:0.0}");
                }

                ResourceChunk chunk = asset.AssetType switch
                {
                    AssetType.Model => new ModelChunk(asset.AssetName, 0, 0),
                    AssetType.Shader => new ShaderChunk(asset.AssetName, 0, 0),
                    AssetType.Texture => new TextureChunk(asset.AssetName, 0, 0),
                    _ => new ResourceChunk(asset.AssetType, asset.AssetName, 0, 0),
                };
                chunk.MakeBinary(asset.EditorPath);

                chunks.Add(chunk);
            }

            if (loudness.Length != 0)
            {
                progress.Report("Generating Loudness chunk.");
                byte[] fileBuffer;
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] fileContents = Encoding.Default.GetBytes(loudness.ToString());
                    ms.Write(fileContents, 0, fileContents.Length);
                    fileBuffer = ms.ToArray();
                }

                chunks.Add(new ResourceChunk(AssetType.Audio, "loudness", 0U, (uint)fileBuffer.Length)
                {
                    Buffer = fileBuffer
                });
            }

            return(chunks);
        }
예제 #5
0
        public void ExtractBinary(string inputPath, string outputPath, ProgressWrapper progress)
        {
            byte[] fileBuffer = File.ReadAllBytes(inputPath);

            Directory.CreateDirectory(Path.Combine(outputPath, AssetType.Particle.GetFolderName()));

            int i = HeaderSize;

            while (i < fileBuffer.Length)
            {
                ParticleChunk chunk = ReadParticleChunk(fileBuffer, i);
                i += chunk.Buffer.Length;

                progress.Report($"Creating Particle file for chunk \"{chunk.Name}\".", i / (float)fileBuffer.Length);

                File.WriteAllBytes(Path.Combine(outputPath, AssetType.Particle.GetFolderName(), chunk.Name + AssetType.Particle.GetFileExtension()), chunk.Buffer[chunk.Name.Length..]);
        private byte[] CreateAssetStream(List <ResourceChunk> chunks, byte[] tocBuffer, Dictionary <ResourceChunk, long> startOffsetBytePositions, ProgressWrapper progress)
        {
            using MemoryStream assetStream = new MemoryStream();
            int i = 0;

            foreach (ResourceChunk chunk in chunks)
            {
                progress.Report($"Writing file contents of \"{chunk.Name}\" to '{BinaryFileName}' file.", 0.5f + i++ / (float)chunks.Count / 2);

                uint startOffset = (uint)(HeaderSize + tocBuffer.Length + assetStream.Position);
                chunk.StartOffset = startOffset;

                // Write start offset to TOC stream.
                Buffer.BlockCopy(BitConverter.GetBytes(startOffset), 0, tocBuffer, (int)startOffsetBytePositions[chunk], sizeof(uint));

                // Write asset data to asset stream.
                byte[] bytes = chunk.Buffer.ToArray();
                assetStream.Write(bytes, 0, bytes.Length);
            }

            return(assetStream.ToArray());
        }
        /// <summary>
        /// Inserts multiple asset files into one binary file that can be read by Devil Daggers.
        /// </summary>
        /// <param name="allAssets">The list of asset objects.</param>
        /// <param name="outputPath">The path where the binary file will be placed.</param>
        /// <param name="progress">The progress wrapper to report progress to.</param>
        public void MakeBinary(List <AbstractAsset> allAssets, string outputPath, ProgressWrapper progress)
        {
            progress.Report($"Initializing '{BinaryFileName}' file creation.");

            allAssets = allAssets.Where(a => File.Exists(a.EditorPath)).ToList();             // TODO: Also check if FragmentShader file exists.

            progress.Report("Generating chunks based on asset list.");
            List <ResourceChunk> chunks = CreateChunksFromAssets(allAssets, progress);

            progress.Report("Generating TOC stream.");
            CreateTocStream(chunks, out byte[] tocBuffer, out Dictionary <ResourceChunk, long> startOffsetBytePositions);

            progress.Report("Generating asset stream.");
            byte[] assetBuffer = CreateAssetStream(chunks, tocBuffer, startOffsetBytePositions, progress);

            progress.Report($"Writing buffers to '{BinaryFileName}' file.");
            byte[] binaryBytes = CreateBinary(tocBuffer, assetBuffer);

            progress.Report($"Writing '{BinaryFileName}' file.");
            File.WriteAllBytes(outputPath, binaryBytes);
        }