public static byte[] getDataBySHA1(string sha1, SQLiteConnection con) { SQLiteDataReader reader = Database.getAllWhere("sha1db", "line LIKE '" + sha1 + "%'", con); if (!reader.Read()) { return(new byte[0]); } string lines = reader.GetString(0); byte[] buff = Tools.StringToByteArray(lines); uint[] line = new uint[9]; MemoryStream m = new MemoryStream(buff); m.Seek(20, 0); uint offset = Tools.ReadLEUInt(m); uint size = Tools.ReadLEUInt(m); uint casn = Tools.ReadLEUInt(m); reader = Database.getAllWhere("casfiles", "path LIKE '%cas_" + casn.ToString("d2") + ".cas'", con); if (!reader.Read()) { return(new byte[0]); } CASFile cas = new CASFile(reader.GetString(0)); CASFile.CASEntry entry = cas.ReadEntry(offset, size); return(entry.data); }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "*.cas|*.cas"; if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { cas = new CASFile(d.FileName); OpenFileDialog d2 = new OpenFileDialog(); d2.Filter = "*.cat|*.cat"; if (d2.ShowDialog() == System.Windows.Forms.DialogResult.OK) { cat = new CATFile(d2.FileName); cas.SetCAT(cat); if (cas.Indexes.Count > 100) { hs1.Maximum = cas.Indexes.Count - 100; } else { hs1.Maximum = 0; } RefreshList(); } } }
private void ExtractAllTextures(string target, bool withpath) { if (cat == null) { return; } rtb1.Text = ""; string basepath = Path.GetDirectoryName(cat.MyPath) + "\\"; pb1.Value = 0; pb1.Maximum = listTex.Count; for (int i = 0; i < listTex.Count; i++) { TextureInfo t = listTex[i]; if (t.chunk.catline != null && CheckCASExist(basepath, t.chunk.catline[7])) { string path = GetDDSTargetFullPath(target, withpath, t); CASFile cas = new CASFile(CASFile.GetCASFileName(basepath, t.chunk.catline[7])); CASFile.CASEntry e = cas.ReadEntry(t.chunk.catline.ToArray()); WriteDDSFile(ref t, path, ref e); rtb1.AppendText("Wrote file: " + path + "\n"); Application.DoEvents(); pb1.Value = i; } } rtb1.AppendText("Done.\n"); }
public CASResult Write() { FixOffsets(); using (var md5 = MD5.Create()) using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { // write each chunk foreach (var c in Chunks) { bw.Write((uint)c.Entries.Count); bw.Write((uint)c.ContentFlags); bw.Write((uint)c.LocaleFlags); foreach (var e in c.Entries) { bw.Write(e.FileDataIdOffset); } foreach (var e in c.Entries) { bw.Write(e.CEKey.Value); bw.Write(e.NameHash); } } // create CASCFile CASFile entry = new CASFile(ms.ToArray(), encodingMap.Type, encodingMap.CompressionLevel); // save and update Build Config CASResult res = DataHandler.Write(WriteMode.CDN, entry); res.CEKey = new MD5Hash(md5.ComputeHash(ms.ToArray())); res.HighPriority = true; CASContainer.BuildConfig.Set("root", res.CEKey.ToString()); CASContainer.Logger.LogInformation($"Root: EKey: {res.EKey} CEKey: {res.CEKey}"); // cache Root Hash CASContainer.Settings.Cache?.AddOrUpdate(new CacheEntry() { CEKey = res.CEKey, EKey = res.EKey, Path = "__ROOT__" }); return(res); } }
public static byte[] GetDataBySha1(byte[] sha1, int maxsize = 0x7FFFFFFF) { CATFile cat = null; if (cat_base == null) { string path = GlobalStuff.FindSetting("gamepath") + "Data\\cas.cat"; cat_base = new CATFile(path); } List <uint> casline = cat_base.FindBySHA1(sha1); if (casline.Count == 9) { cat = cat_base; } else { if (cat_patch == null) { string path = GlobalStuff.FindSetting("gamepath") + "Update\\Patch\\Data\\cas.cat"; cat_patch = new CATFile(path); } cat = cat_patch; casline = cat_patch.FindBySHA1(sha1); } if (casline.Count == 9) { if (cas == null || cas.casnumber != casline[7]) { string[] files = Directory.GetFiles(Path.GetDirectoryName(cat.MyPath)); foreach (string file in files) { if (Path.GetFileName(file) == CASFile.GetCASFileName(casline[7])) { cas = new CASFile(file); break; } } } if (cas != null && cas.casnumber == casline[7]) { CASFile.CASEntry ce = cas.ReadEntry(casline.ToArray(), maxsize); return(ce.data); } } return(new byte[0]); }
private void LinkTexAndChunks() { if (cat == null) { return; } string basepath = Path.GetDirectoryName(cat.MyPath) + "\\"; for (int i = 0; i < listTex.Count; i++) { TextureInfo t = listTex[i]; if (t.catline != null && CheckCASExist(basepath, t.catline[7])) { CASFile cas = new CASFile(CASFile.GetCASFileName(basepath, t.catline[7])); CASFile.CASEntry e = cas.ReadEntry(t.catline.ToArray()); byte[] id = null; LoadTextureData(ref t, ref id, e.data); LoadChunkData(ref t, i, id); } } }
public CASResult Write(List <CASResult> newentries) { if (!NeedsWrite(newentries)) { return(null); } byte[][] entries = new byte[EncodingMap.Length][]; CASFile[] files = new CASFile[EncodingMap.Length]; // header using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { bw.Write(Header.Magic); bw.Write(Header.Version); bw.Write(Header.HashSize); bw.WriteUInt16BE((ushort)Tags.Count); bw.WriteUInt32BE((uint)InstallData.Count); foreach (var tag in Tags) { bw.Write(Encoding.UTF8.GetBytes(tag.Name)); bw.Write((byte)0); bw.WriteUInt16BE(tag.Type); bw.Write(tag.BitMask.ToByteArray()); } entries[0] = ms.ToArray(); files[0] = new CASFile(entries[0], EncodingMap[0].Type, EncodingMap[0].CompressionLevel); } // entries using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { foreach (var entry in InstallData) { bw.Write(Encoding.UTF8.GetBytes(entry.Name)); bw.Write((byte)0); bw.Write(entry.CEKey.Value); bw.WriteUInt32BE(entry.Size); } entries[1] = ms.ToArray(); files[1] = new CASFile(entries[1], EncodingMap[1].Type, EncodingMap[1].CompressionLevel); } // write CASResult res = DataHandler.Write(WriteMode.CDN, files); using (var md5 = MD5.Create()) res.CEKey = new MD5Hash(md5.ComputeHash(entries.SelectMany(x => x).ToArray())); Console.WriteLine($"Install: EKey: {res.EKey} CEKey: {res.CEKey}"); CASContainer.BuildConfig.Set("install-size", res.DecompressedSize.ToString()); CASContainer.BuildConfig.Set("install-size", (res.CompressedSize - 30).ToString(), 1); // BLTE size minus header CASContainer.BuildConfig.Set("install", res.CEKey.ToString()); CASContainer.BuildConfig.Set("install", res.EKey.ToString(), 1); Array.Resize(ref entries, 0); Array.Resize(ref files, 0); return(res); }
public CASResult Write() { byte[][] entries = new byte[EncodingMap.Length][]; CASFile[] files = new CASFile[EncodingMap.Length]; // ESpecStringTable 1 entries[1] = Encoding.UTF8.GetBytes(string.Join("\0", ESpecStringTable)); files[1] = new CASFile(entries[1], EncodingMap[1].Type, EncodingMap[1].CompressionLevel); // CEKeysPageTable Data 3 using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { long pos = 0; foreach (var entry in CEKeys.Values) { if (pos + entry.EntrySize > CHUNK_SIZE) { bw.Write(new byte[CHUNK_SIZE - pos]); // pad to chunk size pos = 0; } bw.Write((ushort)entry.EKeys.Count); bw.WriteUInt32BE(entry.DecompressedSize); bw.Write(entry.CKey.Value); for (int i = 0; i < entry.EKeys.Count; i++) { bw.Write(entry.EKeys[i].Value); } pos += entry.EntrySize; } bw.Write(new byte[CHUNK_SIZE - pos]); // final padding entries[3] = ms.ToArray(); files[3] = new CASFile(entries[3], EncodingMap[3].Type, EncodingMap[3].CompressionLevel); } // EKeysPageTable Data 5 using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { long pos = 0; foreach (var entry in EKeys.Values) { if (pos + entry.EntrySize > CHUNK_SIZE) { bw.Write(new byte[CHUNK_SIZE - pos]); // pad to chunk size pos = 0; } bw.Write(entry.EKey.Value); bw.WriteUInt32BE(entry.ESpecStringIndex); bw.WriteUInt40BE(entry.FileSize); pos += entry.EntrySize; } // EOF flag bw.Write(new byte[16]); // empty hash bw.Write(0xFFFFFFFF); // flag pos += 16 + 4; bw.Write(new byte[CHUNK_SIZE - pos]); // final padding entries[5] = ms.ToArray(); files[5] = new CASFile(entries[5], EncodingMap[5].Type, EncodingMap[5].CompressionLevel); } // CEKeysPageTable lookup 2 using (var md5 = MD5.Create()) using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { int chunks = entries[3].Length / CHUNK_SIZE; for (int i = 0; i < chunks; i++) { byte[] chunk = new byte[CHUNK_SIZE]; Buffer.BlockCopy(entries[3], (i * CHUNK_SIZE), chunk, 0, CHUNK_SIZE); bw.Write(chunk, 6, 16); // first entry hash bw.Write(md5.ComputeHash(chunk)); // md5 of chunk } entries[2] = ms.ToArray(); files[2] = new CASFile(entries[2], EncodingMap[2].Type, EncodingMap[2].CompressionLevel); } // EKeysPageTable lookup 4 using (var md5 = MD5.Create()) using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { int chunks = entries[5].Length / CHUNK_SIZE; for (int i = 0; i < chunks; i++) { byte[] chunk = new byte[CHUNK_SIZE]; Buffer.BlockCopy(entries[5], (i * CHUNK_SIZE), chunk, 0, CHUNK_SIZE); bw.Write(chunk, 0, 16); // first entry hash bw.Write(md5.ComputeHash(chunk)); // md5 of chunk } entries[4] = ms.ToArray(); files[4] = new CASFile(entries[4], EncodingMap[4].Type, EncodingMap[4].CompressionLevel); } // Encoding Header 0 using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { bw.Write(Header.Magic); bw.Write(Header.Version); bw.Write(Header.ChecksumSizeC); bw.Write(Header.ChecksumSizeE); bw.Write(Header.PageSizeCEKey); bw.Write(Header.PageSizeEKey); bw.WriteUInt32BE((uint)entries[2].Length / 32); bw.WriteUInt32BE((uint)entries[4].Length / 32); bw.Write(Header.Unknown_x11); bw.WriteUInt32BE((uint)Encoding.UTF8.GetByteCount(string.Join("\0", ESpecStringTable))); entries[0] = ms.ToArray(); files[0] = new CASFile(entries[0], EncodingMap[0].Type, EncodingMap[0].CompressionLevel); } // Encoding's own ESpecStringTable 6 entries[6] = GetStringTable(entries.Select(x => x.Length)); files[6] = new CASFile(entries[6], EncodingMap[6].Type, EncodingMap[6].CompressionLevel); //Write CASResult res = DataHandler.Write(WriteMode.CDN, files); using (var md5 = MD5.Create()) res.CEKey = new MD5Hash(md5.ComputeHash(entries.SelectMany(x => x).ToArray())); CASContainer.Logger.LogInformation($"Encoding: EKey: {res.EKey} CEKey: {res.CEKey}"); CASContainer.BuildConfig.Set("encoding-size", res.DecompressedSize.ToString()); CASContainer.BuildConfig.Set("encoding-size", (res.CompressedSize - 30).ToString(), 1); // BLTE size minus header CASContainer.BuildConfig.Set("encoding", res.CEKey.ToString()); CASContainer.BuildConfig.Set("encoding", res.EKey.ToString(), 1); Array.Resize(ref entries, 0); Array.Resize(ref files, 0); entries = null; files = null; // cache Encoding Hash CASContainer.Settings.Cache?.AddOrUpdate(new CacheEntry() { CEKey = res.CEKey, EKey = res.EKey, Path = "__ENCODING__" }); return(res); }
public CASResult Write() { byte[][] entries = new byte[EncodingMap.Length][]; CASFile[] files = new CASFile[EncodingMap.Length]; // header using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { bw.Write(Header.Header); bw.Write(Header.Version); bw.Write(Header.ChecksumSize); bw.Write(Header.HasChecksum); bw.WriteUInt32BE((uint)Entries.Count); bw.WriteUInt16BE((ushort)Tags.Count); if (Header.Version >= 2) { bw.Write(Header.NumFlags); } if (Header.Version >= 3) { // TODO //bw.Write(Header.BasePriority); //bw.Write(Header.Unknown_0D); } entries[0] = ms.ToArray(); files[0] = new CASFile(entries[0], EncodingMap[0].Type, EncodingMap[0].CompressionLevel); } // files using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { foreach (var entry in Entries) { bw.Write(entry.EKey.Value); bw.WriteUInt40BE(entry.FileSize); bw.Write(entry.Priority); if (Header.HasChecksum != 0) { bw.WriteUInt32BE(entry.Checksum); } if (Header.Version >= 2) { bw.Write((byte[])(object)entry.Flags); } } entries[1] = ms.ToArray(); files[1] = new CASFile(entries[1], EncodingMap[1].Type, EncodingMap[1].CompressionLevel); } // tags using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { foreach (var tag in Tags) { bw.Write(Encoding.UTF8.GetBytes(tag.Name)); bw.Write((byte)0); bw.WriteUInt16BE(tag.Type); bw.Write(tag.BitMask.ToByteArray()); tag.BitMask.Clear(); } entries[2] = ms.ToArray(); files[2] = new CASFile(entries[2], EncodingMap[2].Type, EncodingMap[2].CompressionLevel); } // write CASResult res = DataHandler.Write(WriteMode.CDN, files); using (var md5 = MD5.Create()) res.CEKey = new MD5Hash(md5.ComputeHash(entries.SelectMany(x => x).ToArray())); File.Delete(Path.Combine(CASContainer.Settings.OutputPath, CASContainer.BuildConfig["download"][0])); CASContainer.Logger.LogInformation($"Download: EKey: {res.EKey} CEKey: {res.CEKey}"); CASContainer.BuildConfig.Set("download-size", res.DecompressedSize.ToString()); CASContainer.BuildConfig.Set("download-size", (res.CompressedSize - 30).ToString(), 1); CASContainer.BuildConfig.Set("download", res.CEKey.ToString()); CASContainer.BuildConfig.Set("download", res.EKey.ToString(), 1); Array.Resize(ref entries, 0); Array.Resize(ref files, 0); entries = null; files = null; return(res); }
private bool CheckCASExist(string basepath, uint id) { return(File.Exists(CASFile.GetCASFileName(basepath, id))); }
public static void AddBundle(string filepath, Bundle b, SQLiteConnection con, CATFile cat) { if (b.ebx == null) { b.ebx = new List <Bundle.ebxtype>(); } if (b.res == null) { b.res = new List <Bundle.restype>(); } if (b.chunk == null) { b.chunk = new List <Bundle.chunktype>(); } SQLCommand("INSERT INTO bundles VALUES (NULL,'" + filepath + "','" + b.path + "', " + b.ebx.Count + ", " + b.res.Count + ", " + b.chunk.Count + " )", con); SQLiteCommand command = new SQLiteCommand("SELECT last_insert_rowid()", con); SQLiteDataReader reader = command.ExecuteReader(); reader.Read(); long id = (long)reader.GetValue(0); var transaction = con.BeginTransaction(); string basepath = Path.GetDirectoryName(cat.MyPath) + "\\"; if (!exceptions.Contains(b.path)) { foreach (Bundle.ebxtype ebx in b.ebx) { StringBuilder sb = new StringBuilder(); foreach (byte bb in ebx.SHA1) { sb.Append(bb.ToString("X2")); } List <uint> line = cat.FindBySHA1(ebx.SHA1); string type = ""; string guid = ""; if (line.Count == 9) { CASFile cas = new CASFile(basepath + "cas_" + line[7].ToString("d2") + ".cas"); CASFile.CASEntry entry = cas.ReadEntry(line.ToArray()); try { /* Just obtain the Guid and Type from raw EBX */ Tools.ExtractEbxGuidAndType(new MemoryStream(entry.data), out type, out guid); } catch (Exception) { } } SQLCommand("INSERT INTO ebx VALUES ('" + ebx.name.Replace("'", "") + "','" + sb.ToString() + "', " + id + ", '" + type + "', '" + guid + "')", con); } } transaction.Commit(); transaction = con.BeginTransaction(); foreach (Bundle.restype res in b.res) { StringBuilder sb = new StringBuilder(); foreach (byte bb in res.SHA1) { sb.Append(bb.ToString("X2")); } uint restype = BitConverter.ToUInt32(res.rtype, 0); SQLCommand("INSERT INTO res VALUES ('" + res.name.Replace("'", "") + "','" + sb.ToString() + "', '" + restype.ToString("X8") + "', " + id + ")", con); } transaction.Commit(); transaction = con.BeginTransaction(); foreach (Bundle.chunktype chunk in b.chunk) { StringBuilder sb = new StringBuilder(); foreach (byte bb in chunk.id) { sb.Append(bb.ToString("X2")); } StringBuilder sb2 = new StringBuilder(); foreach (byte bb2 in chunk.SHA1) { sb2.Append(bb2.ToString("X2")); } SQLCommand("INSERT INTO chunk VALUES ('" + sb.ToString() + "', '" + sb2.ToString() + "', " + id + ")", con); } transaction.Commit(); }
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { TreeNode t = treeView1.SelectedNode; if (t == null) { return; } if (t.Text == "82") { TreeNode t2 = null; foreach (TreeNode child in t.Nodes) { if (child.Text == "sha1") { t2 = child; break; } } if (t2 != null) { string sha1 = t2.Nodes[0].Text; byte[] sha1buff = Tools.StringToByteArray(sha1); if (cat == null) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "*.cat|*.cat"; if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { cat = new CATFile(d.FileName); } else { return; } } List <uint> casline = cat.FindBySHA1(sha1buff); if (casline.Count == 8) { if (cas == null) { string[] files = Directory.GetFiles(Path.GetDirectoryName(cat.MyPath)); foreach (string file in files) { if (Path.GetFileName(file) == CASFile.GetCASFileName(casline[7])) { cas = new CASFile(file); break; } } } if (cas != null && cas.casnumber == casline[7]) { CASFile.CASEntry ce = cas.ReadEntry(casline.ToArray()); hb1.ByteProvider = new DynamicByteProvider(ce.data); hb1.BringToFront(); rtb1.Text = Tools.DecompileLUAC(ce.data); if (rtb1.Text != "") { rtb1.BringToFront(); } } } } } }
private void extractResourceToolStripMenuItem_Click(object sender, EventArgs e) { TreeNode t = treeView1.SelectedNode; if (t == null) { return; } TreeNode sha1t = null; foreach (TreeNode child in t.Nodes) { if (child.Text == "sha1") { sha1t = child; break; } } if (sha1t == null) { return; } string sha1 = sha1t.Nodes[0].Text; byte[] sha1b = Tools.StringToByteArray(sha1); if (cat == null) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "*.cat|*.cat"; if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { cat = new CATFile(d.FileName); } else { return; } } List <uint> catline = cat.FindBySHA1(sha1b); CASFile.CASEntry ce = new CASFile.CASEntry(); if (catline.Count == 8) { if (cas != null && cas.casnumber == catline[7]) { ce = cas.ReadEntry(catline.ToArray()); } else { OpenFileDialog d = new OpenFileDialog(); string casname = CASFile.GetCASFileName(catline[7]); d.Filter = casname + "|" + casname; d.FileName = casname; if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { cas = new CASFile(d.FileName); ce = cas.ReadEntry(catline.ToArray()); } else { return; } } } else { MessageBox.Show("SHA1 Not found!"); return; } SaveFileDialog d2 = new SaveFileDialog(); d2.Filter = "*.bin|*.bin"; d2.FileName = sha1 + ".bin"; if (d2.ShowDialog() == System.Windows.Forms.DialogResult.OK) { File.WriteAllBytes(d2.FileName, ce.data); MessageBox.Show("Done."); return; } return; }