Example #1
0
            public uint DecodeToBuffer(float f, byte[] buffer, uint offset)
            {
                if (offset >= buffer.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(offset));
                }
                var value = (short)(f * 0x7fffffff);

                if (!BitConverter.IsLittleEndian)
                {
                    value = DereToreHelper.SwapEndian(value);
                }
                var bytes        = BitConverter.GetBytes(value);
                var bytesWritten = 0u;

                for (var i = 0; i < 4; ++i)
                {
                    if (offset + i >= buffer.Length)
                    {
                        break;
                    }
                    buffer[offset + i] = bytes[i];
                    ++bytesWritten;
                }
                return(bytesWritten);
            }
Example #2
0
        private void FixReaderEndianess()
        {
            var reader   = AssetReader;
            var platform = Platform;

            if (platform > 255 || platform < 0)
            {
                Platform      = DereToreHelper.SwapEndian(platform);
                reader.Endian = Endian.LittleEndian;
            }
        }
        private static void FixDataBlock(byte[] blockData)
        {
            var length = blockData.Length;
            var sum    = HcaHelper.Checksum(blockData, 0, length - 2);

            if (BitConverter.IsLittleEndian)
            {
                sum = DereToreHelper.SwapEndian(sum);
            }
            var sumBytes = BitConverter.GetBytes(sum);

            blockData[length - 2] = sumBytes[0];
            blockData[length - 1] = sumBytes[1];
        }
        private void UpdateHeader()
        {
            var dataOffset   = HcaInfo.DataOffset;
            var buffer       = new byte[dataOffset];
            var sourceStream = SourceStream;
            var outputStream = _outputStream;

            sourceStream.Seek(0, SeekOrigin.Begin);
            sourceStream.Read(buffer, 0, buffer.Length);
            sourceStream.Seek(0, SeekOrigin.Begin);

            uint v;

            // HCA
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.HCA))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(HcaHeader)));
            }
            // FMT
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.FMT))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(FormatHeader)));
            }
            // COMP / DEC
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.COMP))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(CompressHeader)));
            }
            else if (MagicValues.IsMagicMatch(v, MagicValues.DEC))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(DecodeHeader)));
            }
            // VBR
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.VBR))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(VbrHeader)));
            }
            // ATH
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.ATH))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(AthHeader)));
            }
            // LOOP
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.LOOP))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(LoopHeader)));
            }
            // CIPH
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.CIPH))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                var cipherOffset = (int)(sourceStream.Position + 4);
                var u            = (ushort)_ccTo.CipherType;
                if (BitConverter.IsLittleEndian)
                {
                    u = DereToreHelper.SwapEndian(u);
                }
                var cipherTypeBytes = BitConverter.GetBytes(u);
                buffer[cipherOffset]     = cipherTypeBytes[0];
                buffer[cipherOffset + 1] = cipherTypeBytes[1];
            }
            // RVA
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.RVA))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(RvaHeader)));
            }
            // COMM
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.COMM))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(Marshal.SizeOf(typeof(CommentHeader)));
                byte tmpByte;
                do
                {
                    tmpByte = (byte)sourceStream.ReadByte();
                } while (tmpByte != 0);
            }
            // PAD (undocumented)
            v = sourceStream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.PAD))
            {
                ProcessHeaderSignature(sourceStream, buffer);
                sourceStream.Skip(4);
            }

            FixDataBlock(buffer);
            outputStream.Write(buffer, 0, buffer.Length);
        }
