Represents a Valve resource.
Inheritance: IDisposable
        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);
 }
Example #9
0
        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);
        }
Example #10
0
 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;
 }