Example #1
0
        public int Write(Stream input, int absDataOffset, int baseDataOffset)
        {
            using (var bw = new BinaryWriterX(input, true))
            {
                bw.BaseStream.Position = absDataOffset;
                FileData.CopyTo(bw.BaseStream);
                if (bw.BaseStream.Position % 4 > 0)
                {
                    bw.WriteAlignment(4);
                }
                else
                {
                    bw.WritePadding(4);
                }

                var relOffset = absDataOffset - baseDataOffset;
                Entry.tmp   = (ushort)((relOffset >> 2) & 0xffff);
                Entry.tmpZ  = (byte)(((relOffset >> 2) & 0xff0000) >> 16);
                Entry.tmp2  = (ushort)(FileSize & 0xffff);
                Entry.tmp2Z = (byte)((FileSize & 0xff0000) >> 16);

                return(((absDataOffset + FileSize) % 4 > 0) ? (int)(absDataOffset + FileSize + 0x3) & ~0x3 : (int)(absDataOffset + FileSize + 4));
            }
        }
Example #2
0
        public void Save(string filename)
        {
            using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename)))
            {
                var textOffset = header.offsetSecOffset + header.offsetCount * 0x4;

                //Write Text and update Offsets
                bw.BaseStream.Position = textOffset;
                var labelCount = 0;
                for (int i = 0; i < textOffsets.Count(); i++)
                {
                    if (textOffsets[i] != 0)
                    {
                        textOffsets[i] = (int)bw.BaseStream.Position;
                        bw.Write(Encoding.GetEncoding("UTF-16").GetBytes(Labels[labelCount++].Text));
                        bw.WritePadding(2);
                    }
                }
                bw.WriteAlignment(0x20);

                //Write textOffsets
                bw.BaseStream.Position = header.offsetSecOffset;
                foreach (var offset in textOffsets)
                {
                    bw.Write(offset);
                }

                //Write unk section
                bw.BaseStream.Position = 0x20;
                bw.Write(unkSec);

                //Header
                bw.BaseStream.Position = 0x0;
                bw.WriteStruct(header);
            }
        }
