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); }
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); }
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; }