Example #5
0
        internal void ParseHeaders()
        {
            var  stream = SourceStream;
            uint v;
            var  hcaInfo = new HcaInfo();

            // HCA
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.HCA))
            {
                HcaHeader header;
                stream.Read(out header);
                hcaInfo.Version    = DereToreHelper.SwapEndian(header.Version);
                hcaInfo.DataOffset = DereToreHelper.SwapEndian(header.DataOffset);
            }
            else
            {
                throw new HcaException("Missing HCA signature.", ActionResult.MagicNotMatch);
            }
            // FMT
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.FMT))
            {
                FormatHeader header;
                stream.Read(out header);
                hcaInfo.ChannelCount = header.Channels;
                hcaInfo.SamplingRate = DereToreHelper.SwapEndian(header.SamplingRate << 8);
                hcaInfo.BlockCount   = DereToreHelper.SwapEndian(header.Blocks);
                hcaInfo.FmtR01       = DereToreHelper.SwapEndian(header.R01);
                hcaInfo.FmtR02       = DereToreHelper.SwapEndian(header.R02);
                if (hcaInfo.ChannelCount < 1 || hcaInfo.ChannelCount > 16)
                {
                    throw new HcaException($"Channel count should be between 1 and 16, read {hcaInfo.ChannelCount}.", ActionResult.InvalidFieldValue);
                }
                if (hcaInfo.SamplingRate < 1 || hcaInfo.SamplingRate > 0x7fffff)
                {
                    throw new HcaException($"Sampling rate should be between 1 and {0x7fffffff}, read {hcaInfo.SamplingRate}.", ActionResult.InvalidFieldValue);
                }
            }
            else
            {
                throw new HcaException("Missing FMT signature.", ActionResult.MagicNotMatch);
            }
            // COMP / DEC
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.COMP))
            {
                CompressHeader header;
                stream.Read(out header);
                hcaInfo.BlockSize = DereToreHelper.SwapEndian(header.BlockSize);
                hcaInfo.CompR01   = header.R01;
                hcaInfo.CompR02   = header.R02;
                hcaInfo.CompR03   = header.R03;
                hcaInfo.CompR04   = header.R04;
                hcaInfo.CompR05   = header.R05;
                hcaInfo.CompR06   = header.R06;
                hcaInfo.CompR07   = header.R07;
                hcaInfo.CompR08   = header.R08;
                if ((hcaInfo.BlockSize < 8 || hcaInfo.BlockSize > 0xffff) && hcaInfo.BlockSize != 0)
                {
                    throw new HcaException($"Block size should be between 8 and {0xffff}, read {hcaInfo.BlockSize}.", ActionResult.InvalidFieldValue);
                }
                if (!(hcaInfo.CompR01 <= hcaInfo.CompR02 && hcaInfo.CompR02 <= 0x1f))
                {
                    throw new HcaException($"CompR01 should be less than or equal to CompR02, and CompR02 should be less than or equal to {0x1f}, read {hcaInfo.CompR01} and {hcaInfo.CompR02}.", ActionResult.InvalidFieldValue);
                }
            }
            else if (MagicValues.IsMagicMatch(v, MagicValues.DEC))
            {
                DecodeHeader header;
                stream.Read(out header);
                hcaInfo.CompR01 = header.R01;
                hcaInfo.CompR02 = header.R02;
                hcaInfo.CompR03 = header.R04;
                hcaInfo.CompR04 = header.R03;
                hcaInfo.CompR05 = (ushort)(header.Count1 + 1);
                hcaInfo.CompR06 = (ushort)((header.EnableCount2 ? header.Count2 : header.Count1) + 1);
                hcaInfo.CompR07 = (ushort)(hcaInfo.CompR05 - hcaInfo.CompR06);
                hcaInfo.CompR08 = 0;
                if ((hcaInfo.BlockSize < 8 || hcaInfo.BlockSize > 0xffff) && hcaInfo.BlockSize != 0)
                {
                    throw new HcaException($"Block size should be between 8 and {0xffff}, read {hcaInfo.BlockSize}.", ActionResult.InvalidFieldValue);
                }
                if (!(hcaInfo.CompR01 <= hcaInfo.CompR02 && hcaInfo.CompR02 <= 0x1f))
                {
                    throw new HcaException($"CompR01 should be less than or equal to CompR02, and CompR02 should be less than or equal to {0x1f}, read {hcaInfo.CompR01} and {hcaInfo.CompR02}.", ActionResult.InvalidFieldValue);
                }
                if (hcaInfo.CompR03 == 0)
                {
                    hcaInfo.CompR03 = 1;
                }
            }
            else
            {
                throw new HcaException("Missing COMP/DEC signature.", ActionResult.MagicNotMatch);
            }
            // VBR
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.VBR))
            {
                VbrHeader header;
                stream.Read(out header);
                hcaInfo.VbrR01 = DereToreHelper.SwapEndian(header.R01);
                hcaInfo.VbrR02 = DereToreHelper.SwapEndian(header.R02);
                if (!(hcaInfo.BlockSize == 0 && hcaInfo.VbrR01 < 0x01ff))
                {
                    throw new HcaException($"VbrR01 should be less than {0x01ff} in VBR HCA.", ActionResult.InvalidFieldValue);
                }
            }
            else
            {
                hcaInfo.VbrR01 = hcaInfo.VbrR02 = 0;
            }
            // ATH
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.ATH))
            {
                AthHeader header;
                stream.Read(out header);
                hcaInfo.AthType = header.Type;
            }
            else
            {
                hcaInfo.AthType = (ushort)(hcaInfo.Version < 0x0200 ? 1 : 0);
            }
            // LOOP
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.LOOP))
            {
                LoopHeader header;
                stream.Read(out header);
                hcaInfo.LoopStart = DereToreHelper.SwapEndian(header.LoopStart);
                hcaInfo.LoopEnd   = DereToreHelper.SwapEndian(header.LoopEnd);
                hcaInfo.LoopR01   = DereToreHelper.SwapEndian(header.R01);
                hcaInfo.LoopR02   = DereToreHelper.SwapEndian(header.R02);
                hcaInfo.LoopFlag  = true;
            }
            else
            {
                hcaInfo.LoopStart = 0;
                hcaInfo.LoopEnd   = 0;
                hcaInfo.LoopR01   = 0;
                hcaInfo.LoopR02   = 0x400;
                hcaInfo.LoopFlag  = false;
            }
            // CIPH
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.CIPH))
            {
                CipherHeader header;
                stream.Read(out header);
                hcaInfo.CipherType = (CipherType)DereToreHelper.SwapEndian(header.Type);
            }
            else
            {
                hcaInfo.CipherType = CipherType.NoChipher;
            }
            // RVA
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.RVA))
            {
                RvaHeader header;
                stream.Read(out header);
                hcaInfo.RvaVolume = DereToreHelper.SwapEndian(header.Volume);
            }
            else
            {
                hcaInfo.RvaVolume = 1;
            }
            // COMM
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.COMM))
            {
                CommentHeader header;
                stream.Read(out header);
                hcaInfo.CommentLength = header.Length;
                var  tmpCommentCharList = new List <byte>();
                byte tmpByte;
                do
                {
                    tmpByte = (byte)stream.ReadByte();
                    tmpCommentCharList.Add(tmpByte);
                } while (tmpByte != 0);
                hcaInfo.Comment = tmpCommentCharList.ToArray();
            }
            else
            {
                hcaInfo.CommentLength = 0;
                hcaInfo.Comment       = null;
            }
            // PAD (undocumented)
            v = stream.PeekUInt32LE();
            if (MagicValues.IsMagicMatch(v, MagicValues.PAD))
            {
                stream.Skip(4); // Length of 'pad '
            }

            if (hcaInfo.CompR03 == 0)
            {
                hcaInfo.CompR03 = 1;
            }

            if (hcaInfo.CompR01 != 1 || hcaInfo.CompR02 != 0xf)
            {
                throw new HcaException($"Expected CompR01=1, CompR02=15, read {hcaInfo.CompR01}, {hcaInfo.CompR02}.", ActionResult.InvalidFieldValue);
            }
            hcaInfo.CompR09 = HcaHelper.Ceil2((uint)(hcaInfo.CompR05 - (hcaInfo.CompR06 + hcaInfo.CompR07)), hcaInfo.CompR08);
            HcaInfo         = hcaInfo;
        }