public void SaveAll(object oinfo) { SaveAllInformation info = (SaveAllInformation)oinfo; IEnumerable <BigFile.Entry> saving; if (info.Saving == null) { saving = info.Archive.Entries; } else { saving = info.Saving; } this.SetStatus("", 0); int total = saving.Count(); int current = 0; byte[] buffer = new byte[0x4000]; foreach (var entry in saving) { current++; if (entry.Duplicate == true && info.Settings.SaveFilesWithDuplicateNames == false) { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } string fileName = null; if (info.FileNames.ContainsKey(entry.Name) == true) { fileName = info.FileNames[entry.Name]; if (entry.Duplicate == true) { string newFileName; newFileName = Path.GetFileNameWithoutExtension(fileName); newFileName = string.Format("{0} (duplicate #{1})", newFileName, current); newFileName = Path.ChangeExtension(newFileName, Path.GetExtension(fileName)); fileName = Path.Combine(Path.GetDirectoryName(fileName), newFileName); } } else { if (info.Settings.SaveOnlyKnownFiles) { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } fileName = entry.Name.ToString("X8"); if (true) { info.Stream.Seek(entry.Offset, SeekOrigin.Begin); byte[] guess = new byte[16]; int read = info.Stream.Read(guess, 0, guess.Length); if ( read >= 4 && guess[0] == 0x28 && guess[1] == 0x7B && guess[2] == 0xBA && guess[3] == 0x9C) { fileName = Path.ChangeExtension(fileName, ".toc"); fileName = Path.Combine("archive", fileName); } else if ( read >= 4 && guess[0] == 0x9C && guess[1] == 0xBA && guess[2] == 0x7B && guess[3] == 0x28) { fileName = Path.ChangeExtension(fileName, ".toc"); fileName = Path.Combine("archive", fileName); } else if ( read >= 4 && guess[0] == '3' && // 3 guess[1] == 's' && // s guess[2] == 'l' && // l guess[3] == 'o') // o { fileName = Path.ChangeExtension(fileName, ".str"); fileName = Path.Combine("archive", fileName); } else if ( read >= 4 && guess[0] == 'o' && // o guess[1] == 'l' && // l guess[2] == 's' && // s guess[3] == '3') // 3 { fileName = Path.ChangeExtension(fileName, ".str"); fileName = Path.Combine("archive", fileName); } else if ( read >= 4 && guess[0] == 'M' && guess[1] == 'V' && guess[2] == 'h' && guess[3] == 'd') { fileName = Path.ChangeExtension(fileName, ".vp6"); fileName = Path.Combine("video", fileName); } else if ( read >= 4 && guess[0] == 'S' && guess[1] == 'C' && guess[2] == 'H' && guess[3] == 'l') { fileName = Path.ChangeExtension(fileName, ".vp6"); fileName = Path.Combine("audio", fileName); } else if ( read >= 3 && guess[0] == 0x03 && guess[1] == 0x00 && guess[2] == 0x00) { fileName = Path.ChangeExtension(fileName, ".exa.snu"); fileName = Path.Combine("audio", fileName); } else { //fileName = Path.Combine(Path.Combine("unknown", fileName.Substring(0, 1)), fileName); fileName = Path.Combine("unknown", fileName); } } fileName = Path.Combine("__UNKNOWN", fileName); if (entry.Duplicate == true) { string newFileName; newFileName = Path.GetFileNameWithoutExtension(fileName); newFileName = string.Format("{0} (duplicate #{1})", newFileName, current); newFileName = Path.ChangeExtension(newFileName, Path.GetExtension(fileName)); fileName = Path.Combine(Path.GetDirectoryName(fileName), newFileName); } } string path = Path.Combine(info.BasePath, fileName); if (File.Exists(path) == true && info.Settings.DontOverwriteFiles == true) { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } if (info.Settings.DontSaveAudioFiles == true && Path.GetExtension(path) == ".snu") { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } this.SetStatus(fileName, (int)(((float)current / (float)total) * 100.0f)); Directory.CreateDirectory(Path.Combine(info.BasePath, Path.GetDirectoryName(fileName))); info.Stream.Seek(entry.Offset, SeekOrigin.Begin); using (var output = File.Create(path)) { int left = (int)entry.Size; while (left > 0) { int read = info.Stream.Read(buffer, 0, Math.Min(left, buffer.Length)); if (read == 0) { break; } output.Write(buffer, 0, read); left -= read; } } } this.SaveDone(); }
public void SaveAll(object oinfo) { SaveAllInformation info = (SaveAllInformation)oinfo; XmlTextWriter writer = new XmlTextWriter(Path.Combine(info.BasePath, "files.xml"), Encoding.UTF8); writer.Formatting = Formatting.Indented; writer.WriteStartDocument(); writer.WriteStartElement("files"); for (int i = 0; i < info.Files.Length; i++) { DatabasePackedFile.Entry index = info.Files[i]; string fileName = null; string groupName = null; if (Lookup.Files.ContainsKey(index.Key.InstanceId)) { fileName = Lookup.Files[index.Key.InstanceId]; char[] invalids = Path.GetInvalidFileNameChars(); for (int j = 0; j < invalids.Length; j++) { fileName = fileName.Replace(invalids[j].ToString(), ""); } } else { fileName = "#" + index.Key.InstanceId.ToString("X16"); } if (Lookup.Groups.ContainsKey(index.Key.GroupId)) { groupName = Lookup.Groups[index.Key.GroupId]; } else { groupName = "#" + index.Key.GroupId.ToString("X8"); } string fragmentPath; if (Lookup.Types.ContainsKey(index.Key.TypeId) == true) { TypeLookup type = Lookup.Types[index.Key.TypeId]; fragmentPath = Path.Combine(type.Category, type.Directory); fragmentPath = Path.Combine(fragmentPath, groupName); fileName += "." + Lookup.Types[index.Key.TypeId].Extension; } else { fragmentPath = Path.Combine("unknown", "#" + index.Key.TypeId.ToString("X8")); fragmentPath = Path.Combine(fragmentPath, groupName); } Directory.CreateDirectory(Path.Combine(info.BasePath, fragmentPath)); string path = Path.Combine(fragmentPath, fileName); this.SetStatus(path, i); writer.WriteStartElement("file"); writer.WriteAttributeString("groupid", "0x" + index.Key.GroupId.ToString("X8")); writer.WriteAttributeString("instanceid", "0x" + index.Key.InstanceId.ToString("X16")); writer.WriteAttributeString("typeid", "0x" + index.Key.TypeId.ToString("X8")); writer.WriteValue(path); writer.WriteEndElement(); path = Path.Combine(info.BasePath, path); if (index.Compressed) { info.Archive.Seek(index.Offset, SeekOrigin.Begin); byte[] d = info.Archive.RefPackDecompress(); FileStream output = new FileStream(path, FileMode.Create); output.Write(d, 0, d.Length); output.Close(); } else { info.Archive.Seek(index.Offset, SeekOrigin.Begin); byte[] d = new byte[index.DecompressedSize]; info.Archive.Read(d, 0, d.Length); FileStream output = new FileStream(path, FileMode.Create); output.Write(d, 0, d.Length); output.Close(); } } writer.WriteEndElement(); writer.WriteEndDocument(); writer.Flush(); writer.Close(); this.SaveDone(); }
public void SaveAll(object oinfo) { SaveAllInformation info = (SaveAllInformation)oinfo; IEnumerable <ERF.Entry> saving; if (info.Saving == null) { saving = info.Archive.Entries; } else { saving = info.Saving; } this.SetStatus("", 0); int total = saving.Count(); int current = 0; var buffer = new byte[0x100000]; foreach (var entry in saving) { current++; string fileName = null; if (entry.Name != null) { fileName = entry.Name; } else { if (info.FileNames.Contains(entry.NameHash) == true) { fileName = info.FileNames[entry.NameHash]; } else { if (info.Settings.SaveOnlyKnownFiles) { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } if (info.TypeNames != null && info.TypeNames.Contains(entry.TypeHash) == true) { fileName = entry.NameHash.ToString("X16") + "." + info.TypeNames[entry.TypeHash]; fileName = Path.Combine(info.TypeNames[entry.TypeHash], fileName); } else { fileName = entry.NameHash.ToString("X16") + "." + entry.TypeHash.ToString("X8"); } fileName = Path.Combine("__UNKNOWN", fileName); } } string path = Path.Combine(info.BasePath, fileName); if (File.Exists(path) == true && info.Settings.DontOverwriteFiles == true) { this.SetStatus("Skipping...", (int)(((float)current / (float)total) * 100.0f)); continue; } this.SetStatus(fileName, (int)(((float)current / (float)total) * 100.0f)); Directory.CreateDirectory(Path.Combine(info.BasePath, Path.GetDirectoryName(fileName))); info.Stream.Seek(entry.Offset, SeekOrigin.Begin); using (var output = File.Create(path)) { Stream data = info.Stream; switch (info.Archive.Encryption) { case ERF.EncryptionScheme.None: { //data = data; break; } default: { throw new NotSupportedException("unsupported encryption scheme"); } } switch (info.Archive.Compression) { case ERF.CompressionScheme.BiowareZlib: { /* Bioware's zlib has a custom header of 1 byte * rather than the normal two-byte zlib header. * * The upper 4 bits are the window bits. * * The uppermost bit must always be set to 1, * since a valid window bits size must be from * 8 to 15. * * Don't know what the lower 4 bits are for yet. * * So for now, we'll ignore it their header. */ data.Seek(1, SeekOrigin.Current); data = new InflaterInputStream( data, new Inflater(true)); break; } case ERF.CompressionScheme.HeaderlessZlib: { data = new InflaterInputStream( data, new Inflater(true)); break; } case ERF.CompressionScheme.None: { //data = data; break; } default: { throw new NotSupportedException("unsupported compression scheme"); } } long left = entry.UncompressedSize; while (left > 0) { int block = (int)(Math.Min(left, buffer.Length)); int read = data.Read(buffer, 0, block); output.Write(buffer, 0, read); left -= read; } } } this.SaveDone(); }