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