private void ExportButton_Click(object sender, EventArgs e) { if (InProgress) { return; } if (!(RpfMan?.IsInited ?? false)) { MessageBox.Show("Please wait for the scan to complete."); return; } RpfFileEntry rfe = RpfSelectedEntry as RpfFileEntry; if (rfe == null) { MessageBox.Show("Please select a file to export."); return; } SaveFileDialog.FileName = rfe.Name; if (SaveFileDialog.ShowDialog() == DialogResult.OK) { string fpath = SaveFileDialog.FileName; byte[] data = rfe.File.ExtractFile(rfe); if (ExportCompressCheckBox.Checked) { data = ResourceBuilder.Compress(data); } RpfResourceFileEntry rrfe = rfe as RpfResourceFileEntry; if (rrfe != null) //add resource header if this is a resource file. { data = ResourceBuilder.AddResourceHeader(rrfe, data); } if (data == null) { MessageBox.Show("Error extracting file! " + rfe.File.LastError); return; } try { File.WriteAllBytes(fpath, data); } catch (Exception ex) { MessageBox.Show("Error saving file! " + ex.ToString()); } } }
public static byte[] SaveResourceAsBytes(RpfEntry RPFFile) { RpfFileEntry InternalFile = (RpfFileEntry)RPFFile; byte[] data = InternalFile.Parent.File.ExtractFile(InternalFile); RpfResourceFileEntry rrfe = InternalFile as RpfResourceFileEntry; if (rrfe != null) { data = ResourceBuilder.Compress(data); data = ResourceBuilder.AddResourceHeader(rrfe, data); } return(data); }
private void ExtractButton_Click(object sender, EventArgs e) { if (InProgress) { return; } if (!KeysLoaded) { MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); return; } if (!Directory.Exists(FolderTextBox.Text)) { MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); return; } if (!Directory.Exists(OutputFolderTextBox.Text)) { MessageBox.Show("Folder doesn't exist: " + OutputFolderTextBox.Text); return; } if (string.IsNullOrEmpty(FileMatchTextBox.Text) || (FileMatchTextBox.Text.Length < 3)) { MessageBox.Show("Please enter at least 3 characters to match."); return; } InProgress = true; AbortOperation = false; string searchpath = FolderTextBox.Text; string outputpath = OutputFolderTextBox.Text; string replpath = searchpath + "\\"; string matchstr = FileMatchTextBox.Text; bool endswith = MatchEndsWithRadio.Checked; bool compress = CompressCheckBox.Checked; Task.Run(() => { UpdateExtractStatus("Keys loaded."); RpfManager rpfman = new RpfManager(); rpfman.Init(searchpath, UpdateExtractStatus, UpdateExtractStatus); UpdateExtractStatus("Beginning file extraction..."); StringBuilder errsb = new StringBuilder(); foreach (RpfFile rpf in rpfman.AllRpfs) { foreach (RpfEntry entry in rpf.AllEntries) { if (AbortOperation) { UpdateExtractStatus("Operation aborted"); InProgress = false; return; } try { bool extract = false; if (endswith) { extract = entry.NameLower.EndsWith(matchstr); } else { extract = entry.NameLower.Contains(matchstr); } var fentry = entry as RpfFileEntry; if (fentry == null) { extract = false; } if (extract) { UpdateExtractStatus(entry.Path); byte[] data = entry.File.ExtractFile(fentry); if (compress) { data = ResourceBuilder.Compress(data); } RpfResourceFileEntry rrfe = fentry as RpfResourceFileEntry; if (rrfe != null) //add resource header if this is a resource file. { data = ResourceBuilder.AddResourceHeader(rrfe, data); } if (data != null) { var finf = new FileInfo(entry.Name); string bpath = outputpath + "\\" + entry.Name.Substring(0, entry.Name.Length - finf.Extension.Length); string fpath = bpath + finf.Extension; int c = 1; while (File.Exists(fpath)) { fpath = bpath + "_" + c.ToString() + finf.Extension; c++; } File.WriteAllBytes(fpath, data); } else { throw new Exception("Couldn't extract data."); } } } catch (Exception ex) { string err = entry.Name + ": " + ex.Message; UpdateExtractStatus(err); errsb.AppendLine(err); } } } File.WriteAllText(outputpath + "\\_errors.txt", errsb.ToString()); UpdateExtractStatus("Complete."); InProgress = false; }); }
private void ExportButton_Click(object sender, EventArgs e) { if (InProgress) { return; } if (ScannedFiles.Count == 0) { MessageBox.Show("Please scan the GTAV folder first."); return; } TreeNode node = MainTreeView.SelectedNode; if (node == null) { MessageBox.Show("Please select a file to export."); return; } RpfFileEntry rfe = node.Tag as RpfFileEntry; if (rfe == null) { MessageBox.Show("Please select a file to export."); return; } SaveFileDialog.FileName = rfe.Name; if (SaveFileDialog.ShowDialog() == DialogResult.OK) { string fpath = SaveFileDialog.FileName; byte[] data = rfe.File.ExtractFile(rfe); if (ExportCompressCheckBox.Checked) { data = ResourceBuilder.Compress(data); } RpfResourceFileEntry rrfe = rfe as RpfResourceFileEntry; if (rrfe != null) //add resource header if this is a resource file. { data = ResourceBuilder.AddResourceHeader(rrfe, data); } if (data == null) { MessageBox.Show("Error extracting file! " + rfe.File.LastError); return; } try { File.WriteAllBytes(fpath, data); } catch (Exception ex) { MessageBox.Show("Error saving file! " + ex.ToString()); } } }
static void ExtractFilesInRPF(RpfFile rpf, string directoryOffset) { try { using (BinaryReader br = new BinaryReader(File.OpenRead(rpf.GetPhysicalFilePath()))) { foreach (RpfEntry entry in rpf.AllEntries) { if (!entry.NameLower.EndsWith(".rpf")) //don't try to extract rpf's, they will be done separately.. { if (entry is RpfBinaryFileEntry) { RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); if (data == null) { if (binentry.FileSize == 0) { Console.WriteLine("Invalid binary file size!"); } else { Console.WriteLine("data is null!"); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("binary meme -> " + entry.NameLower); File.WriteAllBytes(directoryOffset + entry.NameLower, data); } } else if (entry is RpfResourceFileEntry) { RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; byte[] data = rpf.ExtractFileResource(resentry, br); data = ResourceBuilder.Compress(data); //not completely ideal to recompress it... data = ResourceBuilder.AddResourceHeader(resentry, data); if (data == null) { if (resentry.FileSize == 0) { Console.WriteLine("{0} : Resource FileSize is 0.", entry.Path); } else { Console.WriteLine("{0} : {1}", entry.Path); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("Potential meme -> " + entry.NameLower); foreach (KeyValuePair <string, string[]> extentionMap in extensions) { foreach (string extention in extentionMap.Value) { if (entry.NameLower.EndsWith(extention)) { Console.WriteLine("Resource meme -> " + entry.NameLower); if (extention.Equals(".ytd")) { RpfFileEntry rpfent = entry as RpfFileEntry; byte[] ytddata = rpfent.File.ExtractFile(rpfent); bool needsResized = ytddata.Length > 5242880; // 5MB YtdFile ytd = new YtdFile(); ytd.Load(ytddata, rpfent); Dictionary <uint, Texture> Dicts = new Dictionary <uint, Texture>(); bool somethingResized = false; foreach (KeyValuePair <uint, Texture> texture in ytd.TextureDict.Dict) { if (texture.Value.Width > 1440 || needsResized && texture.Value.Width > 550) // Only resize if it is greater than 1440p or 550p if vehicle is oversized { byte[] dds = DDSIO.GetDDSFile(texture.Value); string fileName = $"{texture.Value.Name}.dds"; fileName = String.Concat(fileName.Where(c => !Char.IsWhiteSpace(c))); File.WriteAllBytes("./NConvert/" + fileName, dds); Process p = new Process(); p.StartInfo.FileName = @"./NConvert/nconvert.exe"; p.StartInfo.Arguments = @"-out dds -resize 50% 50% -overwrite ./NConvert/" + fileName; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.Start(); //Wait for the process to end. p.WaitForExit(); // Move file back File.Move("./NConvert/" + fileName, directoryOffset + fileName); byte[] resizedData = File.ReadAllBytes(directoryOffset + fileName); Texture resizedTex = DDSIO.GetTexture(resizedData); resizedTex.Name = texture.Value.Name; Console.WriteLine(resizedData.Length.ToString()); Dicts.Add(texture.Key, resizedTex); // Yeet the file, we are done with it File.Delete(directoryOffset + fileName); somethingResized = true; } else { Dicts.Add(texture.Key, texture.Value); } } // No point rebuilding the ytd when nothing was resized if (!somethingResized) { break; } TextureDictionary dic = new TextureDictionary(); dic.Textures = new ResourcePointerList64 <Texture>(); dic.TextureNameHashes = new ResourceSimpleList64_uint(); dic.Textures.data_items = Dicts.Values.ToArray(); dic.TextureNameHashes.data_items = Dicts.Keys.ToArray(); dic.BuildDict(); ytd.TextureDict = dic; byte[] resizedYtdData = ytd.Save(); File.WriteAllBytes(directoryOffset + entry.NameLower, resizedYtdData); Console.WriteLine("Done some ytd resize memes -> " + entry.NameLower); break; } File.WriteAllBytes(directoryOffset + entry.NameLower, data); break; } } } if (entry.NameLower.EndsWith(".ytd")) { latestModelName = entry.NameLower.Remove(entry.NameLower.Length - 4); } } } } else { // Write file first RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); File.WriteAllBytes(directoryOffset + entry.NameLower, data); RpfFile subRPF = new RpfFile(directoryOffset + entry.NameLower, directoryOffset + entry.NameLower); if (subRPF.ScanStructure(null, null)) { //recursive memes ExtractFilesInRPF(subRPF, directoryOffset); } //yeet File.Delete(directoryOffset + entry.NameLower); } } } } catch (Exception e) { Console.WriteLine("Exception memes!"); Console.WriteLine(e.Message); } }
// same as ResourceBuilder.Build but with support NG encrypting after compressing private static byte[] Build(ResourceFileBase fileBase, int version, string name, bool compress = true, bool encrypt = true) { fileBase.FilePagesInfo = new ResourcePagesInfo(); IList <IResourceBlock> systemBlocks; IList <IResourceBlock> graphicBlocks; ResourceBuilder.GetBlocks(fileBase, out systemBlocks, out graphicBlocks); RpfResourcePageFlags systemPageFlags; ResourceBuilder.AssignPositions(systemBlocks, 0x50000000, out systemPageFlags); RpfResourcePageFlags graphicsPageFlags; ResourceBuilder.AssignPositions(graphicBlocks, 0x60000000, out graphicsPageFlags); fileBase.FilePagesInfo.SystemPagesCount = (byte)systemPageFlags.Count; fileBase.FilePagesInfo.GraphicsPagesCount = (byte)graphicsPageFlags.Count; var systemStream = new MemoryStream(); var graphicsStream = new MemoryStream(); var resourceWriter = new ResourceDataWriter(systemStream, graphicsStream); resourceWriter.Position = 0x50000000; foreach (var block in systemBlocks) { resourceWriter.Position = block.FilePosition; var pos_before = resourceWriter.Position; block.Write(resourceWriter); var pos_after = resourceWriter.Position; if ((pos_after - pos_before) != block.BlockLength) { throw new Exception("error in system length"); } } resourceWriter.Position = 0x60000000; foreach (var block in graphicBlocks) { resourceWriter.Position = block.FilePosition; var pos_before = resourceWriter.Position; block.Write(resourceWriter); var pos_after = resourceWriter.Position; if ((pos_after - pos_before) != block.BlockLength) { throw new Exception("error in graphics length"); } } var sysDataSize = (int)systemPageFlags.Size; var sysData = new byte[sysDataSize]; systemStream.Flush(); systemStream.Position = 0; systemStream.Read(sysData, 0, (int)systemStream.Length); var gfxDataSize = (int)graphicsPageFlags.Size; var gfxData = new byte[gfxDataSize]; graphicsStream.Flush(); graphicsStream.Position = 0; graphicsStream.Read(gfxData, 0, (int)graphicsStream.Length); uint uv = (uint)version; uint sv = (uv >> 4) & 0xF; uint gv = (uv >> 0) & 0xF; uint sf = systemPageFlags.Value + (sv << 28); uint gf = graphicsPageFlags.Value + (gv << 28); var tdatasize = sysDataSize + gfxDataSize; var tdata = new byte[tdatasize]; Buffer.BlockCopy(sysData, 0, tdata, 0, sysDataSize); Buffer.BlockCopy(gfxData, 0, tdata, sysDataSize, gfxDataSize); var cdata = compress ? ResourceBuilder.Compress(tdata) : tdata; cdata = encrypt ? GTACrypto.EncryptNG(cdata, name, (uint)cdata.Length + 0x10) : cdata; var dataSize = 16 + cdata.Length; var data = new byte[dataSize]; byte[] h1 = BitConverter.GetBytes((uint)0x37435352); byte[] h2 = BitConverter.GetBytes((int)version); byte[] h3 = BitConverter.GetBytes(sf); byte[] h4 = BitConverter.GetBytes(gf); Buffer.BlockCopy(h1, 0, data, 0, 4); Buffer.BlockCopy(h2, 0, data, 4, 4); Buffer.BlockCopy(h3, 0, data, 8, 4); Buffer.BlockCopy(h4, 0, data, 12, 4); Buffer.BlockCopy(cdata, 0, data, 16, cdata.Length); return(data); }