Пример #1
0
        public void Write(BinaryWriter bw)
        {
            bw.Write(LxrsFooter.s_magic);
            bw.Write(LxrsFooter.s_version);

            using var ms     = new MemoryStream();
            using var tempBw = new BinaryWriter(ms);
            foreach (var s in FileInfos)
            {
                tempBw.WriteCR2WString(s);
            }

            var inbuffer = ms.ToByteArray();

            IEnumerable <byte> outBuffer = new List <byte>();
            var r = OodleHelper.Compress(
                inbuffer,
                inbuffer.Length,
                ref outBuffer,
                OodleNative.OodleLZ_Compressor.Kraken,
                OodleNative.OodleLZ_Compression.Normal,
                false);

            bw.Write(inbuffer.Length);      //size
            bw.Write(outBuffer.Count());    //zsize
            bw.Write(FileInfos.Count());    //count
            bw.Write(outBuffer.ToArray());
        }
Пример #2
0
        /// <summary>
        /// Kraken-compresses a buffer and writes it to a stream.
        /// </summary>
        /// <param name="bw"></param>
        /// <param name="inbuffer"></param>
        /// <returns></returns>
        public static (uint, uint) CompressAndWrite(this BinaryWriter bw, byte[] inbuffer)
        {
            var size = (uint)inbuffer.Length;

            if (size < 255)
            {
                var crc = Crc32Algorithm.Compute(inbuffer);
                bw.Write(inbuffer);

                return(size, crc);
            }
            else
            {
                IEnumerable <byte> outBuffer = new List <byte>();
                var r = OodleHelper.Compress(
                    inbuffer,
                    (int)size,
                    ref outBuffer,
                    OodleNative.OodleLZ_Compressor.Kraken,
                    OodleNative.OodleLZ_Compression.Normal);

                var b = outBuffer.ToArray();

                var crc = Crc32Algorithm.Compute(b);
                bw.Write(b);

                return((uint)r, crc);
            }
        }
Пример #3
0
        private static int OodleTask(string path, string outpath, bool decompress, bool compress)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(0);
            }

            if (string.IsNullOrEmpty(outpath))
            {
                outpath = Path.ChangeExtension(path, ".kark");
            }

            if (decompress)
            {
                var file = File.ReadAllBytes(path);
                using var ms = new MemoryStream(file);
                using var br = new BinaryReader(ms);

                var oodleCompression = br.ReadBytes(4);
                if (!(oodleCompression.SequenceEqual(new byte[] { 0x4b, 0x41, 0x52, 0x4b })))
                {
                    throw new NotImplementedException();
                }

                var size = br.ReadUInt32();

                var buffer = br.ReadBytes(file.Length - 8);

                byte[] unpacked     = new byte[size];
                long   unpackedSize = OodleHelper.Decompress(buffer, unpacked);

                using var msout = new MemoryStream();
                using var bw    = new BinaryWriter(msout);
                bw.Write(unpacked);

                File.WriteAllBytes($"{outpath}", msout.ToArray());
            }

            if (compress)
            {
                var inbuffer = File.ReadAllBytes(path);
                IEnumerable <byte> outBuffer = new List <byte>();

                var r = OodleHelper.Compress(
                    inbuffer,
                    inbuffer.Length,
                    ref outBuffer,
                    OodleNative.OodleLZ_Compressor.Kraken,
                    OodleNative.OodleLZ_Compression.Normal,
                    true);

                File.WriteAllBytes(outpath, outBuffer.ToArray());
            }

            return(1);
        }
Пример #4
0
        public void Read(BinaryReader br)
        {
            var magic = br.ReadUInt32();

            if (magic != s_magic)
            {
                throw new InvalidParsingException("not a valid Archive");
            }

            var version = br.ReadUInt32();
            var size    = br.ReadInt32();
            var zsize   = br.ReadInt32();
            var count   = br.ReadInt32();

            var inbuffer = br.ReadBytes(zsize);

            if (size > zsize)
            {
                // buffer is compressed
                var outBuffer = new byte[size];
                var r         = OodleHelper.Decompress(inbuffer, outBuffer);
                using var ms     = new MemoryStream(outBuffer);
                using var tempbr = new BinaryReader(ms);
                for (var i = 0; i < count; i++)
                {
                    FileInfos.Add(tempbr.ReadCR2WString());
                }
            }
            else if (size < zsize)
            {
                // error
                // extract as .bin file
            }
            else
            {
                // no compression
                using var ms     = new MemoryStream(inbuffer);
                using var tempbr = new BinaryReader(ms);
                for (var i = 0; i < count; i++)
                {
                    FileInfos.Add(tempbr.ReadCR2WString());
                }
            }
        }
