public static void DecompressData(byte[] inData, out byte[] outData) { using (MemoryStream outMemoryStream = new MemoryStream()) using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream)) using (Stream inMemoryStream = new MemoryStream(inData)) { CopyStream(inMemoryStream, outZStream); outZStream.finish(); outData = outMemoryStream.ToArray(); } }
public static void CompressData(byte[] inData, out byte[] outData) { using (MemoryStream outMemoryStream = new MemoryStream()) using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_DEFAULT_COMPRESSION)) using (Stream inMemoryStream = new MemoryStream(inData)) { CopyStream(inMemoryStream, outZStream); outZStream.finish(); outData = outMemoryStream.ToArray(); } }
public static byte[] Compress(byte[] inputBytes) { using (MemoryStream stream = new MemoryStream()) { using (ZOutputStream stream2 = new ZOutputStream(stream, 0)) { stream2.Write(inputBytes, 0, inputBytes.Length); stream2.finish(); return stream.ToArray(); } } }
private bool ReplaceContentHelperFunc(byte[] content, FileStream datFileStream) { // Store the old offsets just in case we need to perform a restore. // This actually isn't necessary currently, since the raf directory file is saved after packing. UInt32 oldOffset = FileOffset; UInt32 oldSize = FileSize; try { // Navigate to the end of it datFileStream.Seek(0, SeekOrigin.End); UInt32 offset = (UInt32)datFileStream.Length; FileInfo fInfo = new FileInfo(m_fileName); // .fsb, .fev, and .gfx files aren't compressed byte[] finalContent; if (fInfo.Extension == ".fsb" || fInfo.Extension == ".fev" || fInfo.Extension == ".gfx") { finalContent = content; } else { // Start of compression MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } // Write the data to the end of the .dat file datFileStream.Write(finalContent, 0, finalContent.Length); // Update entry values to represent the new changes FileOffset = offset; FileSize = (UInt32)finalContent.Length; return(true); } catch (Exception) { FileOffset = oldOffset; FileSize = oldSize; return(false); } }
private bool ReplaceContentHelperFunc(byte[] content, FileStream datFileStream) { // Store the old offsets just in case we need to perform a restore. // This actually isn't necessary currently, since the raf directory file is saved after packing. var oldOffset = FileOffset; var oldSize = FileSize; try { // Navigate to the end of it datFileStream.Seek(0, SeekOrigin.End); var offset = (UInt32) datFileStream.Length; var fInfo = new FileInfo(FileName); // .fsb, .fev, and .gfx files aren't compressed byte[] finalContent; if (fInfo.Extension == ".fsb" || fInfo.Extension == ".fev" || fInfo.Extension == ".gfx") { finalContent = content; } else { // Start of compression var mStream = new MemoryStream(); var oStream = new ZOutputStream(mStream, zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } // Write the data to the end of the .dat file datFileStream.Write(finalContent, 0, finalContent.Length); // Update entry values to represent the new changes FileOffset = offset; FileSize = (UInt32) finalContent.Length; return true; } catch (Exception) { FileOffset = oldOffset; FileSize = oldSize; return false; } }
public static OSD ZDecompressOSD(byte[] data) { OSD ret; using (MemoryStream input = new MemoryStream(data)) using (MemoryStream output = new MemoryStream()) using (ZOutputStream zout = new ZOutputStream(output)) { CopyStream(input, zout); zout.finish(); output.Seek(0, SeekOrigin.Begin); ret = OSDParser.DeserializeLLSDBinary(output); } return ret; }
public static byte[] ZCompressOSD(OSD data) { byte[] ret = null; using (MemoryStream outMemoryStream = new MemoryStream()) using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_BEST_COMPRESSION)) using (Stream inMemoryStream = new MemoryStream(OSDParser.SerializeLLSDBinary(data, false))) { CopyStream(inMemoryStream, outZStream); outZStream.finish(); ret = outMemoryStream.ToArray(); } return ret; }
//Inserts a file into the raf archive... public bool InsertFile(string fileName, byte[] content, TextWriter ostream) { if (ostream == null) ostream = new StreamWriter(Stream.Null); ostream.WriteLine(" Insert: " + fileName); ostream.WriteLine(" To: " + GetID()); RAFFileListEntry fileentry = this.GetDirectoryFile().GetFileList().GetFileEntry(fileName); if (fileentry == null) { //Define a new entry ostream.WriteLine("# Create new entry in RAF Archive, using experimental hash calculations"); ostream.WriteLine(" Get DAT File Stream"); FileStream datFileStream = GetDataFileContentStream(); //navigate to the end of it, add the file. datFileStream.Seek(0, SeekOrigin.End); UInt32 offset = (UInt32)datFileStream.Length; byte[] finalContent; if (nocompress.Contains(fileName)) { finalContent = content; } else { ostream.WriteLine(" Begin compression of content"); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } ostream.WriteLine(" Begin DAT Write"); datFileStream.Write(finalContent, 0, finalContent.Length); ostream.WriteLine(" Add file entry to in memory directory..."); UInt32 strTableIndex = directoryFile.GetStringTable().Add(fileName); directoryFile.CreateFileEntry(fileName, offset, (UInt32)finalContent.Length, strTableIndex); //directoryFile.Save(); //datFileStream.Close(); ostream.WriteLine(" Done."); return true; } else { //store the old offsets just in case we need to perform a restore. //This actually isn't necessary currently, since the raf directory file is saved //After packing. UInt32 oldOffset = (UInt32)fileentry.FileOffset; UInt32 oldSize = (UInt32)fileentry.FileSize; ostream.WriteLine("Old Offset: " + oldOffset + "; Old Size: " + oldSize); ostream.WriteLine("Begin modify game files... This may take a while"); try { ostream.WriteLine(" Get File Stream"); FileStream datFileStream = GetDataFileContentStream(); //navigate to the end of it, add the file. datFileStream.Seek(0, SeekOrigin.End); UInt32 offset = (UInt32)datFileStream.Length; byte[] finalContent; if (nocompress.Contains(fileName)) { finalContent = content; } else { ostream.WriteLine(" Begin compression of content"); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } ostream.WriteLine(" Begin DAT Write"); datFileStream.Write(finalContent, 0, finalContent.Length); ostream.WriteLine(" Begin FileEntry Write"); fileentry.FileOffset = offset; fileentry.FileSize = (UInt32)finalContent.Length; //directoryFile.Save(); //datFileStream.Close(); ostream.WriteLine(" Done."); return true; } catch (Exception e) { ostream.WriteLine("!! An error occurred in inserting a file."); ostream.WriteLine("!! Note that the content of the raf archive has been added to"); ostream.WriteLine("!! But the directory file that points the game to the data in the content file"); ostream.WriteLine("!! Has not been modified. In other words, if the game read the RAF archive now"); ostream.WriteLine("!! It wouldn't see a difference."); ostream.WriteLine("!! However, the RAF archive is a bit bigger than before."); ostream.WriteLine(e.ToString()); fileentry.FileOffset = oldOffset; fileentry.FileSize = oldSize; //directoryFile.GetContent(); return false; } } }
public bool PackRAF(string sourceDirectory, string targetDirectory) { //RAFHashManager.Init(); //Inits if it needs to load the hashes dict... //archivedPaths = RAFHashManager.GetKeys(); uncompressedFiles = new List<string>(); uncompressedFiles.AddRange(File.ReadAllLines(Environment.CurrentDirectory + "\\nocompress.txt")); sourceDirectory = sourceDirectory.Replace("/", "\\"); String[] files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories); ostream.WriteLine("Begin packing RAF"); ostream.WriteLine("Count content bytes + file name bytes"); UInt32 totalNameBytes = 0; List<UInt32> stringTableContentOffsets = new List<UInt32>(); List<String> archivedPaths = new List<string>(); //Misnomer - name of the files once archived foreach (String filePath in files) { string archivePath = filePath.Replace(sourceDirectory, "").Replace("\\", "/"); stringTableContentOffsets.Add((UInt32)totalNameBytes); totalNameBytes += (UInt32)(archivePath.Length + 1); archivedPaths.Add(archivePath);//raf uses / in storage name. } foreach (String archivePath in archivedPaths) { stringTableContentOffsets.Add((UInt32)totalNameBytes); totalNameBytes += (UInt32)(archivePath.Length + 1); //archivedPaths.Add(archivePath);//raf uses / in storage name. } //Calculate total bytes of header file: // ulong magic = 0x18BE0EF0 6*4 // ulong version = 1 // toc: // ulong mgrIndex = 0? // ulong fileListOffset // ulong tableListOffset // ...filler... // @fileListOffset: // header: // ulong countFiles 4 // ulong hashName 4*4*n // ulong offsetInDataFile // ulong size(Compressed/noncompressed) // ulong name string @ string table // ....filler.... // @tableListOffset // header: 4*2 // ulong sizeOfData ( including header ) // ulong stringsContained // ulong offsetOfDataAfterTableListOffset 4*2*n // ulong stringLength (including null terminating char) //TODO: Check if string table contains strings other than filenames //List<byte> datBytes = new List<byte>(); UInt32 totalDatBytes = 0; List<UInt32> datFileOffsets = new List<UInt32>(); List<UInt32> fileSizes = new List<UInt32>(); //We start by packing the files into the .dat... We just archive all files and remember their offsets for later PrepareDirectory(targetDirectory); FileStream datFileStream = File.Create(targetDirectory + "\\output.raf.dat"); for(int i = 0; i < archivedPaths.Count; i++) { //datFileOffsets.Add((UInt32)datBytes.Count); //LoL_Audio.fev and LoL_Audio.fsb aren't compressed. We write them raw. if (uncompressedFiles.Contains(archivedPaths[i].ToLower())) { //Write raw ostream.WriteLine("No Compress: " + archivedPaths[i]); fileSizes.Add((UInt32)new FileInfo(sourceDirectory + archivedPaths[i]).Length); datFileOffsets.Add((UInt32)totalDatBytes); //datBytes.AddRange(File.ReadAllBytes(sourceDirectory + archivedPaths[i])); byte[] content = File.ReadAllBytes(sourceDirectory + archivedPaths[i]); datFileStream.Write(content, 0, content.Length); totalDatBytes += (UInt32)content.Length; } else { ostream.WriteLine("Compress: " + archivedPaths[i]); //FileStream fStream = new FileStream(sourceDirectory + archivedPaths[i], FileMode.Open); //fStream.Seek(0, SeekOrigin.Begin); //ostreamWriteLine("FStream Length: " + fStream.Length); byte[] fileContent = File.ReadAllBytes(sourceDirectory + archivedPaths[i]); ostream.WriteLine("Original Size:" + fileContent.Length); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(fileContent, 0, fileContent.Length); oStream.finish(); byte[] compressedContent = mStream.ToArray(); datFileOffsets.Add((UInt32)totalDatBytes); datFileStream.Write(compressedContent, 0, compressedContent.Length); //datBytes.AddRange(compressedContent);//contentBuffer.SubArray(0, length)); //count += (UInt32)length; totalDatBytes += (UInt32)compressedContent.Length; ostream.WriteLine("Done, {0} bytes".F(compressedContent.Length)); fileSizes.Add((UInt32)compressedContent.Length); } } UInt32 finalLength = (UInt32)(2*4 + 3*4 + 4 + 4*4*archivedPaths.Count + 4*2 + 4*2*archivedPaths.Count + totalNameBytes); byte[] buffer = new byte[finalLength]; //0x18BE0EF0.. note that the settings to 0 aren't necessary, but they're // for readability //Magic StoreUInt32InBuffer((UInt32)0x18BE0EF0, (UInt32)0, ref buffer); //Version StoreUInt32InBuffer((UInt32)0x00000001, (UInt32)4, ref buffer); //mgrIndex = 0 StoreUInt32InBuffer((UInt32)0x00000000, (UInt32)8, ref buffer); //fileListOffset StoreUInt32InBuffer((UInt32) 20, (UInt32)12, ref buffer); //stringTableOffset StoreUInt32InBuffer((UInt32)(20+4+16*archivedPaths.Count), (UInt32)16, ref buffer); //Start file list UInt32 offset = 0x14; //20, header of file list //Store # entries in list StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); offset += 4; //Store entries for (int i = 0; i < archivedPaths.Count; i++) { ostream.WriteLine("Store Entry: " + archivedPaths[i]); //Hash of string name? Get it from previous RAF files. StoreUInt32InBuffer(GetStringHash(archivedPaths[i]) , offset, ref buffer); // Offset to the start of the archived file in the data file ostream.WriteLine(" Dat Offset: " + datFileOffsets[i].ToString("x") + "; i="+i); StoreUInt32InBuffer(datFileOffsets[i] , offset+4, ref buffer); // Size of this archived file StoreUInt32InBuffer(fileSizes[i] , offset+8, ref buffer); // Index of the name of the archvied file in the string table StoreUInt32InBuffer((UInt32)i , offset+12, ref buffer); offset += 16; } //Create String Tables UInt32 stringTableOffset = offset = (UInt32)(20 + 4 + 16 * archivedPaths.Count); //This should be equivalent to offset= offset at the moment... //Header: Uint32 size of all data including header // UINT32 Number of strings in the table StoreUInt32InBuffer((UInt32)totalNameBytes, offset, ref buffer); offset += 4; StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); offset += 4; //Write entries: UINT32 Offset from start of table, UINT32 Size of String + NUL //Also write the actual string values for (int i = 0; i < archivedPaths.Count; i++) { ostream.WriteLine("Store String: " + archivedPaths[i]); //Write the offset for the string after the table's offset // offset after table = header + entry count * 8 + [strings offset] * 8 UInt32 offsetAfterTable = (UInt32)(8 + archivedPaths.Count * 8 + stringTableContentOffsets[i]); StoreUInt32InBuffer(offsetAfterTable, offset, ref buffer); offset += 4; //Length byte[] stringBytes = Encoding.ASCII.GetBytes(archivedPaths[i]); StoreUInt32InBuffer((UInt32)archivedPaths[i].Length + 1, offset, ref buffer); offset += 4; ostream.WriteLine(" STO:" + stringTableOffset.ToString("x")); ostream.WriteLine(" finalIndex:" + (stringTableOffset + 8 + archivedPaths.Count * 8 + stringTableContentOffsets[i]).ToString("x")); //Copy the string contents to where offsetAfterTable points to for (int j = 0; j < stringBytes.Length; j++) { buffer[stringTableOffset+ 8 + archivedPaths.Count * 8 + stringTableContentOffsets[i] + j] = stringBytes[j]; } //StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); //offset += 4; } //We are done. Write the files ostream.WriteLine("All files processed. Writing to disk."); //buffer ostream.WriteLine("Prepare."); PrepareDirectory(targetDirectory); ostream.WriteLine("Write RAF Directory File."); File.WriteAllBytes(targetDirectory + "\\output.raf", buffer); ostream.WriteLine("Finalize"); datFileStream.Flush(); datFileStream.Close(); //ostreamWriteLine("Write RAF Content File. Length:"+datBytes.Count); //File.WriteAllBytes(targetDirectory + "\\output.raf.dat", datBytes.ToArray()); return true; }
/// <summary> /// 解压流 /// </summary> /// <param name="SourceStream">需要被解缩的流数据</param> /// <returns></returns> public static Stream DecompressStream(Stream SourceStream) { try { MemoryStream stmOutput = new MemoryStream(); ZOutputStream outZStream = new ZOutputStream(stmOutput); CopyStream(SourceStream, outZStream); outZStream.finish(); return stmOutput; } catch { return null; } }
/// <summary> /// 压缩流 /// </summary> /// <param name="SourceStream">需要被压缩的流数据</param> /// <returns></returns> public static Stream CompressStream(Stream SourceStream) { try { MemoryStream stmOutTemp = new MemoryStream(); ZOutputStream outZStream = new ZOutputStream(stmOutTemp, zlibConst.Z_DEFAULT_COMPRESSION); CopyStream(SourceStream, outZStream); outZStream.finish(); return stmOutTemp; } catch { return null; } }
public bool PackRAF(string sourceDirectory, string targetDirectory) { //RAFHashManager.Init(); //Inits if it needs to load the hashes dict... //archivedPaths = RAFHashManager.GetKeys(); uncompressedFiles = new List <string>(); uncompressedFiles.AddRange(File.ReadAllLines(Environment.CurrentDirectory + "\\nocompress.txt")); sourceDirectory = sourceDirectory.Replace("/", "\\"); String[] files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories); ostream.WriteLine("Begin packing RAF"); ostream.WriteLine("Count content bytes + file name bytes"); UInt32 totalNameBytes = 0; List <UInt32> stringTableContentOffsets = new List <UInt32>(); List <String> archivedPaths = new List <string>(); //Misnomer - name of the files once archived foreach (String filePath in files) { string archivePath = filePath.Replace(sourceDirectory, "").Replace("\\", "/"); stringTableContentOffsets.Add((UInt32)totalNameBytes); totalNameBytes += (UInt32)(archivePath.Length + 1); archivedPaths.Add(archivePath);//raf uses / in storage name. } foreach (String archivePath in archivedPaths) { stringTableContentOffsets.Add((UInt32)totalNameBytes); totalNameBytes += (UInt32)(archivePath.Length + 1); //archivedPaths.Add(archivePath);//raf uses / in storage name. } //Calculate total bytes of header file: // ulong magic = 0x18BE0EF0 6*4 // ulong version = 1 // toc: // ulong mgrIndex = 0? // ulong fileListOffset // ulong tableListOffset // ...filler... // @fileListOffset: // header: // ulong countFiles 4 // ulong hashName 4*4*n // ulong offsetInDataFile // ulong size(Compressed/noncompressed) // ulong name string @ string table // ....filler.... // @tableListOffset // header: 4*2 // ulong sizeOfData ( including header ) // ulong stringsContained // ulong offsetOfDataAfterTableListOffset 4*2*n // ulong stringLength (including null terminating char) //TODO: Check if string table contains strings other than filenames //List<byte> datBytes = new List<byte>(); UInt32 totalDatBytes = 0; List <UInt32> datFileOffsets = new List <UInt32>(); List <UInt32> fileSizes = new List <UInt32>(); //We start by packing the files into the .dat... We just archive all files and remember their offsets for later PrepareDirectory(targetDirectory); FileStream datFileStream = File.Create(targetDirectory + "\\output.raf.dat"); for (int i = 0; i < archivedPaths.Count; i++) { //datFileOffsets.Add((UInt32)datBytes.Count); //LoL_Audio.fev and LoL_Audio.fsb aren't compressed. We write them raw. if (uncompressedFiles.Contains(archivedPaths[i].ToLower())) { //Write raw ostream.WriteLine("No Compress: " + archivedPaths[i]); fileSizes.Add((UInt32) new FileInfo(sourceDirectory + archivedPaths[i]).Length); datFileOffsets.Add((UInt32)totalDatBytes); //datBytes.AddRange(File.ReadAllBytes(sourceDirectory + archivedPaths[i])); byte[] content = File.ReadAllBytes(sourceDirectory + archivedPaths[i]); datFileStream.Write(content, 0, content.Length); totalDatBytes += (UInt32)content.Length; } else { ostream.WriteLine("Compress: " + archivedPaths[i]); //FileStream fStream = new FileStream(sourceDirectory + archivedPaths[i], FileMode.Open); //fStream.Seek(0, SeekOrigin.Begin); //ostreamWriteLine("FStream Length: " + fStream.Length); byte[] fileContent = File.ReadAllBytes(sourceDirectory + archivedPaths[i]); ostream.WriteLine("Original Size:" + fileContent.Length); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(fileContent, 0, fileContent.Length); oStream.finish(); byte[] compressedContent = mStream.ToArray(); datFileOffsets.Add((UInt32)totalDatBytes); datFileStream.Write(compressedContent, 0, compressedContent.Length); //datBytes.AddRange(compressedContent);//contentBuffer.SubArray(0, length)); //count += (UInt32)length; totalDatBytes += (UInt32)compressedContent.Length; ostream.WriteLine("Done, {0} bytes".F(compressedContent.Length)); fileSizes.Add((UInt32)compressedContent.Length); } } UInt32 finalLength = (UInt32)(2 * 4 + 3 * 4 + 4 + 4 * 4 * archivedPaths.Count + 4 * 2 + 4 * 2 * archivedPaths.Count + totalNameBytes); byte[] buffer = new byte[finalLength]; //0x18BE0EF0.. note that the settings to 0 aren't necessary, but they're // for readability //Magic StoreUInt32InBuffer((UInt32)0x18BE0EF0, (UInt32)0, ref buffer); //Version StoreUInt32InBuffer((UInt32)0x00000001, (UInt32)4, ref buffer); //mgrIndex = 0 StoreUInt32InBuffer((UInt32)0x00000000, (UInt32)8, ref buffer); //fileListOffset StoreUInt32InBuffer((UInt32)20, (UInt32)12, ref buffer); //stringTableOffset StoreUInt32InBuffer((UInt32)(20 + 4 + 16 * archivedPaths.Count), (UInt32)16, ref buffer); //Start file list UInt32 offset = 0x14; //20, header of file list //Store # entries in list StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); offset += 4; //Store entries for (int i = 0; i < archivedPaths.Count; i++) { ostream.WriteLine("Store Entry: " + archivedPaths[i]); //Hash of string name? Get it from previous RAF files. StoreUInt32InBuffer(GetStringHash(archivedPaths[i]), offset, ref buffer); // Offset to the start of the archived file in the data file ostream.WriteLine(" Dat Offset: " + datFileOffsets[i].ToString("x") + "; i=" + i); StoreUInt32InBuffer(datFileOffsets[i], offset + 4, ref buffer); // Size of this archived file StoreUInt32InBuffer(fileSizes[i], offset + 8, ref buffer); // Index of the name of the archvied file in the string table StoreUInt32InBuffer((UInt32)i, offset + 12, ref buffer); offset += 16; } //Create String Tables UInt32 stringTableOffset = offset = (UInt32)(20 + 4 + 16 * archivedPaths.Count); //This should be equivalent to offset= offset at the moment... //Header: Uint32 size of all data including header // UINT32 Number of strings in the table StoreUInt32InBuffer((UInt32)totalNameBytes, offset, ref buffer); offset += 4; StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); offset += 4; //Write entries: UINT32 Offset from start of table, UINT32 Size of String + NUL //Also write the actual string values for (int i = 0; i < archivedPaths.Count; i++) { ostream.WriteLine("Store String: " + archivedPaths[i]); //Write the offset for the string after the table's offset // offset after table = header + entry count * 8 + [strings offset] * 8 UInt32 offsetAfterTable = (UInt32)(8 + archivedPaths.Count * 8 + stringTableContentOffsets[i]); StoreUInt32InBuffer(offsetAfterTable, offset, ref buffer); offset += 4; //Length byte[] stringBytes = Encoding.ASCII.GetBytes(archivedPaths[i]); StoreUInt32InBuffer((UInt32)archivedPaths[i].Length + 1, offset, ref buffer); offset += 4; ostream.WriteLine(" STO:" + stringTableOffset.ToString("x")); ostream.WriteLine(" finalIndex:" + (stringTableOffset + 8 + archivedPaths.Count * 8 + stringTableContentOffsets[i]).ToString("x")); //Copy the string contents to where offsetAfterTable points to for (int j = 0; j < stringBytes.Length; j++) { buffer[stringTableOffset + 8 + archivedPaths.Count * 8 + stringTableContentOffsets[i] + j] = stringBytes[j]; } //StoreUInt32InBuffer((UInt32)archivedPaths.Count, offset, ref buffer); //offset += 4; } //We are done. Write the files ostream.WriteLine("All files processed. Writing to disk."); //buffer ostream.WriteLine("Prepare."); PrepareDirectory(targetDirectory); ostream.WriteLine("Write RAF Directory File."); File.WriteAllBytes(targetDirectory + "\\output.raf", buffer); ostream.WriteLine("Finalize"); datFileStream.Flush(); datFileStream.Close(); //ostreamWriteLine("Write RAF Content File. Length:"+datBytes.Count); //File.WriteAllBytes(targetDirectory + "\\output.raf.dat", datBytes.ToArray()); return(true); }
// serialize all components into a stream, then compress and write the result to disk. Operation derived from // the original SiD C source public void Save(String filename) { MemoryStream ms = new MemoryStream(mComponents.Count * 1064); using (ms) { using (BinaryWriter b = new BinaryWriter(ms)) { b.Write(ByteUtils.SwapUInt32((UInt32)mComponents.Count)); foreach (SiDComponent exC in mComponents) { byte[] compName = ASCIIEncoding.UTF8.GetBytes(exC.Name); byte[] typeName = ASCIIEncoding.UTF8.GetBytes(exC.ResourceTypeName); UID uid = exC.getUID(); b.Write(typeName); b.Write('\0'); b.Write(uid.UIDBytes); b.Write(compName); b.Write('\0'); byte[] dataBuf = exC.SaveToByteStream(); b.Write(ByteUtils.SwapUInt32((UInt32)dataBuf.Length)); b.Write(dataBuf); } Int32 uncompressedSize = (Int32)ms.Length; MemoryStream packMem = new MemoryStream(uncompressedSize); using (ZOutputStream zStream = new ZOutputStream(packMem, 9)) { zStream.Write(ms.ToArray(), 0, (Int32)ms.Length); zStream.finish(); using (FileStream fs = File.Open(filename, FileMode.Create)) { using (BinaryWriter fb = new BinaryWriter(fs)) { fb.Write(ByteUtils.SwapUInt32((UInt32)uncompressedSize)); fb.Write(packMem.ToArray(), 0, (Int32)packMem.Length); } fs.Close(); } } } } }
/// <summary> /// Old Decompress method not using .NET compressor /// </summary> /// <param name="Data"></param> /// <returns></returns> public byte[] DecompressOld(byte[] Data) { byte[] decompressedPixelData = new byte[UncompressedLength]; // ZLIB if (version > BgfFile.VERSION9) { // init streams MemoryStream destStream = new MemoryStream(decompressedPixelData, true); ZOutputStream destZ = new ZOutputStream(destStream); // decompress destZ.Write(Data, 0, Data.Length); destZ.Flush(); destZ.finish(); // cleanup destStream.Dispose(); destZ.Dispose(); } // CRUSH else { #if WINCLR && X86 // decompress Crush32.Decompress(Data, 0, decompressedPixelData, 0, (int)UncompressedLength, CompressedLength); #else throw new Exception(ERRORCRUSHPLATFORM); #endif } // set decompressed array to pixeldata return decompressedPixelData; }
/// <summary> /// Returns a compressed byte[] of PixelData argument /// </summary> /// <param name="Data"></param> /// <returns></returns> public byte[] Compress(byte[] Data) { // allocate a buffer with uncompressed length to write compressed stream to byte[] tempBuffer = new byte[UncompressedLength]; int compressedLength; // ZLIB if (version > BgfFile.VERSION9) { // init streams MemoryStream destStream = new MemoryStream(tempBuffer, true); ZOutputStream destZ = new ZOutputStream(destStream, zlibConst.Z_BEST_COMPRESSION); // compress destZ.Write(Data, 0, Data.Length); destZ.Flush(); destZ.finish(); // update compressed length compressedLength = (int)destZ.TotalOut; // cleanup destStream.Dispose(); destZ.Dispose(); } // CRUSH else { #if WINCLR && X86 // compress to tempBuffer compressedLength = Crush32.Compress(Data, 0, tempBuffer, 0, (int)UncompressedLength); #else throw new Exception(ERRORCRUSHPLATFORM); #endif } // copy all bytes we actually used from tempBuffer to new PixelData byte[] newPixelData = new byte[compressedLength]; Array.Copy(tempBuffer, 0, newPixelData, 0, compressedLength); return newPixelData; }
//Inserts a file into the raf archive... public bool InsertFile(string fileName, byte[] content, TextWriter ostream) { if (ostream == null) { ostream = new StreamWriter(Stream.Null); } ostream.WriteLine(" Insert: " + fileName); ostream.WriteLine(" To: " + GetID()); RAFFileListEntry fileentry = this.GetDirectoryFile().GetFileList().GetFileEntry(fileName); if (fileentry == null) { //Define a new entry ostream.WriteLine("# Create new entry in RAF Archive, using experimental hash calculations"); ostream.WriteLine(" Get DAT File Stream"); FileStream datFileStream = GetDataFileContentStream(); //navigate to the end of it, add the file. datFileStream.Seek(0, SeekOrigin.End); UInt32 offset = (UInt32)datFileStream.Length; byte[] finalContent; if (nocompress.Contains(fileName)) { finalContent = content; } else { ostream.WriteLine(" Begin compression of content"); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } ostream.WriteLine(" Begin DAT Write"); datFileStream.Write(finalContent, 0, finalContent.Length); ostream.WriteLine(" Add file entry to in memory directory..."); UInt32 strTableIndex = directoryFile.GetStringTable().Add(fileName); directoryFile.CreateFileEntry(fileName, offset, (UInt32)finalContent.Length, strTableIndex); //directoryFile.Save(); //datFileStream.Close(); ostream.WriteLine(" Done."); return(true); } else { //store the old offsets just in case we need to perform a restore. //This actually isn't necessary currently, since the raf directory file is saved //After packing. UInt32 oldOffset = (UInt32)fileentry.FileOffset; UInt32 oldSize = (UInt32)fileentry.FileSize; ostream.WriteLine("Old Offset: " + oldOffset + "; Old Size: " + oldSize); ostream.WriteLine("Begin modify game files... This may take a while"); try { ostream.WriteLine(" Get File Stream"); FileStream datFileStream = GetDataFileContentStream(); //navigate to the end of it, add the file. datFileStream.Seek(0, SeekOrigin.End); UInt32 offset = (UInt32)datFileStream.Length; byte[] finalContent; if (nocompress.Contains(fileName)) { finalContent = content; } else { ostream.WriteLine(" Begin compression of content"); MemoryStream mStream = new MemoryStream(); zlib.ZOutputStream oStream = new zlib.ZOutputStream(mStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION); //using default compression level oStream.Write(content, 0, content.Length); oStream.finish(); finalContent = mStream.ToArray(); } ostream.WriteLine(" Begin DAT Write"); datFileStream.Write(finalContent, 0, finalContent.Length); ostream.WriteLine(" Begin FileEntry Write"); fileentry.FileOffset = offset; fileentry.FileSize = (UInt32)finalContent.Length; //directoryFile.Save(); //datFileStream.Close(); ostream.WriteLine(" Done."); return(true); } catch (Exception e) { ostream.WriteLine("!! An error occurred in inserting a file."); ostream.WriteLine("!! Note that the content of the raf archive has been added to"); ostream.WriteLine("!! But the directory file that points the game to the data in the content file"); ostream.WriteLine("!! Has not been modified. In other words, if the game read the RAF archive now"); ostream.WriteLine("!! It wouldn't see a difference."); ostream.WriteLine("!! However, the RAF archive is a bit bigger than before."); ostream.WriteLine(e.ToString()); fileentry.FileOffset = oldOffset; fileentry.FileSize = oldSize; //directoryFile.GetContent(); return(false); } } }