private void Run(Settings settings, ProgressDialog dialog) { for (int i = 0; i < fileList.Count; i++) { string file = fileList[i]; string description; if (fileList.Count == 1) { description = String.Format("Processing {0}", Path.GetFileName(file)); } else { description = String.Format("Processing {0} ({1:N0} of {2:N0})", Path.GetFileName(file), i + 1, fileList.Count); } dialog.ReportProgress(i * 100 / fileList.Count, description); // Let's open the file. // But, we're going to do this in a try catch in case any errors happen. try { ArchiveFormat format; string outPath, outName; Queue <TextureEntry> textureFileQueue = null; using (FileStream inStream = File.OpenRead(file)) { // Set source to inStream // The reason we do it like this is because source does not always equal inStream. // You'll see why very soon. Stream source = inStream; // Get the format of the archive format = Archive.GetFormat(source, Path.GetFileName(file)); if (format == ArchiveFormat.Unknown) { // Maybe it's compressed? Let's check. // But first, we need to make sure we want to check if (settings.DecompressSourceArchive) { // Get the compression format, if it is compressed that is. CompressionFormat compressionFormat = Compression.GetFormat(source, Path.GetFileName(file)); if (compressionFormat != CompressionFormat.Unknown) { // Ok, it appears to be compressed. Let's decompress it, and then check the format again source = new MemoryStream(); Compression.Decompress(inStream, source, compressionFormat); source.Position = 0; format = Archive.GetFormat(source, Path.GetFileName(file)); } } // If we still don't know what the archive format is, just skip the file. if (format == ArchiveFormat.Unknown) { continue; } } // Now that we know its format, let's open it and start working with it. ArchiveReader archive = Archive.Open(source, format); // Get the appropiate output directory if (settings.ExtractToSourceDirectory) { // Extract to the same directory as the source archive outPath = Path.GetDirectoryName(file); } else if (settings.ExtractToSameNameDirectory) { // Extract to a directory of the same name outPath = file + "." + Path.GetRandomFileName(); } else { // Just the standard output path outPath = Path.Combine(Path.Combine(Path.GetDirectoryName(file), "Extracted Files"), Path.GetFileNameWithoutExtension(file)); } // Create the output directory if it does not exist if (!Directory.Exists(outPath)) { Directory.CreateDirectory(outPath); } // Now we can start extracting the files for (int j = 0; j < archive.Entries.Count; j++) { if (fileList.Count == 1) { // If there is just one file in the file list, then the progress will be // based on how many files are being extracted from the archive, not // how many archives we are extracting. dialog.ReportProgress(j * 100 / archive.Entries.Count, description + "\n\n" + String.Format("{0:N0} of {1:N0} extracted", j + 1, archive.Entries.Count)); } else { dialog.Description = description + "\n\n" + String.Format("{0:N0} of {1:N0} extracted", j + 1, archive.Entries.Count); } ArchiveEntry entry = archive.Entries[j]; Stream entryData = entry.Open(); // Get the output name for this file if (settings.FileNumberAsFilename || entry.Name == String.Empty) { // Use the file number as its filename outName = j.ToString("D" + archive.Entries.Count.ToString().Length) + Path.GetExtension(entry.Name); } else if (settings.AppendFileNumber) { // Append the file number to its filename outName = Path.GetFileNameWithoutExtension(entry.Name) + j.ToString("D" + archive.Entries.Count.ToString().Length) + Path.GetExtension(entry.Name); } else { // Just use the filename as defined in the archive outName = entry.Name; } // What we're going to do here may seem a tiny bit hackish, but it'll make my job much simplier. // First, let's check to see if the file is compressed, and if we want to decompress it. if (settings.DecompressExtractedFiles) { // Get the compression format, if it is compressed that is. CompressionFormat compressionFormat = Compression.GetFormat(entryData, entry.Name); if (compressionFormat != CompressionFormat.Unknown) { // Ok, it appears to be compressed. Let's decompress it, and then edit the entry MemoryStream decompressedData = new MemoryStream(); Compression.Decompress(entryData, decompressedData, compressionFormat); entryData = decompressedData; entryData.Position = 0; } } // Check to see if this file is a texture. If so, let's convert it to a PNG and then edit the entry if (settings.ConvertExtractedTextures) { // Get the texture format, if it is a texture that is. TextureFormat textureFormat = Texture.GetFormat(entryData, entry.Name); if (textureFormat != TextureFormat.Unknown) { // Ok, it appears to be a texture. We're going to attempt to convert it here. // If we get a TextureNeedsPalette exception, we'll wait until after we extract // all the files in this archive before we process it. try { MemoryStream textureData = new MemoryStream(); Texture.Read(entryData, textureData, textureFormat); // If no exception was thrown, then we are all good doing what we need to do entryData = textureData; entryData.Position = 0; outName = Path.GetFileNameWithoutExtension(outName) + ".png"; } catch (TextureNeedsPaletteException) { // Uh oh, looks like we need a palette. // What we are going to do is add it to textureFileQueue, then convert it // after we extract all of the files. if (textureFileQueue == null) { textureFileQueue = new Queue <TextureEntry>(); } TextureEntry textureEntry = new TextureEntry(); textureEntry.Format = textureFormat; textureEntry.Filename = Path.Combine(outPath, outName); textureFileQueue.Enqueue(textureEntry); } } } // Time to write out the file using (FileStream destination = File.Create(Path.Combine(outPath, outName))) { PTStream.CopyTo(entryData, destination, (int)entryData.Length); } // Let's check to see if this is an archive. If it is an archive, add it to the file list. entryData.Position = 0; if (settings.ExtractExtractedArchives) { ArchiveFormat archiveFormat = Archive.GetFormat(entryData, entry.Name); if (archiveFormat != ArchiveFormat.Unknown) { // It appears to be an archive. Let's add it to the file list if (settings.ExtractToSameNameDirectory) { // If we're adding to a directory of the same name, the outPath will be different. // We should remember that. fileList.Add(Path.Combine(file, outName)); } else { fileList.Add(Path.Combine(outPath, outName)); } if (fileList.Count == 2) { // If there was one archive in the file list, and now there is more, // adjust the progress bar and the description description = String.Format("Processing {0} ({1:N0} of {2:N0})", Path.GetFileName(file), i + 1, fileList.Count); dialog.ReportProgress(i * 100 / fileList.Count, description + "\n\n" + String.Format("{0:N0} of {1:N0} extracted", j + 1, archive.Entries.Count)); } } } } } // Let's see if we have any textures we still need to convert. if (settings.ConvertExtractedTextures && textureFileQueue != null) { // Ok, it appears we do. So, let's loop through the queue until it is empty. while (textureFileQueue.Count > 0) { TextureEntry textureEntry = textureFileQueue.Dequeue(); // Get the palette file name, and the out file name string paletteName = Path.Combine(Path.GetDirectoryName(textureEntry.Filename), Path.GetFileNameWithoutExtension(textureEntry.Filename)) + Texture.Formats[textureEntry.Format].PaletteFileExtension; string textureOutName = Path.Combine(Path.GetDirectoryName(textureEntry.Filename), Path.GetFileNameWithoutExtension(textureEntry.Filename)) + ".png"; // Make sure the two files exist before we attempt to open them. // Wrap the whole thing in a try catch in case for some reason the texture file was modifed. // That way, it'll fail peacefully and not screw over last minute things that need to be done to the archive. // Open up the archive and test to make sure it's still a valid texture. // You know, in case somehow it was edited or not extracted properly. if (File.Exists(textureEntry.Filename) && File.Exists(paletteName)) { try { using (FileStream inTextureStream = File.OpenRead(textureEntry.Filename)) { if (!Texture.Formats[textureEntry.Format].Is(inTextureStream, (int)inTextureStream.Length, textureEntry.Filename)) { // Oh dear, somehow this isn't a texture anymore. Just skip over it continue; } // Ok, now we can load the palette data and try to convert it. using (FileStream inPaletteStream = File.OpenRead(paletteName), outTextureStream = File.Create(textureOutName)) { TextureBase texture = Texture.Formats[textureEntry.Format]; texture.PaletteStream = inPaletteStream; texture.PaletteLength = (int)inPaletteStream.Length; texture.Read(inTextureStream, outTextureStream, (int)inTextureStream.Length); } } // Now we can delete those two files File.Delete(textureEntry.Filename); File.Delete(paletteName); } catch { // Something happened! But we'll just ignore it. } } } } // Delete the source archive if the user chose to if (settings.DeleteSourceArchive) { File.Delete(file); } // If we're extracting to a directory of the same name, we can now rename the directory if (settings.ExtractToSameNameDirectory) { Directory.Move(outPath, file); } } catch { // Meh, just ignore the error. } } }
private void listView_DoubleClick(object sender, EventArgs e) { int index = listView.SelectedIndices[0]; if (openedArchives.Count > 1) { // Do we want to go to the parent archive? if (index == 0) { openedArchives.Pop(); openedArchiveNames.RemoveAt(openedArchiveNames.Count - 1); Populate(openedArchives.Peek()); return; } else { // Subtract the index by 1 so we're referring to the correct files index--; } } ArchiveEntry entry = openedArchives.Peek().Archive.Entries[index]; Stream entryData = entry.Open(); // Let's determine first if it is an archive or a texture ArchiveFormat archiveFormat; TextureFormat textureFormat; archiveFormat = Archive.GetFormat(entryData, entry.Name); if (archiveFormat != ArchiveFormat.Unknown) { // This is an archive. Let's open it. OpenArchive(entryData, entry.Name, archiveFormat); return; } textureFormat = Texture.GetFormat(entryData, entry.Name); if (textureFormat != TextureFormat.Unknown) { // This is a texture. Let's attempt to open it up in the texture viewer OpenTexture(entryData, entry.Name, textureFormat); return; } // It's not an archive or a texture. Maybe it's compressed? CompressionFormat compressionFormat = Compression.GetFormat(entryData, entry.Name); if (compressionFormat != CompressionFormat.Unknown) { // The file is compressed! Let's decompress it and then try to determine if it is an archive or a texture MemoryStream decompressedData = new MemoryStream(); Compression.Decompress(entryData, decompressedData, compressionFormat); decompressedData.Position = 0; // Now with this decompressed data, let's determine if it is an archive or a texture archiveFormat = Archive.GetFormat(decompressedData, entry.Name); if (archiveFormat != ArchiveFormat.Unknown) { // This is an archive. Let's open it. OpenArchive(decompressedData, entry.Name, archiveFormat); return; } textureFormat = Texture.GetFormat(decompressedData, entry.Name); if (textureFormat != TextureFormat.Unknown) { // This is a texture. Let's attempt to open it up in the texture viewer OpenTexture(decompressedData, entry.Name, textureFormat); return; } } }