Пример #5
0
        public static int OodleTask(string path, string outpath, bool decompress)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(0);
            }

            if (string.IsNullOrEmpty(outpath))
            {
                outpath = path;
            }

            if (decompress)
            {
                var file = File.ReadAllBytes(path);
                using var ms = new MemoryStream(file);
                using var br = new BinaryReader(ms);

                var oodleCompression = br.ReadBytes(4);
                if (!(oodleCompression.SequenceEqual(new byte[] { 0x4b, 0x41, 0x52, 0x4b })))
                {
                    throw new NotImplementedException();
                }
                var size = br.ReadUInt32();

                var buffer = br.ReadBytes(file.Length - 8);

                byte[] unpacked     = new byte[size];
                long   unpackedSize = OodleHelper.Decompress(buffer, unpacked);

                using var msout = new MemoryStream();
                using var bw    = new BinaryWriter(msout);
                bw.Write(unpacked);

                File.WriteAllBytes($"{outpath}.kark", msout.ToArray());
            }


            return(1);
        }
Пример #6
0
        public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true)
        {
            var cr2w = _wolvenkitFileService.TryReadRED4File(animStream);

            if (!cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().Any())
            {
                return(false);
            }
            var blob = cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().First();

            List <MemoryStream> animDataBuffers = new List <MemoryStream>();

            foreach (var chk in blob.AnimationDataChunks)
            {
                UInt16 bufferIdx = chk.Buffer.Buffer.Value;
                var    b         = cr2w.Buffers[bufferIdx - 1];
                animStream.Seek(b.Offset, SeekOrigin.Begin);
                var ms = new MemoryStream();
                animStream.DecompressAndCopySegment(ms, b.DiskSize, b.MemSize);
                animDataBuffers.Add(ms);
            }

            var Rig  = new RawArmature();
            var hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath);

            foreach (var ar in archives)
            {
                if (ar.Files.ContainsKey(hash))
                {
                    var ms = new MemoryStream();
                    ModTools.ExtractSingleToStream(ar, hash, ms);
                    Rig = RIG.ProcessRig(_wolvenkitFileService.TryReadRED4File(ms));
                    break;
                }
            }

            if (Rig is null)
            {
                return(false);
            }

            if (Rig.BoneCount < 1)
            {
                return(false);
            }

            var model = ModelRoot.CreateModel();
            var skin  = model.CreateSkin();

            skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray());

            for (int i = 0; i < blob.Animations.Count; i++)
            {
                var setEntry    = (blob.Animations[i].GetReference().Data as animAnimSetEntry);
                var animAnimDes = (setEntry.Animation.GetReference().Data as animAnimation);
                if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal)
                {
                    continue;
                }
                switch (animAnimDes.AnimBuffer.GetReference().REDType)
                {
                case "animAnimationBufferSimd":
                {
                    var animBuff       = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferSimd);
                    var defferedBuffer = new MemoryStream();
                    if (animBuff.InplaceCompressedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.InplaceCompressedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                        var br = new BinaryReader(defferedBuffer);
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        if (br.ReadUInt32() == OodleHelper.KARK)
                        {
                            uint size   = br.ReadUInt32();
                            var  input  = br.ReadBytes((int)(br.BaseStream.Length - 8));
                            var  output = new Byte[size];
                            OodleHelper.Decompress(input, output);
                            defferedBuffer = new MemoryStream(output);
                        }
                    }
                    else
                    {
                        var bufferIdx = animBuff.DefferedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer, animAnimDes);
                }
                break;

                case "animAnimationBufferCompressed":
                {
                    var animBuff       = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferCompressed);
                    var defferedBuffer = new MemoryStream();
                    if (animBuff.InplaceCompressedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.InplaceCompressedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                        var br = new BinaryReader(defferedBuffer);
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        if (br.ReadUInt32() == OodleHelper.KARK)
                        {
                            uint size   = br.ReadUInt32();
                            var  input  = br.ReadBytes((int)(br.BaseStream.Length - 8));
                            var  output = new Byte[size];
                            OodleHelper.Decompress(input, output);
                            defferedBuffer = new MemoryStream(output);
                        }
                    }
                    else if (animBuff.DataAddress.IsSerialized)
                    {
                        var    dataAddr = animBuff.DataAddress;
                        Byte[] bytes    = new Byte[dataAddr.ZeInBytes.Value];
                        animDataBuffers[(int)dataAddr.UnkIndex.Value].Seek(dataAddr.FsetInBytes.Value, SeekOrigin.Begin);
                        animDataBuffers[(int)dataAddr.UnkIndex.Value].Read(bytes, 0, (int)dataAddr.ZeInBytes.Value);
                        defferedBuffer = new MemoryStream(bytes);
                    }
                    else if (animBuff.DefferedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.DefferedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer, animAnimDes);
                }
                break;
                }
            }
            if (isGLBinary)
            {
                model.SaveGLB(outfile.FullName);
            }
            else
            {
                model.SaveGLTF(outfile.FullName);
            }

            return(true);
        }