public AudioPlayer(Resource resource, TabPage tab) { var soundData = (Sound)resource.Blocks[BlockType.DATA]; var stream = soundData.GetSoundStream(); waveOut = new WaveOutEvent(); if (soundData.Type == Sound.AudioFileType.WAV) { var rawSource = new WaveFileReader(stream); waveOut.Init(rawSource); } else if (soundData.Type == Sound.AudioFileType.MP3) { var rawSource = new Mp3FileReader(stream); waveOut.Init(rawSource); } playButton = new Button(); playButton.Text = "Play"; playButton.TabIndex = 1; playButton.Size = new Size(100, 25); playButton.Click += PlayButton_Click; tab.Controls.Add(playButton); }
// Armature constructor public Skeleton(Resource model) { Bones = new Bone[0]; Roots = new List<Bone>(); var modelData = (NTRO)model.Blocks[BlockType.DATA]; // Check if there is any skeleton data present at all if (!modelData.Output.Contains("m_modelSkeleton")) { Console.WriteLine("No skeleton data found."); } // Get the remap table and invert it for our construction method var remapTable = ((NTROArray)modelData.Output["m_remappingTable"]).ToArray<short>(); var invMapTable = new Dictionary<int, int>(); for (var i = 0; i < remapTable.Length; i++) { if (!invMapTable.ContainsKey(remapTable[i])) { invMapTable.Add(remapTable[i], i); } } // Construct the armature from the skeleton KV ConstructFromNTRO(((NTROValue<NTROStruct>)modelData.Output["m_modelSkeleton"]).Value, invMapTable); }
public ResourceStat(Resource resource, string info = "") { Type = resource.ResourceType; Version = resource.Version; Count = 1; Info = info; }
// Build animation from resource public Animation(Resource resource, NTROStruct decodeKey, Skeleton skeleton) { Name = string.Empty; Fps = 0; Frames = new Frame[0]; Skeleton = skeleton; var animationData = (NTRO)resource.Blocks[BlockType.DATA]; var animArray = (NTROArray)animationData.Output["m_animArray"]; if (animArray.Count == 0) { Console.WriteLine("Empty animation file found."); return; } var decoderArray = MakeDecoderArray((NTROArray)animationData.Output["m_decoderArray"]); var segmentArray = (NTROArray)animationData.Output["m_segmentArray"]; // Get the first animation description ConstructFromDesc(animArray.Get<NTROStruct>(0), decodeKey, decoderArray, segmentArray); }
private static void ProcessFile(string path, Dictionary<string, ResourceStat> stats, Dictionary<string, string> uniqueSpecialDependancies) { if (Path.GetExtension(path) == ".vpk") { ParseVPK(path); return; } lock (ConsoleWriterLock) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("[{0}/{1}] {2}", ++CurrentFile, TotalFiles, path); Console.ResetColor(); } var resource = new Resource(); try { var sw = Stopwatch.StartNew(); resource.Read(path); sw.Stop(); Console.WriteLine("Parsed in {0}ms", sw.ElapsedMilliseconds); string extension = Path.GetExtension(path); if (extension.EndsWith("_c", StringComparison.Ordinal)) { extension = extension.Substring(0, extension.Length - 2); } // Verify that extension matches resource type if (resource.ResourceType != ResourceType.Unknown) { var type = typeof(ResourceType).GetMember(resource.ResourceType.ToString()).First(); var attribute = "." + ((ExtensionAttribute)type.GetCustomAttributes(typeof(ExtensionAttribute), false).First()).Extension; if (attribute != extension) { throw new Exception(string.Format("Mismatched resource type and file extension. ({0} != expected {1})", attribute, extension)); } } if (Options.CollectStats) { var id = resource.ResourceType == ResourceType.Texture ? ((Texture)resource.Blocks[BlockType.DATA]).Format.ToString() : string.Format("{0}_{1}", resource.ResourceType, resource.Version); var info = resource.ResourceType == ResourceType.Texture ? id : ""; lock (stats) { if (stats.ContainsKey(id)) { stats[id].Count++; } else { stats.Add(id, new ResourceStat(resource, info)); } } if (resource.EditInfo != null && resource.EditInfo.Structs.ContainsKey(ResourceEditInfo.REDIStruct.SpecialDependencies)) { lock (uniqueSpecialDependancies) { foreach (var dep in ((ValveResourceFormat.Blocks.ResourceEditInfoStructs.SpecialDependencies)resource.EditInfo.Structs[ResourceEditInfo.REDIStruct.SpecialDependencies]).List) { uniqueSpecialDependancies[string.Format("{0} \"{1}\"", dep.CompilerIdentifier, dep.String)] = path; } } } } if (Options.OutputFile != null) { byte[] data; switch (resource.ResourceType) { case ResourceType.Panorama: data = ((Panorama)resource.Blocks[BlockType.DATA]).Data; break; case ResourceType.Sound: extension = "mp3"; data = ((Sound)resource.Blocks[BlockType.DATA]).GetSound(); break; case ResourceType.Texture: extension = "png"; var bitmap = ((Texture)resource.Blocks[BlockType.DATA]).GenerateBitmap(); using (var ms = new MemoryStream()) { bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); data = ms.ToArray(); } break; default: Console.WriteLine("-- (I don't know how to dump this resource type)"); return; } var filePath = Path.ChangeExtension(path, extension); if (Options.RecursiveSearch) { // I bet this is prone to breaking, is there a better way? filePath = filePath.Remove(0, Options.InputFile.TrimEnd(Path.DirectorySeparatorChar).Length + 1); } else { filePath = Path.GetFileName(filePath); } DumpFile(filePath, data); } } catch (Exception e) { lock (ConsoleWriterLock) { File.AppendAllText("exceptions.txt", string.Format("---------------\nFile: {0}\nException: {1}\n\n", path, e)); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine(e); Console.ResetColor(); } } //Console.WriteLine("\tInput Path: \"{0}\"", args[fi]); //Console.WriteLine("\tResource Name: \"{0}\"", "???"); //Console.WriteLine("\tID: {0:x16}", 0); lock (ConsoleWriterLock) { // Highlight resource type line if undetermined if (resource.ResourceType == ResourceType.Unknown) { Console.ForegroundColor = ConsoleColor.Cyan; } Console.WriteLine("\tResource Type: {0} [Version {1}] [Header Version: {2}]", resource.ResourceType, resource.Version, resource.HeaderVersion); Console.ResetColor(); } Console.WriteLine("\tFile Size: {0} bytes", resource.FileSize); Console.WriteLine(Environment.NewLine); if (resource.Blocks.ContainsKey(BlockType.RERL)) { Console.WriteLine("--- Resource External Refs: ---"); Console.WriteLine("\t{0,-16} {1,-48}", "Id:", "Resource Name:"); foreach (var res in resource.ExternalReferences.ResourceRefInfoList) { Console.WriteLine("\t{0:X16} {1,-48}", res.Id, res.Name); } } else { Console.WriteLine("--- (No External Resource References Found)"); } Console.WriteLine(Environment.NewLine); if (false) { // TODO: Resource Deferred Refs: } else { Console.WriteLine("--- (No Deferred Resource References Found)"); } Console.WriteLine(Environment.NewLine); Console.WriteLine("--- Resource Blocks: Count {0} ---", resource.Blocks.Count); foreach (var block in resource.Blocks) { Console.WriteLine("\t-- Block: {0,-4} Size: {1,-6} bytes [Offset: {2,6}]", block.Key, block.Value.Size, block.Value.Offset); } if (Options.PrintAllBlocks || !string.IsNullOrEmpty(Options.BlockToPrint)) { Console.WriteLine(Environment.NewLine); foreach (var block in resource.Blocks) { if(!Options.PrintAllBlocks && Options.BlockToPrint != block.Key.ToString()) { continue; } Console.WriteLine("--- Data for block \"{0}\" ---", block.Key); Console.WriteLine(block.Value); } } }
private static void DumpVPK(Package package, string type, string newType) { if (!package.Entries.ContainsKey(type)) { Console.WriteLine("There are no files of type \"{0}\".", type); return; } var entries = package.Entries[type]; foreach (var file in entries) { var filePath = string.Format("{0}.{1}", file.FileName, file.TypeName); if (!string.IsNullOrWhiteSpace(file.DirectoryName)) { filePath = Path.Combine(file.DirectoryName, filePath); } filePath = FixPathSlahes(filePath); Console.WriteLine("\t[archive index: {0:D3}] {1}", file.ArchiveIndex, filePath); byte[] output; package.ReadEntry(file, out output); if (type.EndsWith("_c", StringComparison.Ordinal)) { using (var resource = new Resource()) { using (var memory = new MemoryStream(output)) { resource.Read(memory); } output = ((Panorama)resource.Blocks[BlockType.DATA]).Data; } } if (Options.OutputFile != null) { if (type != newType) { filePath = Path.ChangeExtension(filePath, newType); } DumpFile(filePath, output); } } }
private TabPage ProcessFile(string fileName, byte[] input = null) { var tab = new TabPage(); if (fileName.EndsWith(".vpk", StringComparison.Ordinal)) { var package = new Package(); if (input != null) { package.SetFileName(fileName); package.Read(new MemoryStream(input)); } else { package.Read(fileName); } // create a TreeView with search capabilities, register its events, and add it to the tab var treeViewWithSearch = new GUI.Controls.TreeViewWithSearchResults(ImageList); treeViewWithSearch.Dock = DockStyle.Fill; treeViewWithSearch.InitializeTreeViewFromPackage("treeViewVpk", package); treeViewWithSearch.TreeNodeMouseDoubleClick += VPK_OpenFile; treeViewWithSearch.TreeNodeMouseClick += VPK_OnClick; treeViewWithSearch.ListViewItemDoubleClick += VPK_OpenFile; treeViewWithSearch.ListViewItemRightClick += VPK_OnClick; tab.Controls.Add(treeViewWithSearch); // since we're in a separate thread, invoke to update the UI this.Invoke((MethodInvoker)delegate { findToolStripButton.Enabled = true; }); } else { var resource = new Resource(); if (input != null) { resource.Read(new MemoryStream(input)); } else { resource.Read(fileName); } var resTabs = new TabControl(); resTabs.Dock = DockStyle.Fill; switch (resource.ResourceType) { case ResourceType.Texture: var tab2 = new TabPage("TEXTURE"); tab2.AutoScroll = true; try { var tex = (Texture)resource.Blocks[BlockType.DATA]; var control = new Forms.Texture(); control.BackColor = Color.Black; control.SetImage(tex.GenerateBitmap(), Path.GetFileNameWithoutExtension(fileName), tex.Width, tex.Height); tab2.Controls.Add(control); } catch (Exception e) { var control = new TextBox { Dock = DockStyle.Fill, Font = new Font(FontFamily.GenericMonospace, 8), Multiline = true, ReadOnly = true, Text = e.ToString() }; tab2.Controls.Add(control); } resTabs.TabPages.Add(tab2); break; case ResourceType.Panorama: if (((Panorama)resource.Blocks[BlockType.DATA]).Names.Count > 0) { var nameTab = new TabPage("PANORAMA NAMES"); var nameControl = new DataGridView(); nameControl.Dock = DockStyle.Fill; nameControl.AutoSize = true; nameControl.ReadOnly = true; nameControl.AllowUserToAddRows = false; nameControl.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; nameControl.DataSource = new BindingSource(new BindingList<Panorama.NameEntry>(((Panorama)resource.Blocks[BlockType.DATA]).Names), null); nameTab.Controls.Add(nameControl); resTabs.TabPages.Add(nameTab); } break; } foreach (var block in resource.Blocks) { if (block.Key == BlockType.RERL) { var externalRefsTab = new TabPage("External Refs"); var externalRefs = new DataGridView(); externalRefs.Dock = DockStyle.Fill; externalRefs.AutoGenerateColumns = true; externalRefs.AutoSize = true; externalRefs.ReadOnly = true; externalRefs.AllowUserToAddRows = false; externalRefs.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; externalRefs.DataSource = new BindingSource(new BindingList<ResourceExtRefList.ResourceReferenceInfo>(resource.ExternalReferences.ResourceRefInfoList), null); externalRefsTab.Controls.Add(externalRefs); resTabs.TabPages.Add(externalRefsTab); continue; } if (block.Key == BlockType.NTRO) { if (((ResourceIntrospectionManifest)block.Value).ReferencedStructs.Count > 0) { var externalRefsTab = new TabPage("Introspection Manifest: Structs"); var externalRefs = new DataGridView(); externalRefs.Dock = DockStyle.Fill; externalRefs.AutoGenerateColumns = true; externalRefs.AutoSize = true; externalRefs.ReadOnly = true; externalRefs.AllowUserToAddRows = false; externalRefs.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; externalRefs.DataSource = new BindingSource(new BindingList<ResourceIntrospectionManifest.ResourceDiskStruct>(((ResourceIntrospectionManifest)block.Value).ReferencedStructs), null); externalRefsTab.Controls.Add(externalRefs); resTabs.TabPages.Add(externalRefsTab); } if (((ResourceIntrospectionManifest)block.Value).ReferencedEnums.Count > 0) { var externalRefsTab = new TabPage("Introspection Manifest: Enums"); var externalRefs2 = new DataGridView(); externalRefs2.Dock = DockStyle.Fill; externalRefs2.AutoGenerateColumns = true; externalRefs2.AutoSize = true; externalRefs2.ReadOnly = true; externalRefs2.AllowUserToAddRows = false; externalRefs2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; externalRefs2.DataSource = new BindingSource(new BindingList<ResourceIntrospectionManifest.ResourceDiskEnum>(((ResourceIntrospectionManifest)block.Value).ReferencedEnums), null); externalRefsTab.Controls.Add(externalRefs2); resTabs.TabPages.Add(externalRefsTab); } //continue; } var tab2 = new TabPage(block.Key.ToString()); var control = new TextBox(); control.Font = new Font(FontFamily.GenericMonospace, control.Font.Size); try { control.Text = block.Value.ToString().Replace("\r", ""); //Prevent copy+paste with double new line control.Text = block.Value.ToString().Replace("\n", Environment.NewLine); //make sure panorama is new lines } catch (Exception e) { control.Text = e.ToString(); } control.Dock = DockStyle.Fill; control.Multiline = true; control.ReadOnly = true; control.ScrollBars = ScrollBars.Both; tab2.Controls.Add(control); resTabs.TabPages.Add(tab2); } tab.Controls.Add(resTabs); } return tab; }
public AnimationGroupLoader(Resource resource, string filename, Skeleton skeleton) { data = (NTRO)resource.Blocks[BlockType.DATA]; LoadAnimationGroup(filename, skeleton); }
public TabPage Create(VrfGuiContext vrfGuiContext, byte[] input) { var tab = new TabPage(); var resource = new ValveResourceFormat.Resource(); if (input != null) { resource.Read(new MemoryStream(input)); } else { resource.Read(vrfGuiContext.FileName); } var resTabs = new TabControl { Dock = DockStyle.Fill, }; switch (resource.ResourceType) { case ResourceType.Texture: var tab2 = new TabPage("TEXTURE") { AutoScroll = true, }; try { var tex = (Texture)resource.DataBlock; var control = new Forms.Texture { BackColor = Color.Black, }; control.SetImage(tex.GenerateBitmap().ToBitmap(), Path.GetFileNameWithoutExtension(vrfGuiContext.FileName), tex.ActualWidth, tex.ActualHeight); tab2.Controls.Add(control); Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as an image", vrfGuiContext.FileName, new ExportData { Resource = resource }); } catch (Exception e) { var control = new TextBox { Dock = DockStyle.Fill, Font = new Font(FontFamily.GenericMonospace, 8), Multiline = true, ReadOnly = true, Text = e.ToString(), }; tab2.Controls.Add(control); } resTabs.TabPages.Add(tab2); break; case ResourceType.Panorama: if (((Panorama)resource.DataBlock).Names.Count > 0) { var nameTab = new TabPage("PANORAMA NAMES"); var nameControl = new DataGridView { Dock = DockStyle.Fill, AutoSize = true, ReadOnly = true, AllowUserToAddRows = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, DataSource = new BindingSource( new BindingList <Panorama.NameEntry>(((Panorama)resource.DataBlock).Names), null), }; nameTab.Controls.Add(nameControl); resTabs.TabPages.Add(nameTab); } break; case ResourceType.PanoramaLayout: Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as XML", vrfGuiContext.FileName, new ExportData { Resource = resource }); break; case ResourceType.PanoramaScript: Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as JS", vrfGuiContext.FileName, new ExportData { Resource = resource }); break; case ResourceType.PanoramaStyle: Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as CSS", vrfGuiContext.FileName, new ExportData { Resource = resource }); break; case ResourceType.Particle: var viewerControl = new GLParticleViewer(vrfGuiContext); viewerControl.Load += (_, __) => { var particleSystem = (ParticleSystem)resource.DataBlock; var particleRenderer = new ParticleRenderer.ParticleRenderer(particleSystem, vrfGuiContext); viewerControl.AddRenderer(particleRenderer); }; var particleRendererTab = new TabPage("PARTICLE"); particleRendererTab.Controls.Add(viewerControl.Control); resTabs.TabPages.Add(particleRendererTab); break; case ResourceType.Sound: var soundTab = new TabPage("SOUND"); var ap = new AudioPlayer(resource, soundTab); resTabs.TabPages.Add(soundTab); Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as {((Sound) resource.DataBlock).SoundType}", vrfGuiContext.FileName, new ExportData { Resource = resource }); break; case ResourceType.World: var worldmeshTab = new TabPage("MAP"); worldmeshTab.Controls.Add( new GLWorldViewer(vrfGuiContext, (World)resource.DataBlock).ViewerControl); resTabs.TabPages.Add(worldmeshTab); break; case ResourceType.WorldNode: var nodemeshTab = new TabPage("WORLD NODE"); nodemeshTab.Controls.Add(new GLWorldViewer(vrfGuiContext, (WorldNode)resource.DataBlock) .ViewerControl); resTabs.TabPages.Add(nodemeshTab); break; case ResourceType.Model: Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as glTF", vrfGuiContext.FileName, new ExportData { Resource = resource, VrfGuiContext = vrfGuiContext }); var modelRendererTab = new TabPage("MODEL"); modelRendererTab.Controls.Add(new GLModelViewer(vrfGuiContext, (Model)resource.DataBlock) .ViewerControl); resTabs.TabPages.Add(modelRendererTab); break; case ResourceType.Mesh: if (!resource.ContainsBlockType(BlockType.VBIB)) { Console.WriteLine("Old style model, no VBIB!"); break; } Program.MainForm.Invoke(new ExportDel(AddToExport), resTabs, $"Export {Path.GetFileName(vrfGuiContext.FileName)} as glTF", vrfGuiContext.FileName, new ExportData { Resource = resource, VrfGuiContext = vrfGuiContext }); var meshRendererTab = new TabPage("MESH"); meshRendererTab.Controls.Add(new GLModelViewer(vrfGuiContext, new Mesh(resource)).ViewerControl); resTabs.TabPages.Add(meshRendererTab); break; case ResourceType.Material: var materialViewerControl = new GLMaterialViewer(); materialViewerControl.Load += (_, __) => { var material = vrfGuiContext.MaterialLoader.LoadMaterial(resource); var materialRenderer = new MaterialRenderer(material); materialViewerControl.AddRenderer(materialRenderer); }; var materialRendererTab = new TabPage("MATERIAL"); materialRendererTab.Controls.Add(materialViewerControl.Control); resTabs.TabPages.Add(materialRendererTab); break; } foreach (var block in resource.Blocks) { if (block.Type == BlockType.RERL) { var externalRefsTab = new TabPage("External Refs"); var externalRefs = new DataGridView { Dock = DockStyle.Fill, AutoGenerateColumns = true, AutoSize = true, ReadOnly = true, AllowUserToAddRows = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, DataSource = new BindingSource( new BindingList <ResourceExtRefList.ResourceReferenceInfo>(resource.ExternalReferences .ResourceRefInfoList), null), }; externalRefsTab.Controls.Add(externalRefs); resTabs.TabPages.Add(externalRefsTab); continue; } if (block.Type == BlockType.NTRO) { if (((ResourceIntrospectionManifest)block).ReferencedStructs.Count > 0) { var externalRefsTab = new TabPage("Introspection Manifest: Structs"); var externalRefs = new DataGridView { Dock = DockStyle.Fill, AutoGenerateColumns = true, AutoSize = true, ReadOnly = true, AllowUserToAddRows = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, DataSource = new BindingSource( new BindingList <ResourceIntrospectionManifest.ResourceDiskStruct>( ((ResourceIntrospectionManifest)block).ReferencedStructs), null), }; externalRefsTab.Controls.Add(externalRefs); resTabs.TabPages.Add(externalRefsTab); } if (((ResourceIntrospectionManifest)block).ReferencedEnums.Count > 0) { var externalRefsTab = new TabPage("Introspection Manifest: Enums"); var externalRefs2 = new DataGridView { Dock = DockStyle.Fill, AutoGenerateColumns = true, AutoSize = true, ReadOnly = true, AllowUserToAddRows = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, DataSource = new BindingSource( new BindingList <ResourceIntrospectionManifest.ResourceDiskEnum>( ((ResourceIntrospectionManifest)block).ReferencedEnums), null), }; externalRefsTab.Controls.Add(externalRefs2); resTabs.TabPages.Add(externalRefsTab); } //continue; } var tab2 = new TabPage(block.Type.ToString()); try { var control = new TextBox(); control.Font = new Font(FontFamily.GenericMonospace, control.Font.Size); if (block.Type == BlockType.DATA) { switch (resource.ResourceType) { case ResourceType.Sound: control.Text = Utils.Utils.NormalizeLineEndings(((Sound)block).ToString()); break; case ResourceType.Particle: case ResourceType.Mesh: if (block is BinaryKV3 blockKeyvalues) { //Wrap it around a KV3File object to get the header. control.Text = Utils.Utils.NormalizeLineEndings(blockKeyvalues.GetKV3File().ToString()); } else if (block is NTRO blockNTRO) { control.Text = Utils.Utils.NormalizeLineEndings(blockNTRO.ToString()); } break; default: control.Text = Utils.Utils.NormalizeLineEndings(block.ToString()); break; } } else { control.Text = Utils.Utils.NormalizeLineEndings(block.ToString()); } control.Dock = DockStyle.Fill; control.Multiline = true; control.ReadOnly = true; control.ScrollBars = ScrollBars.Both; tab2.Controls.Add(control); } catch (Exception e) { Console.WriteLine(e); var bv = new System.ComponentModel.Design.ByteViewer(); bv.Dock = DockStyle.Fill; tab2.Controls.Add(bv); Program.MainForm.Invoke((MethodInvoker)(() => { resource.Reader.BaseStream.Position = block.Offset; bv.SetBytes(resource.Reader.ReadBytes((int)block.Size)); })); } resTabs.TabPages.Add(tab2); } if (resource.ResourceType == ResourceType.PanoramaLayout || resource.ResourceType == ResourceType.PanoramaScript || resource.ResourceType == ResourceType.PanoramaStyle || resource.ResourceType == ResourceType.SoundEventScript || resource.ResourceType == ResourceType.SoundStackScript || resource.ResourceType == ResourceType.EntityLump) { resTabs.SelectTab(resTabs.TabCount - 1); } tab.Controls.Add(resTabs); return(tab); }
public abstract void Read(BinaryReader reader, Resource resource);
public static Resource LoadFileByAnyMeansNecessary(string file, string currentFullPath, Package currentPackage) { Resource resource; // TODO: Might conflict where same file name is available in different paths if (CachedResources.TryGetValue(file, out resource) && resource.Reader != null) { return resource; } resource = new Resource(); var entry = currentPackage?.FindEntry(file); if (entry != null) { byte[] output; currentPackage.ReadEntry(entry, out output); resource.Read(new MemoryStream(output)); CachedResources[file] = resource; return resource; } var paths = Settings.GameSearchPaths.ToList(); var packages = new List<Package>(); foreach (var searchPath in paths.Where(searchPath => searchPath.EndsWith(".vpk")).ToList()) { paths.Remove(searchPath); Package package; if (!CachedPackages.TryGetValue(searchPath, out package)) { Console.WriteLine("Preloading vpk {0}", searchPath); package = new Package(); package.Read(searchPath); CachedPackages[searchPath] = package; } packages.Add(package); } foreach (var package in packages) { entry = package?.FindEntry(file); if (entry != null) { byte[] output; package.ReadEntry(entry, out output); resource.Read(new MemoryStream(output)); CachedResources[file] = resource; return resource; } } var path = FindResourcePath(paths, file, currentFullPath); if (path == null) { return null; } resource.Read(path); CachedResources[file] = resource; return resource; }
public WorldNode(Resource resource) { Resource = resource; }
public World(Resource resource) { Resource = resource; }
internal static List <PackageEntry> RecoverDeletedFiles(SteamDatabase.ValvePak.Package package) { var allEntries = package.Entries .SelectMany(file => file.Value) .OrderBy(file => file.Offset) .GroupBy(file => file.ArchiveIndex) .OrderBy(x => x.Key) .ToDictionary(x => x.Key, x => x.ToList()); var hiddenIndex = 0; var totalSlackSize = 0u; var hiddenFiles = new List <PackageEntry>(); // TODO: Skip non-chunked vpks? foreach (var(archiveIndex, entries) in allEntries) { var nextOffset = 0u; foreach (var entry in entries) { if (entry.Length == 0) { continue; } var offset = nextOffset; nextOffset = entry.Offset + entry.Length; totalSlackSize += entry.Offset - offset; var scan = true; while (scan) { scan = false; if (offset == entry.Offset) { break; } offset = (offset + 16 - 1) & ~(16u - 1); // TODO: Validate this gap var length = entry.Offset - offset; if (length <= 16) { // TODO: Verify what this gap is, seems to be null bytes break; } hiddenIndex++; var newEntry = new PackageEntry { FileName = $"Archive {archiveIndex} File {hiddenIndex}", DirectoryName = DELETED_FILES_FOLDER, TypeName = " ", CRC32 = 0, SmallData = Array.Empty <byte>(), ArchiveIndex = archiveIndex, Offset = offset, Length = length, }; package.ReadEntry(newEntry, out var bytes, validateCrc: false); var stream = new MemoryStream(bytes); try { var resource = new ValveResourceFormat.Resource(); resource.Read(stream, verifyFileSize: false); var fileSize = resource.FullFileSize; if (fileSize != length) { if (fileSize > length) { throw new Exception("Resource filesize is bigger than the gap length we found"); } newEntry.Length = fileSize; offset += fileSize; scan = true; } if (resource.ResourceType != ResourceType.Unknown) { var type = typeof(ResourceType).GetMember(resource.ResourceType.ToString())[0]; newEntry.TypeName = ((ExtensionAttribute)type.GetCustomAttributes(typeof(ExtensionAttribute), false)[0]).Extension; newEntry.TypeName += "_c"; } newEntry.DirectoryName += "/" + resource.ResourceType; } catch (Exception ex) { Console.WriteLine($"File {hiddenIndex} - {ex.Message}"); newEntry.FileName += $" ({length} bytes)"; } if (!package.Entries.TryGetValue(newEntry.TypeName, out var typeEntries)) { typeEntries = new List <PackageEntry>(); package.Entries.Add(newEntry.TypeName, typeEntries); } typeEntries.Add(newEntry); hiddenFiles.Add(newEntry); } } // TODO: Check nextOffset against archive file size } Console.WriteLine($"Found {hiddenIndex} deleted files totaling {totalSlackSize.ToFileSizeString()}"); // TODO: Check for completely unused vpk chunk files return(hiddenFiles); }
public Model(Resource resource) { Resource = resource; }