Example #3
0
        public static byte[] EncodeWAVtoMCA(string wavFile, int version, int loopStart, int loopEnd)
        {
            using (var br = new BinaryReaderX(File.OpenRead(wavFile)))
            {
                //Header
                var wavHeader = br.ReadStruct <WAVHeader>();

                //check info
                if (wavHeader.RIFFMagic != "RIFF" || wavHeader.RIFFType != "WAVE")
                {
                    throw new Exception("Unsupported WAV.");
                }
                if (wavHeader.channelCount > 2)
                {
                    throw new Exception("Only 1 and 2 channel are supported.");
                }
                if (wavHeader.formatTag != 1)
                {
                    throw new Exception("Only 16bit PCM supported.");
                }
                if (wavHeader.bitsPerSample != 16)
                {
                    throw new Exception("Only 16bit PCM supported.");
                }
                var numSamples = (((int)br.BaseStream.Length - 0x2c) * 8) / wavHeader.bitsPerSample;
                if (loopStart > numSamples)
                {
                    loopStart = numSamples;
                }
                if (loopEnd < loopStart)
                {
                    loopEnd = loopStart;
                }
                if (loopEnd > numSamples)
                {
                    loopEnd = numSamples;
                }

                //output Meta
                Console.WriteLine($"\nMeta:\n" +
                                  $"  Version: {version}\n" +
                                  $"\n" +
                                  $"  Channels: {wavHeader.channelCount}\n" +
                                  $"  SampleRate: {wavHeader.sampleRate}\n" +
                                  $"  Samples: {numSamples}\n" +
                                  $"\n" +
                                  $"  LoopStart: {loopStart}\n" +
                                  $"  LoopEnd: {loopEnd}");

                //loop to data portion
                while (br.ReadString(4) != "data")
                {
                    br.ReadBytes(br.ReadInt32());
                }

                //Encode NGCDSP
                var soundDataSize = br.ReadInt32();
                var soundData     = br.ReadBytes(soundDataSize);

                List <short[][]> coefs = new List <short[][]>();
                byte[]           encode;
                if (wavHeader.channelCount == 1)
                {
                    //Create Coefs
                    coefs.Add(GetCoefs(soundData, numSamples));

                    //Encode
                    encode = EncodeNGCDSP(soundData, numSamples, coefs[0]);
                }
                else
                {
                    //Split soundData into their channels
                    var channelData = new List <List <byte> >();
                    for (int i = 0; i < wavHeader.channelCount; i++)
                    {
                        channelData.Add(new List <byte>());
                    }
                    using (var soundBr = new BinaryReaderX(new MemoryStream(soundData)))
                    {
                        while (soundBr.BaseStream.Position < soundBr.BaseStream.Length)
                        {
                            for (int i = 0; i < wavHeader.channelCount; i++)
                            {
                                channelData[i].AddRange(soundBr.ReadBytes(2));
                            }
                        }
                    }

                    //Create coefs
                    for (int i = 0; i < wavHeader.channelCount; i++)
                    {
                        coefs.Add(GetCoefs(channelData[i].ToArray(), numSamples));
                    }

                    //Encode
                    List <List <byte> > tmpEnc = new List <List <byte> >();
                    for (int i = 0; i < wavHeader.channelCount; i++)
                    {
                        tmpEnc.Add(EncodeNGCDSP(channelData[i].ToArray(), numSamples, coefs[i]).ToList());
                    }

                    //Pad encoded data to interleaveBlockSize
                    for (int i = 0; i < wavHeader.channelCount; i++)
                    {
                        tmpEnc[i].AddRange(new byte[0x100 - tmpEnc[i].Count() % 0x100]);
                    }

                    //Merge encoded data into interleaving blocks
                    encode = new byte[tmpEnc[0].Count() * wavHeader.channelCount];
                    int blocksIn     = 0;
                    int blocksInData = tmpEnc[0].Count() / 0x100;
                    while (blocksIn < blocksInData)
                    {
                        for (int i = 0; i < wavHeader.channelCount; i++)
                        {
                            Array.Copy(tmpEnc[i].ToArray(), blocksIn * 0x100, encode, blocksIn * 0x100 * wavHeader.channelCount + i * 0x100, 0x100);
                        }
                        blocksIn++;
                    }
                }

                //Create MCA
                var mcaHeader = new Header
                {
                    version      = (short)version,
                    channelCount = wavHeader.channelCount,
                    numSamples   = numSamples,
                    sampleRate   = wavHeader.sampleRate,
                    loopStart    = loopStart,
                    loopEnd      = loopEnd,
                    headSize     = ((version < 5) ? 0x34 : 0x38) + 0x30 * wavHeader.channelCount,
                    dataSize     = encode.Length,
                    unk4         = 0,
                    unk5         = 0
                };
                var ms = new MemoryStream();
                using (var bw = new BinaryWriterX(ms, true))
                {
                    bw.WriteStruct(mcaHeader);
                    bw.WritePadding(8);
                    if (version >= 5)
                    {
                        bw.Write(0x38 + wavHeader.channelCount * 0x30);
                    }

                    for (int h = 0; h < wavHeader.channelCount; h++)
                    {
                        for (var i = 0; i < 8; i++)
                        {
                            for (var j = 0; j < 2; j++)
                            {
                                bw.Write(coefs[h][i][j]);
                            }
                        }
                        bw.WritePadding(0x10);
                    }

                    bw.Write(encode);
                }

                return(ms.ToArray());
            }
        }
