private void SelectFile(RpfEntry entry, int offset, int length) { SelectedEntry = entry; SelectedOffset = offset; SelectedLength = length; RpfFileEntry rfe = entry as RpfFileEntry; if (rfe == null) { RpfDirectoryEntry rde = entry as RpfDirectoryEntry; if (rde != null) { FileInfoLabel.Text = rde.Path + " (Directory)"; DataTextBox.Text = "[Please select a data file]"; } else { FileInfoLabel.Text = "[Nothing selected]"; DataTextBox.Text = "[Please select a data file]"; } ShowTextures(null); return; } Cursor = Cursors.WaitCursor; string typestr = "Resource"; if (rfe is RpfBinaryFileEntry) { typestr = "Binary"; } byte[] data = rfe.File.ExtractFile(rfe); int datalen = (data != null) ? data.Length : 0; FileInfoLabel.Text = rfe.Path + " (" + typestr + " file) - " + TextUtil.GetBytesReadable(datalen); if (ShowLargeFileContentsCheckBox.Checked || (datalen < 524287)) //512K { DisplayFileContentsText(rfe, data, length, offset); } else { DataTextBox.Text = "[Filesize >512KB. Select the Show large files option to view its contents]"; } bool istexdict = false; if (rfe.NameLower.EndsWith(".ymap")) { YmapFile ymap = new YmapFile(rfe); ymap.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ymap; } else if (rfe.NameLower.EndsWith(".ytyp")) { YtypFile ytyp = new YtypFile(); ytyp.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ytyp; } else if (rfe.NameLower.EndsWith(".ymf")) { YmfFile ymf = new YmfFile(); ymf.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ymf; } else if (rfe.NameLower.EndsWith(".ymt")) { YmtFile ymt = new YmtFile(); ymt.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ymt; } else if (rfe.NameLower.EndsWith(".ybn")) { YbnFile ybn = new YbnFile(); ybn.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ybn; } else if (rfe.NameLower.EndsWith(".fxc")) { FxcFile fxc = new FxcFile(); fxc.Load(data, rfe); DetailsPropertyGrid.SelectedObject = fxc; } else if (rfe.NameLower.EndsWith(".yft")) { YftFile yft = new YftFile(); yft.Load(data, rfe); DetailsPropertyGrid.SelectedObject = yft; if ((yft.Fragment != null) && (yft.Fragment.Drawable != null) && (yft.Fragment.Drawable.ShaderGroup != null) && (yft.Fragment.Drawable.ShaderGroup.TextureDictionary != null)) { ShowTextures(yft.Fragment.Drawable.ShaderGroup.TextureDictionary); istexdict = true; } } else if (rfe.NameLower.EndsWith(".ydr")) { YdrFile ydr = new YdrFile(); ydr.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ydr; if ((ydr.Drawable != null) && (ydr.Drawable.ShaderGroup != null) && (ydr.Drawable.ShaderGroup.TextureDictionary != null)) { ShowTextures(ydr.Drawable.ShaderGroup.TextureDictionary); istexdict = true; } } else if (rfe.NameLower.EndsWith(".ydd")) { YddFile ydd = new YddFile(); ydd.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ydd; //todo: show embedded texdicts in ydd's? is this possible? } else if (rfe.NameLower.EndsWith(".ytd")) { YtdFile ytd = new YtdFile(); ytd.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ytd; ShowTextures(ytd.TextureDict); istexdict = true; } else if (rfe.NameLower.EndsWith(".ycd")) { YcdFile ycd = new YcdFile(); ycd.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ycd; } else if (rfe.NameLower.EndsWith(".ynd")) { YndFile ynd = new YndFile(); ynd.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ynd; } else if (rfe.NameLower.EndsWith(".ynv")) { YnvFile ynv = new YnvFile(); ynv.Load(data, rfe); DetailsPropertyGrid.SelectedObject = ynv; } else if (rfe.NameLower.EndsWith("_cache_y.dat")) { CacheDatFile cdf = new CacheDatFile(); cdf.Load(data, rfe); DetailsPropertyGrid.SelectedObject = cdf; } else if (rfe.NameLower.EndsWith(".rel")) { RelFile rel = new RelFile(rfe); rel.Load(data, rfe); DetailsPropertyGrid.SelectedObject = rel; } else if (rfe.NameLower.EndsWith(".gxt2")) { Gxt2File gxt2 = new Gxt2File(); gxt2.Load(data, rfe); DetailsPropertyGrid.SelectedObject = gxt2; } else if (rfe.NameLower.EndsWith(".pso")) { JPsoFile pso = new JPsoFile(); pso.Load(data, rfe); DetailsPropertyGrid.SelectedObject = pso; } else { DetailsPropertyGrid.SelectedObject = null; } if (!istexdict) { ShowTextures(null); } Cursor = Cursors.Default; }
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); } }