public GARCEntry(byte[] data) { Data = data; Accessed = true; if (data.Length == 0) { return; } if (data[0] != 0x11) { return; } try { using (MemoryStream newMS = new MemoryStream()) { LZSS.Decompress(new MemoryStream(data), data.Length, newMS); Data = newMS.ToArray(); } WasCompressed = true; } catch { } }
public static bool garcUnpack(string garcPath, string outPath, bool skipDecompression, ProgressBar pBar1 = null, Label label = null, bool supress = false, bool bypassExt = false) { if (!File.Exists(garcPath) && !supress) { Util.Alert("File does not exist"); return(false); } // Unpack the GARC GARCFile garc = unpackGARC(garcPath); const string ext = "bin"; // Default Extension Name int fileCount = garc.fatb.FileCount; string format = "D" + Math.Ceiling(Math.Log10(fileCount)); if (outPath == "gametext") { format = "D3"; } #region Display // Initialize ProgressBar if (pBar1 == null) { pBar1 = new ProgressBar(); } if (pBar1.InvokeRequired) { pBar1.Invoke((MethodInvoker) delegate { pBar1.Minimum = 0; pBar1.Step = 1; pBar1.Value = 0; pBar1.Maximum = fileCount; }); } else { pBar1.Minimum = 0; pBar1.Step = 1; pBar1.Value = 0; pBar1.Maximum = garc.fatb.FileCount; } if (label == null) { label = new Label(); } if (label.InvokeRequired) { label.Invoke((MethodInvoker) delegate { label.Visible = true; }); } #endregion using (BinaryReader br = new BinaryReader(File.OpenRead(garcPath))) { // Create Extraction folder if it does not exist. if (!Directory.Exists(outPath)) { Directory.CreateDirectory(outPath); } int filectr = 0; // Pull out all the files for (int o = 0; o < garc.fato.EntryCount; o++) { var Entry = garc.fatb.Entries[o]; // Set Entry File Name string fileName = o.ToString(format); #region OutDirectory Determination string parentFolder = Entry.IsFolder ? Path.Combine(outPath, fileName) : outPath; if (Entry.IsFolder) // Process Folder { Directory.CreateDirectory(parentFolder); } #endregion uint vector = Entry.Vector; for (int i = 0; i < 32; i++) // For each bit in vector { var SubEntry = Entry.SubEntries[i]; if (!SubEntry.Exists) { continue; } // Seek to Offset br.BaseStream.Position = SubEntry.Start + garc.DataOffset; // Check if Compressed bool compressed = false; if (!skipDecompression) { try { compressed = (byte)br.PeekChar() == 0x11; } catch { } } // Write File string fileOut = Path.Combine(parentFolder, (Entry.IsFolder ? i.ToString("00") : fileName) + "." + ext); using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(fileOut))) { // Write out the data for the file br.BaseStream.Position = SubEntry.Start + garc.DataOffset; bw.Write(br.ReadBytes(SubEntry.Length)); filectr++; } if (compressed) #region Decompression { string decout = Path.Combine(Path.GetDirectoryName(fileOut), "dec_" + Path.GetFileName(fileOut)); try { LZSS.Decompress(fileOut, decout); try { File.Delete(fileOut); } catch (Exception e) { Util.Error("A compressed file could not be deleted.", fileOut, e.ToString()); } } catch { // File is really not encrypted. try { File.Delete(decout); } catch (Exception e) { Util.Error("This shouldn't happen", e.ToString()); } } } #endregion #region Step if (pBar1.InvokeRequired) { pBar1.Invoke((MethodInvoker)(() => pBar1.PerformStep())); } else { pBar1.PerformStep(); } string update = $"{filectr/fileCount:P2} - {filectr}/{fileCount}"; if (label.InvokeRequired) { label.Invoke((MethodInvoker) delegate { label.Text = update; }); } else { label.Text = update; } #endregion if ((vector >>= 1) == 0) { break; } } } } #region Updates if (label.InvokeRequired) { label.Invoke((MethodInvoker) delegate { label.Visible = false; }); } else { label.Visible = false; } SystemSounds.Exclamation.Play(); if (!supress) { Util.Alert("Unpack Successful!", fileCount + " files unpacked from the GARC!"); } #endregion return(true); }