Exemplo n.º 1
0
        public string Extract(BundleFileExtractArgs e)
        {
            var newpath = Path.ChangeExtension(e.FileName, "dds");
            var ext     = Path.GetExtension(e.FileName);

            // create new directory and delete existing file
            Directory.CreateDirectory(Path.GetDirectoryName(newpath) ?? "");
            if (File.Exists(newpath))
            {
                File.Delete(newpath);
            }

            // extract to dds
            using (var output = new FileStream(newpath, FileMode.Create, FileAccess.Write))
            {
                Extract(output);
            }

            // don't convert if user extract extension is already dds
            if (e.Extension == EUncookExtension.dds)
            {
                return(newpath);
            }
            // don't convert w2cube cubemaps
            if (ext == ".w2cube")
            {
                return(newpath);
            }

            var extractext = e.Extension;

            // do not convert pngs, jpgs and dds
            if (!(ext == ".dds" || ext == ".w2l"))
            {
                switch (ext)
                {
                case ".png":
                    extractext = EUncookExtension.png;
                    break;

                case ".jpg":
                    extractext = EUncookExtension.jpg;
                    break;
                }


                //convert
                var fi = new FileInfo(newpath);
                if (fi.Exists)
                {
                    TexconvWrapper.Convert(Path.GetDirectoryName(newpath), newpath, (Common.Tools.DDS.EUncookExtension)extractext);
                }

                // delete old DDS
                fi.Delete();
            }

            return(newpath);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Extracts all Files to the specified directory.
        /// </summary>
        /// <param name="outDir"></param>
        /// <returns></returns>
        public int ExtractAll(DirectoryInfo outDir, bool extract = true, bool uncook = false, EUncookExtension uncookext = EUncookExtension.tga)
        {
            var _maincontroller = ServiceLocator.Default.ResolveType <IMainController>();

            using var pb = new ProgressBar();
            using var p1 = pb.Progress.Fork();
            int progress = 0;

            using var mmf = MemoryMappedFile.CreateFromFile(Filepath, FileMode.Open, Mmfhash, 0,
                                                            MemoryMappedFileAccess.Read);

            Parallel.For(0, FileCount, new ParallelOptions {
                MaxDegreeOfParallelism = 8
            }, i =>
            {
                var info = Files.Values.ToList()[i];

                var(file, buffers) = GetFileData(info.NameHash64, mmf);

                var hash    = info.NameHash64;
                string name = $"{hash:X2}.bin";
                if (_maincontroller.Hashdict.ContainsKey(hash))
                {
                    name = _maincontroller.Hashdict[hash];
                }

                var outfile = new FileInfo(Path.Combine(outDir.FullName,
                                                        $"{name}"));
                if (outfile.Directory == null)
                {
                    return;
                }



                // write main file
                if (extract)
                {
                    Directory.CreateDirectory(outfile.Directory.FullName);
                    File.WriteAllBytes(outfile.FullName, file);
                }

                // write buffers
                for (int j = 0; j < buffers.Count; j++)
                {
                    if (uncook)
                    {
                        #region textures

                        if (Path.GetExtension(name) != ".xbm")
                        {
                            continue;
                        }
                        if (buffers.Count > 1)
                        {
                            //TODO: Log
                        }

                        // read cr2w
                        using var ms = new MemoryStream(file);
                        using var br = new BinaryReader(ms);
                        var cr2w     = new CR2WFile();
                        var result   = cr2w.Read(br);
                        if (result != EFileReadErrorCodes.NoError)
                        {
                            continue;
                        }
                        if (!(cr2w.Chunks.FirstOrDefault()?.data is CBitmapTexture xbm) ||
                            !(cr2w.Chunks[1]?.data is rendRenderTextureBlobPC blob))
                        {
                            continue;
                        }

                        // create dds header
                        var width      = blob.Header.SizeInfo.Width.val;
                        var height     = blob.Header.SizeInfo.Height.val;
                        var mips       = blob.Header.TextureInfo.MipCount.val;
                        var slicecount = blob.Header.TextureInfo.SliceCount.val;
                        var alignment  = blob.Header.TextureInfo.DataAlignment.val;

                        Directory.CreateDirectory(outfile.Directory.FullName);
                        using (var stream = new FileStream($"{outfile}.dds", FileMode.Create, FileAccess.Write))
                        {
                            DDSUtils.GenerateAndWriteHeader(stream,
                                                            new DDSMetadata(width, height, mips, EFormat.BC7_UNORM, alignment, false, slicecount));
                            var buffer = buffers[j];
                            stream.Write(buffer);
                        }

                        // convert to texture
                        if (uncookext != EUncookExtension.dds)
                        {
                            try
                            {
                                var di = new FileInfo(outfile.FullName).Directory;
                                TexconvWrapper.Convert(di.FullName, $"{outfile}.dds", uncookext);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                            }
                        }

                        #endregion
                    }
Exemplo n.º 3
0
        private int ExtractSingleInner(MemoryMappedFile mmf, ulong hash, DirectoryInfo outDir, bool extract = true, bool uncook = false,
                                       EUncookExtension uncookext = EUncookExtension.tga)
        {
            var maincontroller = ServiceLocator.Default.ResolveType <IMainController>();
            var logger         = ServiceLocator.Default.ResolveType <ILoggerService>();
            var success        = false;

            var(file, buffers) = GetFileData(hash, mmf);

            string name = $"{hash:X2}.bin";

            if (maincontroller.Hashdict.ContainsKey(hash))
            {
                name = maincontroller.Hashdict[hash];
            }

            var outfile = new FileInfo(Path.Combine(outDir.FullName,
                                                    $"{name}"));

            if (outfile.Directory == null)
            {
                return(0);
            }

            // write main file
            if (extract)
            {
                Directory.CreateDirectory(outfile.Directory.FullName);
                File.WriteAllBytes(outfile.FullName, file);
                success = true;
            }

            // write buffers
            for (int j = 0; j < buffers.Count; j++)
            {
                if (uncook)
                {
                    #region textures

                    if (Path.GetExtension(name) != ".xbm")
                    {
                        continue;
                    }
                    if (buffers.Count > 1)
                    {
                        //TODO: Log
                    }

                    // read cr2w
                    using var ms = new MemoryStream(file);
                    using var br = new BinaryReader(ms);
                    var cr2w   = new CR2WFile();
                    var result = cr2w.Read(br);
                    if (result != EFileReadErrorCodes.NoError)
                    {
                        continue;
                    }
                    if (!(cr2w.Chunks.FirstOrDefault()?.data is CBitmapTexture xbm) ||
                        !(cr2w.Chunks[1]?.data is rendRenderTextureBlobPC blob))
                    {
                        continue;
                    }

                    // create dds header
                    try
                    {
                        var width       = blob.Header.SizeInfo.Width.val;
                        var height      = blob.Header.SizeInfo.Height.val;
                        var mips        = blob.Header.TextureInfo.MipCount.val;
                        var slicecount  = blob.Header.TextureInfo.SliceCount.val;
                        var alignment   = blob.Header.TextureInfo.DataAlignment.val;
                        var compression = xbm.Setup.Compression?.WrappedEnum ?? Enums.ETextureCompression.TCM_None;

                        var texformat = CommonFunctions.GetEformatFromCompression(compression);

                        Directory.CreateDirectory(outfile.Directory.FullName);
                        using (var stream = new FileStream($"{outfile}.dds", FileMode.Create, FileAccess.Write))
                        {
                            DDSUtils.GenerateAndWriteHeader(stream,
                                                            new DDSMetadata(width, height, mips, texformat, alignment, false, slicecount, false));
                            var buffer = buffers[j];
                            stream.Write(buffer);
                        }

                        // success
                        success = true;
                    }
                    catch
                    {
                        success = false;
                        continue;
                    }

                    // convert to texture
                    if (uncookext != EUncookExtension.dds)
                    {
                        try
                        {
                            var di = new FileInfo(outfile.FullName).Directory;
                            TexconvWrapper.Convert(di.FullName, $"{outfile}.dds", uncookext);
                        }
                        catch (Exception e)
                        {
                            // silent
                        }
                    }

                    #endregion
                }
                else if (extract)
                {
                    var buffer     = buffers[j];
                    var bufferpath = $"{outfile}.{j}.buffer";
                    Directory.CreateDirectory(outfile.Directory.FullName);
                    File.WriteAllBytes(bufferpath, buffer);
                }
            }


            return(success ? 1 : 0);
        }
Exemplo n.º 4
0
        private int UncookSingleInner(MemoryMappedFile mmf, ulong hash, DirectoryInfo outDir, EUncookExtension uncookext = EUncookExtension.tga)
        {
            var uncooksuccess = false;

            var(file, buffers) = GetFileData(hash, mmf);

            if (!Files.ContainsKey(hash))
            {
                return(-1);
            }
            string name = Files[hash].NameStr;

            // checks
            var outfile = new FileInfo(Path.Combine(outDir.FullName,
                                                    $"{name}"));

            if (outfile.Directory == null)
            {
                return(-1);
            }
            if (buffers.Count > 1)
            {
                return(-1); //TODO: can that happen?
            }
            var cr2w = new CR2WFile();

            using var ms = new MemoryStream(file);
            using var br = new BinaryReader(ms);
            cr2w.ReadImportsAndBuffers(br);
            if (cr2w.StringDictionary[1] != "CBitmapTexture")
            {
                return(-1);
            }

            br.BaseStream.Seek(0, SeekOrigin.Begin);
            var result = cr2w.Read(br);

            if (result != EFileReadErrorCodes.NoError)
            {
                return(-1);
            }
            if (!(cr2w.Chunks.FirstOrDefault()?.data is CBitmapTexture xbm) ||
                !(cr2w.Chunks[1]?.data is rendRenderTextureBlobPC blob))
            {
                return(-1);
            }

            // write buffers
            foreach (var b in buffers)
            {
                #region textures
                // create dds header
                var newpath = Path.ChangeExtension(outfile.FullName, "dds");
                try
                {
                    var width      = blob.Header.SizeInfo.Width.val;
                    var height     = blob.Header.SizeInfo.Height.val;
                    var mips       = blob.Header.TextureInfo.MipCount.val;
                    var slicecount = blob.Header.TextureInfo.SliceCount.val;
                    var alignment  = blob.Header.TextureInfo.DataAlignment.val;

                    Enums.ETextureRawFormat rawfmt = Enums.ETextureRawFormat.TRF_Invalid;
                    if (xbm.Setup.RawFormat?.WrappedEnum != null)
                    {
                        rawfmt = xbm.Setup.RawFormat.WrappedEnum;
                    }
                    else
                    {
                    }

                    Enums.ETextureCompression compression = Enums.ETextureCompression.TCM_None;
                    if (xbm.Setup.Compression?.WrappedEnum != null)
                    {
                        compression = xbm.Setup.Compression.WrappedEnum;
                    }
                    else
                    {
                    }

                    var texformat = CommonFunctions.GetDXGIFormatFromXBM(compression, rawfmt);

                    Directory.CreateDirectory(outfile.Directory.FullName);
                    using (var stream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write))
                    {
                        DDSUtils.GenerateAndWriteHeader(stream,
                                                        new DDSMetadata(width, height, mips, texformat, alignment, false, slicecount, true));
                        var buffer = b;
                        stream.Write(buffer);
                    }

                    // success
                    uncooksuccess = true;
                }
                catch
                {
                    uncooksuccess = false;
                    continue;
                }

                // convert to texture
                if (uncookext != EUncookExtension.dds)
                {
                    try
                    {
                        var di = new FileInfo(outfile.FullName).Directory;
                        TexconvWrapper.Convert(di.FullName, $"{newpath}", uncookext);
                    }
                    catch (Exception e)
                    {
                        // silent
                    }
                }

                #endregion
            }

            return(uncooksuccess ? 1 : 0);
        }
Exemplo n.º 5
0
        public static bool Uncook(CR2WFile cr2w, List <byte[]> buffers, FileInfo outfile, EUncookExtension uncookext)
        {
            //We need 2 buffers one for atlas one for tile data
            if (buffers.Count < 2)
            {
                return(false);
            }

            if (!(cr2w.Chunks.FirstOrDefault()?.data is Multilayer_Mask mlmask) ||
                !(cr2w.Chunks[1]?.data is rendRenderMultilayerMaskBlobPC blob))
            {
                return(false);
            }

            string filename = Path.GetFileNameWithoutExtension(outfile.FullName);
            string path     = outfile.Directory.FullName;

            uint atlasWidth  = blob.Header.AtlasWidth.val;
            uint atlasHeight = blob.Header.AtlasHeight.val;

            uint maskWidth  = blob.Header.MaskWidth.val;
            uint maskHeight = blob.Header.MaskHeight.val;

            uint maskWidthLow  = blob.Header.MaskWidthLow.val;
            uint maskHeightLow = blob.Header.MaskHeightLow.val;

            uint maskTileSize = blob.Header.MaskTileSize.val;

            uint maskCount = blob.Header.NumLayers.val;

            byte[] atlas = buffers[0];
            uint[] tiles;

            //Read tilesdata buffer into appropriate variable type
            var b = buffers[1];

            tiles = new uint[b.Length / 4];
            for (int i = 0, j = 0; i < b.Length; i += 4, j++)
            {
                tiles[j] = BitConverter.ToUInt32(b, i);
            }
            byte[] atlasRaw = new byte[atlasWidth * atlasHeight];

            //Decode compressed data into single channel uncompressed
            //Mlmask always BC4?
            if (!BlockCompression.DecodeBC(atlas, ref atlasRaw, atlasWidth, atlasHeight, BlockCompression.BlockCompressionType.BC4))
            {
                return(false);
            }

            //{
            //    var mFilename = filename + $"__.dds";
            //    var newpath = Path.Combine(path, mFilename);
            //    using (var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write))
            //    {
            //        DDSUtils.GenerateAndWriteHeader(ddsStream, new DDSMetadata(atlasWidth, atlasHeight, 0, EFormat.R8_UNORM, 8, false, 0, false));
            //
            //        ddsStream.Write(atlasRaw);
            //    }
            //}


            byte[] maskData = new byte[maskWidth * maskHeight];


            Directory.CreateDirectory(path);
            for (int i = 0; i < maskCount; i++)
            {
                var mFilename = filename + $"_{i}.dds";
                var newpath   = Path.Combine(path, mFilename);

                //Clear instead of allocate new is faster?
                //Mandatory cause decode does not always write to every pixel
                Array.Clear(maskData, 0, maskData.Length);
                Decode(ref maskData, maskWidth, maskHeight, maskWidthLow, maskHeightLow, atlasRaw, atlasWidth, atlasHeight, tiles, maskTileSize, i);

                using (var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write))
                {
                    DDSUtils.GenerateAndWriteHeader(ddsStream, new DDSMetadata(maskWidth, maskHeight, 0, EFormat.R8_UNORM, 8, false, 0, false));

                    ddsStream.Write(maskData);
                }

                //convert texture if neccessary
                if (uncookext != EUncookExtension.dds && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var di = new FileInfo(outfile.FullName).Directory;
                    TexconvWrapper.Convert(di.FullName, $"{newpath}", uncookext);
                }
            }
            return(true);
        }
Exemplo n.º 6
0
        public static bool Uncook(Stream cr2wStream, CR2WFile cr2w, EUncookExtension uncookext)
        {
            //We need 2 buffers one for atlas one for tile data

            if (!(cr2w.Chunks.FirstOrDefault()?.data is Multilayer_Mask mlmask) ||
                !(cr2w.Chunks[1]?.data is rendRenderMultilayerMaskBlobPC blob))
            {
                return(false);
            }

            var outfile = new FileInfo(cr2w.FileName);

            if (outfile.Directory == null)
            {
                return(false);
            }

            Directory.CreateDirectory(outfile.Directory.FullName);
            string filename = Path.GetFileNameWithoutExtension(outfile.FullName);
            string path     = outfile.Directory.FullName;

            uint atlasWidth  = blob.Header.AtlasWidth.Value;
            uint atlasHeight = blob.Header.AtlasHeight.Value;

            uint maskWidth  = blob.Header.MaskWidth.Value;
            uint maskHeight = blob.Header.MaskHeight.Value;

            uint maskWidthLow  = blob.Header.MaskWidthLow.Value;
            uint maskHeightLow = blob.Header.MaskHeightLow.Value;

            uint maskTileSize = blob.Header.MaskTileSize.Value;

            uint maskCount = blob.Header.NumLayers.Value;

            byte[] atlas;
            var    atlasRaw    = new byte[atlasWidth * atlasHeight];
            var    atlasBuffer = cr2w.Buffers[0];

            cr2wStream.Seek(atlasBuffer.Offset, SeekOrigin.Begin);
            using (var ms = new MemoryStream())
            {
                cr2wStream.DecompressAndCopySegment(ms, atlasBuffer.DiskSize, atlasBuffer.MemSize);
                atlas = ms.ToArray();
            }

            //Decode compressed data into single channel uncompressed
            //Mlmask always BC4?
            if (!BlockCompression.DecodeBC(atlas, ref atlasRaw, atlasWidth, atlasHeight, BlockCompression.BlockCompressionType.BC4))
            {
                return(false);
            }

            //{
            //    var mFilename = filename + $"__.dds";
            //    var newpath = Path.Combine(path, mFilename);
            //    using (var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write))
            //    {
            //        DDSUtils.GenerateAndWriteHeader(ddsStream, new DDSMetadata(atlasWidth, atlasHeight, 0, EFormat.R8_UNORM, 8, false, 0, false));
            //
            //        ddsStream.Write(atlasRaw);
            //    }
            //}

            //Read tilesdata buffer into appropriate variable type
            var tileBuffer = cr2w.Buffers[0];
            var tiles      = new uint[tileBuffer.MemSize / 4];

            cr2wStream.Seek(tileBuffer.Offset, SeekOrigin.Begin);
            using (var ms = new MemoryStream())
                using (var br = new BinaryReader(ms))
                {
                    cr2wStream.DecompressAndCopySegment(ms, tileBuffer.DiskSize, tileBuffer.MemSize);
                    ms.Seek(0, SeekOrigin.Begin);

                    for (var i = 0; i < tiles.Length; i++)
                    {
                        tiles[i] = br.ReadUInt32();
                    }
                }

            byte[] maskData = new byte[maskWidth * maskHeight];

            Directory.CreateDirectory(path);
            for (int i = 0; i < maskCount; i++)
            {
                var mFilename = filename + $"_{i}.dds";
                var newpath   = Path.Combine(path, mFilename);

                //Clear instead of allocate new is faster?
                //Mandatory cause decode does not always write to every pixel
                Array.Clear(maskData, 0, maskData.Length);
                Decode(ref maskData, maskWidth, maskHeight, maskWidthLow, maskHeightLow, atlasRaw, atlasWidth, atlasHeight, tiles, maskTileSize, i);

                using (var ddsStream = new FileStream($"{newpath}", FileMode.Create, FileAccess.Write))
                {
                    DDSUtils.GenerateAndWriteHeader(ddsStream, new DDSMetadata(maskWidth, maskHeight, 0, EFormat.R8_UNORM, 8, false, 0, false));

                    ddsStream.Write(maskData);
                }

                //convert texture if neccessary
                if (uncookext != EUncookExtension.dds && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var di = new FileInfo(outfile.FullName).Directory;
                    TexconvWrapper.Convert(di.FullName, $"{newpath}", uncookext);
                }
            }
            return(true);
        }