Example #4
0
        public void Save(Stream output, IList <ImageInfo> imageInfos)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var entryOffset = HeaderSize;
            var dataOffset  = entryOffset + imageInfos.Count * EntrySize_;

            // Write image data
            var dataPosition = dataOffset;
            var p4Index      = 0;
            var p8Index      = 0;

            output.Position = dataOffset;
            for (var i = 0; i < imageInfos.Count; i++)
            {
                var entry     = _fileDesc.entries[i];
                var imageInfo = imageInfos[i];

                // Update entry
                entry.DataOffset   = dataPosition;
                entry.DataSize     = imageInfo.ImageData.Length;
                entry.Format       = imageInfo.ImageFormat;
                entry.Width        = imageInfo.ImageSize.Width;
                entry.Height       = imageInfo.ImageSize.Height;
                entry.PaletteIndex = -1;

                if ((uint)imageInfo.ImageFormat == 0x94000000 || (uint)imageInfo.ImageFormat == 0x95000000)
                {
                    entry.SubFormat = imageInfo.PaletteFormat;
                }

                if ((uint)imageInfo.ImageFormat == 0x94000000)
                {
                    entry.PaletteIndex = p4Index++;
                }
                if ((uint)imageInfo.ImageFormat == 0x95000000)
                {
                    entry.PaletteIndex = p8Index++;
                }

                // Write image data
                bw.Write(imageInfo.ImageData);

                dataPosition += imageInfo.ImageData.Length;
            }

            // Write palette data
            foreach (var imageInfo in imageInfos)
            {
                if ((uint)imageInfo.ImageFormat == 0x94000000)
                {
                    bw.Write(imageInfo.PaletteData);
                    bw.WritePadding(P4PaletteSize_ - imageInfo.PaletteData.Length);
                }
            }

            foreach (var imageInfo in imageInfos)
            {
                if ((uint)imageInfo.ImageFormat == 0x95000000)
                {
                    bw.Write(imageInfo.PaletteData);
                    bw.WritePadding(P8PaletteSize_ - imageInfo.PaletteData.Length);
                }
            }

            // Write file description
            _fileDesc.header.dataOffset = dataOffset;
            _fileDesc.header.dataSize   = (int)(output.Length - dataOffset);
            _fileDesc.header.texCount   = imageInfos.Count;
            _fileDesc.header.p4PalCount = p4Index;
            _fileDesc.header.p8PalCount = p8Index;

            output.Position = 0;
            bw.WriteType(_fileDesc);
        }
