예제 #1
0
        private static void WriteAfs2ArchiveToStream(ReadOnlyCollection <byte[]> files, Stream stream, uint alignment)
        {
            var fileCount = (uint)files.Count;

            if (files.Count >= ushort.MaxValue)
            {
                throw new IndexOutOfRangeException($"File count {fileCount} exceeds maximum possible value (65535).");
            }
            if (files.Count != 1)
            {
                throw new NotSupportedException("Currently DereTore does not support more than one file.");
            }
            stream.WriteBytes(Afs2Archive.Afs2Signature);
            const uint version = 0x00020401;

            stream.WriteUInt32LE(version);
            stream.WriteUInt32LE(fileCount);
            stream.WriteUInt32LE(alignment);
            const uint offsetFieldSize = (version >> 8) & 0xff; // version[1], always 4? See Afs2Archive.Initialize().

            // Prepare the fields.
            var afs2HeaderSegmentSize = 0x10 +                        // General data
                                        2 * fileCount +               // Cue IDs
                                        offsetFieldSize * fileCount + // File offsets
                                        sizeof(uint);                 // Size of last file (U32)
            // Assuming the music file always has ID 0 in Waveform table and Cue table.
            var records = new List <Afs2FileRecord>();
            var currentFileRawOffset = afs2HeaderSegmentSize;

            for (ushort i = 0; i < fileCount; ++i)
            {
                var record = new Afs2FileRecord {
                    // TODO: Use the Cue table.
                    CueId             = i,
                    FileOffsetRaw     = currentFileRawOffset,
                    FileOffsetAligned = AcbHelper.RoundUpToAlignment(currentFileRawOffset, alignment)
                };
                records.Add(record);
                currentFileRawOffset = (uint)(record.FileOffsetAligned + files[i].Length);
            }

            var lastFileEndOffset = currentFileRawOffset;

            for (var i = 0; i < files.Count; ++i)
            {
                stream.WriteUInt16LE(records[i].CueId);
            }
            for (var i = 0; i < files.Count; ++i)
            {
                stream.WriteUInt32LE((uint)records[i].FileOffsetRaw);
            }
            // TODO: Dynamically judge it. See Afs2Archive.Initialize().
            stream.WriteUInt32LE(lastFileEndOffset);
            for (var i = 0; i < files.Count; ++i)
            {
                stream.SeekAndWriteBytes(files[i], records[i].FileOffsetAligned);
            }
        }
예제 #2
0
        // ReSharper disable once IdentifierTypo
        private static void AfsToWav(Afs2FileRecord afsRecord, Stream awbStream, DecodeParams decodeParams,
                                     string output)
        {
            using var fileData =
                      AcbHelper.ExtractToNewStream(awbStream, afsRecord.FileOffsetAligned, (int)afsRecord.FileLength);
            var isHcaStream = DereTore.Exchange.Audio.HCA.HcaReader.IsHcaStream(fileData);

            if (!isHcaStream)
            {
                return;
            }

            using var fs = File.OpenWrite(output);
            try
            {
                HcaToWav(fileData, fs, decodeParams);
            }
            catch (Exception)
            {
                Console.Error.WriteLine($"Failed to convert {output}:");
                throw;
            }
        }