private byte[] BuildHashTable() { int tableSize = CalulateHashTableSize(m_pakList.Count); byte[] table = new byte[(tableSize * 8) + 4]; BinaryWriter bw = new BinaryWriter(new MemoryStream(table)); bw.Write(tableSize); int count = m_pakList.Count; for (int i = 0; i < count; i++) { BBA bba = (BBA)m_pakList[i]; int crc = GetCRC32(bba.FileName); int pointer = ((tableSize - 1) & crc); int pos = pointer * 8 + 4; while (BitConverter.ToInt64(table, pos) != 0) { pointer++; pos = pointer * 8 + 4; } bw.BaseStream.Position = (long)pos; bw.Write(crc); bw.Write((int)bba.BBAEntryPositionInTable - 0x114); } return(table); }
private void AddFileToTree(TreeNode rootNode, string path, BBA bba) { int i = path.IndexOf("\\"); if (i != -1) { string item = path.Remove(i); int idx = rootNode.Nodes.IndexOfKey(item); string nextItem = path.Substring(item.Length + 1); if (idx != -1) { AddFileToTree(rootNode.Nodes[idx], nextItem, bba); } else { TreeNode node = rootNode.Nodes.Add(item); node.Name = item; node.SelectedImageIndex = 0; node.ImageIndex = 1; AddFileToTree(node, nextItem, bba); } } else { TreeNode node = rootNode.Nodes.Add(path); int iconIndex = _iconListManager.AddFileIcon(path); node.ImageIndex = iconIndex; node.SelectedImageIndex = iconIndex; node.Name = path; string time = DateTime.FromFileTime(bba.Time).ToString(); string unk1 = string.Format("{0:X}", bba.Unknown1); string unk2 = string.Format("{0:X}", bba.Unknown2); string unk3 = string.Format("{0:X}", bba.Unknown3); string pcrc = string.Format("{0:X}", bba.PackedCRC32); string ucrc = string.Format("{0:X}", bba.UnpackedCRC32); string tip = "File name: " + bba.FileName + "\nOffset: " + bba.Offset.ToString() + "\nPacked size: " + bba.PackedSize.ToString() + "\nUnpacked size: " + bba.UnpackedSize.ToString() + "\nFlags: " + bba.Flags.ToString() + "\nPackedCRC32: " + pcrc + "\nUnpackedCRC32: " + ucrc + "\nisFile: " + bba.IsFile.ToString() + "\nunk1: " + unk1 + "\nunk2: " + unk2 + "\nunk3: " + unk3 + "\nFile time: " + time + "\nOffsetToNextFile:" + String.Format("{0:X}", bba.OffsetToNextFileName) + "\nSizeOfPathToRoot: " + String.Format("{0:X}", bba.SizeOfPathToRootDir); node.ToolTipText = tip; } }
private void FillTree(TreeNode root) { int count = m_pakList.Count; progressBar1.Maximum = count; progressBar1.Step = 1; progressBar1.Value = 0; for (int i = 0; i < count; i++) { BBA bba = ( BBA )m_pakList[i]; //if (bba.IsFile == -1) AddFileToTree(root, bba.FileName, bba); progressBar1.PerformStep(); } }
private byte[] BuildEntry(BBA bba) { MemoryStream entry = new MemoryStream(0x40); BinaryWriter bw = new BinaryWriter(entry); bw.Write(bba.Time); bw.Write(bba.UnpackedSize); bw.Write(bba.UnpackedCRC32); bw.Write(bba.Flags); bw.Write(bba.Unknown1); bw.Write(bba.Offset); bw.Write(bba.PackedSize); bw.Write(bba.PackedCRC32); bw.Write(bba.Unknown2); bw.Write(bba.Unknown3); bw.Write(bba.PathSize); bw.Write(bba.SizeOfPathToRootDir); bw.Write(bba.IsFile); bw.Write(bba.OffsetToNextFileName); byte[] buff = entry.GetBuffer(); return(buff); }
private void GetFilesInfo(DirectoryInfo d, ref int ptrToFirstElement) { BBA bba; DirectoryInfo[] dirs = d.GetDirectories("*"); int pathlen = folderBrowserDialog1.SelectedPath.Length; int count = dirs.Length; for (int i = 0; i < count; i++) { bba = new BBA(); bba.FileName = dirs[i].FullName.Substring(pathlen + 1); bba.PathSize = bba.FileName.Length; bba.SizeOfPathToRootDir = bba.PathSize - dirs[i].Name.Length; bba.Flags = (int)BBAFlags.Directory; ptrToFirstElement += 0x41; ptrToFirstElement += bba.PathSize; int len = ptrToFirstElement % 4; len = (len == 0) ? 0 : 4 - len; ptrToFirstElement += len; bba.IsFile = 0; int idx = m_pakList.Add(bba); GetFilesInfo(dirs[i], ref ptrToFirstElement); if (i == count - 1) { bba.OffsetToNextFileName = -1; } else { bba.OffsetToNextFileName = ptrToFirstElement; } m_pakList[idx] = bba; } FileInfo[] files; files = d.GetFiles("*"); count = files.Length; for (int i = 0; i < count; i++) { bba = new BBA(); bba.FileName = files[i].FullName.Substring(pathlen + 1); bba.IsFile = -1; bba.PathSize = bba.FileName.Length; bba.SizeOfPathToRootDir = bba.PathSize - files[i].Name.Length; bba.Time = files[i].CreationTime.ToFileTime(); bba.UnpackedSize = ( int )files[i].Length; bba.Unknown2 = 0x100000; if (i == count - 1) { bba.OffsetToNextFileName = -1; } m_pakList.Add(bba); ptrToFirstElement += 0x41; ptrToFirstElement += bba.PathSize; int len = ptrToFirstElement % 4; len = (len == 0) ? 0 : 4 - len; ptrToFirstElement += len; } }
private bool SaveFile(BBA bba, string outDir) { FileStream f = null; MemoryStream fStream = null; string FileName = bba.FileName; FileStream pakFile = m_fs; pakFile.Position = bba.Offset; int BytesToWrite = bba.UnpackedSize; int BytesToRead = (bba.PackedSize % 4); BytesToRead = (BytesToRead == 0) ? bba.PackedSize : (4 - BytesToRead) + bba.PackedSize; int BytesRead = 0; try { f = CreateFile(outDir, FileName); if (f == null) { return(false); } if (bba.UnpackedSize == 0) { f.Close(); return(true); } fStream = new MemoryStream(BytesToRead); if (fStream == null) { f.Close(); return(false); } byte[] buff = fStream.GetBuffer(); BBAFlags Flags = (BBAFlags)bba.Flags; bool IsFileWriten = false; bool Decrypted = false; bool Decompressed = false; BytesRead = pakFile.Read(buff, 0, BytesToRead); if (BytesRead == 0) { f.Close(); return(false); } if ((Flags & BBAFlags.EncryptedHeader) == BBAFlags.EncryptedHeader) { int count = bba.PackedSize / bba.Unknown2 + 1; byte[] b = new byte[0x10]; for (int i = 0; i < count; i++) { Array.Copy(buff, i * bba.Unknown2, b, 0, 0x10); using (MemoryStream s = new MemoryStream()) { s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); byte[] TmpKey = s.GetBuffer(); BBACrypt.DecryptFileHeader(b, b.Length, TmpKey, 0x10, false); } Array.Copy(b, 0, buff, i * bba.Unknown2, 0x10); } } if ((Flags & BBAFlags.EncryptedEntireContent) == BBAFlags.EncryptedEntireContent) { IsFileWriten = true; int count = BytesToRead / bba.Unknown2 + 1; byte[] b = new byte[0x8000]; for (int i = 0; i < count; i++) { int ToDecrypt = ((BytesToRead - (i * bba.Unknown2 + b.Length)) >= 0) ? b.Length : BytesToRead - i * bba.Unknown2; Array.Copy(buff, i * bba.Unknown2, b, 0, ToDecrypt); using (MemoryStream s = new MemoryStream()) { s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); byte[] TmpKey = s.GetBuffer(); bool bRes = BBACrypt.DecryptIndexTable(b, ToDecrypt, TmpKey, 0x10); if (!bRes) { this.listBox1.Items.Add("Failed to decrypt: " + bba.FileName); } int ToWrite = (ToDecrypt == 0x8000) ? 0x8000 : BytesToWrite - i * bba.Unknown2; f.Write(b, 0, ToWrite); } } } if ((Flags & BBAFlags.Gziped) == BBAFlags.Gziped && !Decompressed) { IsFileWriten = true; using (MemoryStream m = new MemoryStream(buff)) { using (GZipStream Decompress = new GZipStream(m, CompressionMode.Decompress)) { MemoryStream DecompressionStream = new MemoryStream(0x10000); byte[] DecompressionBuffer = DecompressionStream.GetBuffer(); int numRead; while ((numRead = Decompress.Read(DecompressionBuffer, 0, DecompressionBuffer.Length)) != 0) { f.Write(DecompressionBuffer, 0, numRead); BytesToWrite -= numRead; } DecompressionStream.Dispose(); DecompressionStream.Close(); Decompressed = true; } } } if (!IsFileWriten) { f.Write(buff, 0, bba.PackedSize); } // MemoryStream s = new MemoryStream(); // // s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); // s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); // s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); // s.Write(BitConverter.GetBytes(bba.PathSize), 0, 4); // // byte[] TmpKey = s.GetBuffer(); // buff = new byte[bba.UnpackedSize]; // pakFile.Read(buff, 0, buff.Length); // // bool bRes = BBACrypt.DecryptIndexTable(buff, buff.Length, TmpKey, 0x10); // // if (bRes == false) // { // this.listBox1.SelectedItem = listBox1.Items.Add("Failed to decrypt: " + bba.FileName ); // } // else // { // // } // } } catch (System.Exception ex) { if (FileName != null) { this.listBox1.Items.Add(FileName); } this.listBox1.Items.Add(ex.Message); } f.Position = 0; int crc32 = Compression.GetStreamCRC32(f); if (bba.UnpackedCRC32 != crc32) { listBox1.Items.Add("CRC mismatch: " + bba.FileName); } if (f != null) { f.Close(); } if (fStream != null) { fStream.Dispose(); fStream.Close(); } DateTime time = DateTime.FromFileTime(bba.Time); File.SetCreationTime(outDir + @"\" + FileName, time); File.SetLastWriteTime(outDir + @"\" + FileName, time); File.SetLastAccessTime(outDir + @"\" + FileName, time); return(true); }
private void ReadFAT(FileStream f) { //Prepare FAT reader. f.Position = m_header.IndexTableOffset; byte[] table = new byte[m_header.IndexTableSize]; f.Read(table, 0, table.Length); BBACrypt.DecryptIndexTable(table, table.Length, null, 0); //MemoryStream input = new MemoryStream( table ); m_IndexTable = new MemoryStream(table); //Compression.Decompress( input, 8, m_IndexTable, true ); //input.Dispose(); //input.Close(); //table = m_IndexTable.GetBuffer(); FileStream fs = File.OpenWrite(openFileDialog1.FileName + ".idx"); fs.Write(table, 0, table.Length); fs.Close(); m_tablehead.OffsetToBBAHeadInTable = BitConverter.ToInt32(table, 0); m_tablehead.IndexTableOffset = BitConverter.ToInt32(table, 4); m_tablehead.HashTableOffset = BitConverter.ToInt32(table, 8); m_IndexTable.Position = m_tablehead.IndexTableOffset + 4; BinaryReader reader = new BinaryReader(m_IndexTable, Encoding.Default); int count = BitConverter.ToInt32(table, m_tablehead.IndexTableOffset); long TableBegin = m_IndexTable.Position; for (int i = 0; i < count; i++) { BBA bba = new BBA(); bba.BBAEntryPositionInTable = m_IndexTable.Position; bba.Time = reader.ReadInt64(); bba.UnpackedSize = reader.ReadInt32(); bba.UnpackedCRC32 = reader.ReadInt32(); bba.Flags = reader.ReadInt32(); bba.Unknown1 = reader.ReadInt32(); bba.Offset = reader.ReadInt64(); bba.PackedSize = reader.ReadInt32(); bba.PackedCRC32 = reader.ReadInt32(); bba.Unknown2 = reader.ReadInt32(); bba.Unknown3 = reader.ReadInt32(); bba.PathSize = reader.ReadInt32(); bba.SizeOfPathToRootDir = reader.ReadInt32(); bba.IsFile = reader.ReadInt32(); bba.OffsetToNextFileName = reader.ReadInt32(); byte[] filename = reader.ReadBytes(bba.PathSize); bba.FileName = Encoding.Default.GetString(filename); //if( ( bba.Unknown1 + bba.Unknown2 + bba.Unknown3 ) != 0 ) //{ // listBox1.Items.Add("u1: " + bba.Unknown1.ToString() + "u2: " + bba.Unknown2.ToString() + "u3: " + bba.Unknown3.ToString()); //} if (bba.IsFile == -1) { m_pakList.Add(bba); } //else //{ // m_dirList.Add(bba); //} int pos = (int)m_IndexTable.Position + 1; int x = (pos % 4); pos = (x == 0) ? 0 : 4 - x; m_IndexTable.Position += pos + 1; //if (bba.OffsetToNextFileName == -1) // break; //m_IndexTable.Position = pos;//TableBegin + bba.OffsetToNextFileName; } listBox1.Items.Add("Files found: " + m_pakList.Count.ToString()); m_IndexTable.Position = 0; }
private void BuildBBA(object obj) { DisableControls(); string saveTo = saveFileDialog1.FileName; string openDir = folderBrowserDialog1.SelectedPath; try { m_fs = new FileStream(saveTo, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); m_fs.Position = 0; m_fs.Write(new byte[0x50], 0, 0x50); int idx = listBox1.Items.Add("Getting Files Info..."); ClearMembers(); int aproxsize = 0; GetFilesInfo(new DirectoryInfo(openDir), ref aproxsize); listBox1.Items[idx] += "OK"; int count = m_pakList.Count; int refresh = 0; int counter = 0; this.progressBar1.Maximum = count; this.progressBar1.Value = 0; this.progressBar1.Step = 1; idx = listBox1.Items.Add("writing data..."); for (int i = 0; i < count; i++) { BBA bba = ( BBA )m_pakList[i]; if (bba.IsFile == -1) { string file = openDir + "\\" + bba.FileName; FileStream f1 = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); f1.Position = 0; bba.UnpackedCRC32 = Compression.GetStreamCRC32(f1); f1.Position = 0; bba.Offset = m_fs.Position; bba.PackedSize = WriteFile(m_fs, f1, new FileInfo(file)); if (bba.PackedSize != bba.UnpackedSize) { bba.Flags = 1; } m_fs.Flush(); f1.Close(); m_pakList[i] = bba; } this.progressBar1.PerformStep(); if (refresh == 100) { this.progressBar1.Refresh(); this.listBox1.Refresh(); refresh = 0; } refresh++; counter++; } listBox1.Items[idx] += "OK"; m_header.IndexTableOffset = m_fs.Position; refresh = 0; counter = 0; this.progressBar1.Maximum = count; this.progressBar1.Value = 0; this.progressBar1.Step = 1; idx = listBox1.Items.Add("Generating Index Table and Encrypting Headers..."); m_IndexTable = new MemoryStream(); m_IndexTable.Write(new byte[0x110], 0, 0x110); m_IndexTable.Write(BitConverter.GetBytes(count), 0, 4); int OffsetToNextEntry = 0; for (int i = 0; i < count; i++) { BBA bba = ( BBA )m_pakList[i]; byte[] entry = BuildEntry(bba); if (bba.Flags == 1) { byte[] dataheader = new byte[0x10]; m_fs.Position = bba.Offset; m_fs.Read(dataheader, 0, dataheader.Length); BBACrypt.EncryptFileHeader(dataheader, dataheader.Length, entry, entry.Length); m_fs.Position = bba.Offset; m_fs.Write(dataheader, 0, dataheader.Length); m_fs.Position = bba.Offset; bba.PackedCRC32 = Compression.GetStreamCRC32(m_fs, bba.PackedSize); } else { bba.PackedSize = bba.UnpackedSize; bba.PackedCRC32 = bba.UnpackedCRC32; } OffsetToNextEntry += entry.Length; OffsetToNextEntry += bba.PathSize + 1; int pos = ( int )m_IndexTable.Position; pos += bba.PathSize + 0x40 + 1; int x = (pos % 4); pos = (x == 0) ? 0 : 4 - x; OffsetToNextEntry += pos; bba.BBAEntryPositionInTable = m_IndexTable.Position; if (bba.IsFile == -1) { if (bba.OffsetToNextFileName != -1) { bba.OffsetToNextFileName = OffsetToNextEntry; } } m_pakList[i] = bba; entry = BuildEntry(bba); m_IndexTable.Write(entry, 0, entry.Length); m_IndexTable.Write(Encoding.Default.GetBytes(bba.FileName), 0, bba.PathSize); m_IndexTable.Write(new byte[pos + 1], 0, pos + 1); this.progressBar1.PerformStep(); if (refresh == 100) { this.progressBar1.Refresh(); this.listBox1.Refresh(); refresh = 0; } refresh++; counter++; } int HashTablePosition = ( int )m_IndexTable.Position; byte[] hashtable = BuildHashTable(); m_IndexTable.Write(hashtable, 0, hashtable.Length); BinaryWriter bw = new BinaryWriter(m_IndexTable); m_IndexTable.Position = 0; bw.Write(( int )0x40); bw.Write(( int )0x110); bw.Write(HashTablePosition); m_IndexTable.Position = 0x40; bw.Write(c_bbaHead, 0, c_bbaHead.Length); m_IndexTable.Position = 0x60; bw.Write(s7_bba_header_magic); bw.Write(s7_bba_header_magic2); m_IndexTable.Position = 0x94; bw.Write(s7_bba_magic1); bw.Write(s7_bba_header_magic); m_IndexTable.Position = 0; int IndexTableAlignedSize = (int)m_IndexTable.Length; int len = (int)m_IndexTable.Length; len = (len % 4); len = (len == 0) ? 0 : 4 - len; if (len != 0) { IndexTableAlignedSize += len; } // bw = new BinaryWriter( m_IndexTable ); // bw.Write( ( int )m_IndexTable.Length ); m_header.IndexTableSize = IndexTableAlignedSize; m_IndexTable.Capacity = IndexTableAlignedSize; byte[] idxtable = m_IndexTable.GetBuffer(); bool res = BBACrypt.EncryptIndexTable(idxtable, m_header.IndexTableSize, null, 0); m_header.IndexTableCRC32 = GetCRC32(idxtable); m_header.Magic = s7_bba_header_magic; m_header.Magic2 = s7_bba_header_magic2; m_fs.Position = m_header.IndexTableOffset; m_fs.Write(idxtable, 0, idxtable.Length); m_fs.Position = 0; m_fs.Write(c_bbaHead, 0, c_bbaHead.Length); byte[] header = BuildHeader(); BBACrypt.EncryptHeader(header, header.Length, c_bbaHead, c_bbaHead.Length); m_fs.Write(header, 0, header.Length); listBox1.Items[idx] += "OK"; listBox1.Items.Add("BBA file successfully created."); } catch (Exception e) { listBox1.Items.Add(e.Message); } m_fs.Close(); m_fs = null; EnableControls(); GC.Collect(); }