Example #5
0
        public void Save(Stream xfsa)
        {
            //Update FileInfo
            int offset = 0;

            foreach (var file in Files)
            {
                entries[file.dirEntry.fileEntryOffset + file.fileCountInDir].offset = offset >> 4;
                file.fileEntry.offset = offset >> 4;

                entries[file.dirEntry.fileEntryOffset + file.fileCountInDir].size = (int)file.FileSize;
                file.fileEntry.size = (int)file.FileSize;

                var newOffset = ((offset + file.FileSize) % 16 == 0) ? offset + file.FileSize + 16 : (offset + file.FileSize + 0xf) & ~0xf;
                offset = (int)newOffset;
            }

            using (var bw = new BinaryWriterX(xfsa))
            {
                //Table 0
                bw.BaseStream.Position  = 0x24;
                header.table0Offset     = (int)bw.BaseStream.Position;
                header.table0EntryCount = (short)table0.Count;
                bw.Write(CompressTable(table0, table0Comp));

                //Table 1
                bw.BaseStream.Position  = (bw.BaseStream.Position + 3) & ~3;
                header.table1Offset     = (int)bw.BaseStream.Position;
                header.table1EntryCount = (short)table1.Count;
                bw.Write(CompressTable(table1, table1Comp));

                //FileEntries
                bw.BaseStream.Position      = (bw.BaseStream.Position + 3) & ~3;
                header.fileEntryTableOffset = (int)bw.BaseStream.Position;
                header.fileEntryCount       = entries.Count;
                bw.Write(CompressTable(entries, entriesComp));

                //StringTable
                bw.BaseStream.Position = (bw.BaseStream.Position + 3) & ~3;
                header.nameTableOffset = (int)bw.BaseStream.Position;
                bw.Write(Level5.Compress(new MemoryStream(stringTable), stringComp));

                //FileData
                bw.BaseStream.Position = (bw.BaseStream.Position + 0xf) & ~0xf;
                header.dataOffset      = (int)bw.BaseStream.Position;
                foreach (var file in Files)
                {
                    bw.BaseStream.Position = header.dataOffset + (file.fileEntry.offset << 4);
                    file.FileData.CopyTo(bw.BaseStream);
                    if (bw.BaseStream.Position % 16 == 0)
                    {
                        bw.WritePadding(16);
                    }
                    else
                    {
                        bw.WriteAlignment(16);
                    }
                }

                //Header
                bw.BaseStream.Position = 0;
                bw.WriteStruct(header);
            }

            //Table 1

            /*var ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(table0);
             * ms.Position = 0;
             * var newTable1 = Level5.Compress(ms, (Level5.Method)table1Comp);
             *
             * //Table 2
             * ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(table1);
             * ms.Position = 0;
             * var newTable2 = Level5.Compress(ms, (Level5.Method)table2Comp);
             *
             * //Update Entries
             * Files = Files.OrderBy(f => f.entry.entry.comb1 & 0x01ffffff).ToList();
             * int offset = 0;
             * foreach (var file in Files) offset = file.UpdateEntry(offset);
             *
             * //Get compressed Entry section
             * Files = Files.OrderBy(f => f.entry.ID).ToList();
             * ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(Files.Select(f => f.entry.entry));
             * ms.Position = 0;
             * var newEntryTable = Level5.Compress(ms, (Level5.Method)entriesComp);
             *
             * //Update header
             * header.nameTableOffset = (uint)(0x24 + ((newTable1.Length + 3) & ~3) + ((newTable2.Length + 3) & ~3) + ((newEntryTable.Length + 3) & ~3));
             * header.dataOffset = (uint)(((header.nameTableOffset + nameC.Length) + 0xf) & ~0xf);
             *
             * using (BinaryWriterX bw = new BinaryWriterX(xfsa))
             * {
             *  //Header
             *  bw.WriteStruct(header);
             *
             *  //Table 1
             *  bw.Write(newTable1);
             *  bw.WriteAlignment(4);
             *
             *  //Table 2
             *  bw.Write(newTable2);
             *  bw.WriteAlignment(4);
             *
             *  //Entries
             *  bw.Write(newEntryTable);
             *  bw.WriteAlignment(4);
             *
             *  //Names
             *  bw.Write(nameC);
             *  bw.WriteAlignment();
             *
             *  //Files
             *  Files = Files.OrderBy(f => f.entry.entry.comb1 & 0x01ffffff).ToList();
             *  foreach (var file in Files)
             *  {
             *      file.FileData.CopyTo(bw.BaseStream);
             *      if (bw.BaseStream.Position % 0x10 != 0)
             *          bw.WriteAlignment();
             *      else
             *      {
             *          bw.Write(new byte[0x10]);
             *      }
             *  }
             *
             *
             *  //FileEntries Table
             *  //bw.Write((entries.Count * 0xc) << 3);
             *
             *  /*uint offset = 0;
             *  List<XFSAFileInfo> files = new List<XFSAFileInfo>();
             *  foreach (var entry in entries)
             *  {
             *      var file = Files.Find(c => c.entry.comb1 == entry.comb1);
             *      files.Add(file);
             *
             *      //catch file limits
             *      if (file.FileData.Length >= 0x100000)
             *      {
             *          throw new Exception("File " + file.FileName + " is too big to pack into this archive type!");
             *      }
             *      else if (offset + dataOffset >= 0x20000000)
             *      {
             *          throw new Exception("The archive can't be bigger than 0x10000000 Bytes.");
             *      }
             *
             *      //edit entry
             *      entry.comb1 = (entry.comb1 & 0xfe000000) | (offset >> 4);
             *      entry.comb2 = (entry.comb1 & 0xfff00000) | ((uint)file.FileData.Length);
             *
             *      //write entry
             *      bw.WriteStruct(entry);
             *
             *      //edit values
             *      offset = (uint)(((offset + file.FileData.Length) + 0xf) & ~0xf);
             *  }*/

            //Nametable
            //bw.Write(nameC);

            //Files
            //bw.BaseStream.Position = dataOffset;
            //foreach (var file in files)
            //{
            //    file.FileData.CopyTo(bw.BaseStream);
            //    bw.BaseStream.Position = (bw.BaseStream.Position + 0xf) & ~0xf;
            //}

            //Header
            //header.nameTableOffset = (uint)(0x24 + table1.Length + table2.Length + entries.Count * 0xc + 4);
            //header.dataOffset = (uint)dataOffset;
            //bw.BaseStream.Position = 0;
            //bw.WriteStruct(header);
            //}
        }
Example #6
0
        public void Save(string filename)
        {
            using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename)))
            {
                var textOffset = 0x40 + entries.Count() * 0x20 + sceEntries.Count() * 0x8;

                //Write texts and update textEntries
                bw.BaseStream.Position = textOffset;
                var count = 0;
                for (int i = 0; i < entries.Count(); i++)
                {
                    entries[i].nameOffset = (int)bw.BaseStream.Position;
                    entries[i].nameLength = Encoding.ASCII.GetByteCount(Labels[count].Name);
                    bw.Write(Encoding.ASCII.GetBytes(Labels[count].Name));
                    bw.WritePadding(2);
                    bw.WriteAlignment(2);

                    entries[i].stringOffset = (int)bw.BaseStream.Position;
                    entries[i].stringLength = Encoding.GetEncoding("UTF-16").GetByteCount(Labels[count].Text) / 2;
                    var modText = Labels[count++].Text.Replace("\r\n", "\x1b");
                    entries[i].stringLength += modText.Count(m => m == '\x1b');
                    bw.Write(Encoding.GetEncoding("UTF-16").GetBytes(modText));
                    bw.WritePadding(4 + modText.Count(m => m == '\x1b') * 4);
                }
                bw.WriteAlignment(4);

                //Write scenario Containers and update sceEntries
                count = 0;
                for (int i = 0; i < sceEntries.Count(); i++)
                {
                    if ((bw.BaseStream.Position & 0x4) == 0)
                    {
                        bw.WritePadding(4);
                    }
                    if (sceEntries[i].containerOffset != 0)
                    {
                        sceEntries[i].containerOffset = (int)bw.BaseStream.Position;
                        foreach (var sceTextEntry in scenarios[count++])
                        {
                            bw.Write(sceTextEntry);
                        }
                    }
                }

                //final nulls, they seem to have no reason to exist ;)
                bw.WritePadding(textOffset);

                //Write both tables
                bw.BaseStream.Position = 0x40;
                foreach (var entry in entries)
                {
                    bw.WriteStruct(entry);
                }
                foreach (var sceContainer in sceEntries)
                {
                    bw.WriteStruct(sceContainer);
                }

                //Header
                bw.BaseStream.Position = 0x0;
                bw.WriteStruct(header);
                bw.WriteStruct(entryHeader);
                bw.BaseStream.Position += 0x10;
                bw.WriteStruct(sceHeader);
                bw.Write(unk1);
            }
        }
Example #7
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                // Header
                bw.Write(Magic);
                bw.Write(Count);
                bw.Write(nIDOffset);
                bw.Write(Unk1);
                bw.Write(nIDStringOffset);
                bw.Write(pstrBgmNameOffset);
                bw.Write(pstrArtistNameOffset);
                bw.Write(pstrFileNameOffset);
                bw.Write(nOrderOffset);
                bw.Write(nMixOffset);
                bw.Write(pstrRcidOffset);
                bw.Write(Unk2);
                bw.Write(Unk3);
                bw.WritePadding(0x10, 0x77);

                // Constant Strings
                bw.BaseStream.Position = nIDStringOffset;
                bw.WriteASCII(nIDString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrBgmNameString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrArtistNameString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrFileNameString);
                bw.Write((byte)0);
                bw.WriteASCII(nOrderString);
                bw.Write((byte)0);
                bw.WriteASCII(nMixString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrRcidString);
                bw.Write((byte)0);

                // BgmName
                Data.pstrBgmNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(BgmName);
                bw.Write((byte)0);

                // ArtistName
                Data.pstrArtistNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(ArtistName);
                bw.Write((byte)0);

                // FileName
                Data.pstrFileNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(FileName);
                bw.Write((byte)0);

                // Rcid
                Data.pstrRcidOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(Rcid);
                bw.Write((byte)0);

                // Data
                bw.BaseStream.Position = nIDOffset;
                Data.nID -= 1;
                bw.WriteStruct(Data);
                bw.WritePadding(0x4, 0x77);
            }
        }